In this blog post, I’m going to describe how LightSwitch developers can programmatically access the security data contained in a LightSwitch application. Having access to this data is useful for any number of reasons. For example, you can use this API to programmatically add new users to the application.
This data is exposed in code as entities, just like with your own custom data. So it’s an easy and familiar API to work with. And it’s available from both client or server code.
First I’d like to describe the security data model. Here’s a UML diagram describing the service, entities, and supporting classes:
This is the data service class that provides access to the security entities as well as a few security-related methods. It is available from your DataWorkspace object via its SecurityData property.
SecurityData is a LightSwitch data service and behaves in the same way as the data service that gets generated when you add a data source to LightSwitch. It exposes the same type of query and save methods. It just operates on the built-in security entities instead of your entities.
Some important notes regarding having access to your application’s security data:
In a running LightSwitch application, users which do not have the SecurityAdministration permission are only allowed to read security data; they cannot insert, update, or delete it. In addition, those users are only able to read security data that is relevant to themselves. So if a user named Bob, who does not have the SecurityAdministration permission, queries the UserRegistrations entity set, he will only see a UserRegistration with the name of Bob. He will not be able to see that there also exists a UserRegistration with the name of Kim since he is not logged in as Kim. Similarly with roles, if Bob queries the Roles entity set, he can see that a role named SalesPerson exists because he is assigned to that role. But he cannot see that a role named Manager exists because he is not assigned to that role.
Users which do have the SecurityAdministration permission are not restricted in their access to security data. They are able to read all stored security data and have the ability to modify it.
In addition to entity sets, SecurityData also exposes a few useful methods:
This method allows a user to change their own password. They need to supply their old password in order to do so. If the oldPassword parameter doesn’t match the current password or the new password doesn’t conform to the password requirements, an exception will be thrown. This method is only relevant when Forms authentication is being used. This method can be called by any user; they do not require the SecurityAdministration permission.
This method validates and resolve a Windows account name into a normalized value and retrieve the full name (display name) of that user. As an example, let’s say that you passed “firstname.lastname@example.org” as the parameter to this operation, it would return back a WindowsUserInfo object with the FullName property set to “Kim Abercrombie” and the NormalizedUserName property set to “contoso\kim”. If the service is unable to resolve the username parameter to a known account, an exception will be thrown. This method is only relevant when Windows authentication is being used. This method can only be called by users that have the SecurityAdministration permission.
This method checks whether the supplied password meets the password requirements of the application. This happens automatically when attempting to add a new user or updating their password but this method allows the caller to preemptively check the password which can be useful for validation UI purposes. This method is only relevant when Forms authentication is being used. This method can only be called by users that have the SecurityAdministration permission.
The UserRegistration entity represents a user that has access to the application. (In VS 11, it can also represent an Active Directory security group when Windows authentication is being used). When using Forms authentication, all the UserRegistration properties (UserName, FullName, Password) are required. When using Windows authentication, only the UserName property is required; FullName is populated dynamically based on the UserName and Password is irrelevant.
Here is some example code using the UserRegistration entity:
The Role entity represents a grouping of users with common characteristics. Examples of roles in an application include “Sales Person” and “Manager”. You can then configure your application security around these roles.
Here is some example code using the Role entity:
The RoleAssignment entity represents a mapping between a Role and a UserRegistration. It is how you define that a user belongs to a role.
Here is some example code using the RoleAssignment entity:
The Permission entity represents an action that a logged in user is permitted to do within the application. Examples of permissions in an application include “CanRejectSalesOrder” and “CanUpdateInventory”. Permissions are different than the rest of the security data because they are read-only. The permissions that are available map to the permissions that were defined within the Access Control tab of the application properties of a LightSwitch project:
Here is some example code using the Permission entity:
The RolePermission entity represents a mapping between a Role and a Permission. It is how you define that a permission is assigned to a role.
Here is some example code using the RolePermission entity:
Using the SecurityData service and the entities it exposes, you can accomplish all kinds of interesting scenarios that require dynamic management of your application’s security data. I hope you’ve found this blog post helpful in your work. Happy coding.