I'm trying to secure a WCF service using windows accounts. The service should run on many systems with different languages. How can i set a PrincipalPermission that has language independent role names?
I found ugly workarounds like this one.
[PrincipalPermission(SecurityAction.Demand, Role = "Builtin\\Administrators")] // English
[PrincipalPermission(SecurityAction.Demand, Role = "Vordefiniert\\Administratoren")] // German
public string HelloWorld()
{
return "Hello";
}
I don't think this is a good solution, is there any way to make this language independent? Is there a way to use the account SID instead of a string?
You could roll your own permission attribute which handles the translation:
[Serializable, AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true, Inherited = false), ComVisible(true)]
public sealed class AdministratorPrincipalPermissionAttribute : CodeAccessSecurityAttribute
{
public AdministratorPrincipalPermissionAttribute(SecurityAction action) : base(action)
{ }
public override IPermission CreatePermission()
{
var identifier = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
var role = identifier.Translate(typeof(NTAccount)).Value;
return new PrincipalPermission(null, role);
}
}
Please note that this would require some extra deployment effort (gac, caspol etc.).
One more try: Have a look at http://msdn.microsoft.com/en-us/library/system.security.principal.windowsbuiltinrole.aspx .... and go to the sample . There you can use the BuiltIn enumeration members to get the correctly spelled group name (via the API)... then it should be language neutral.
HTH,
Thomas
You may use the imperative version and dynamically convert a language neutral form (e.g. SID) to the localized form (may be through SecurityIdentifier.Translate).
Well known SIDs are listed in KB 243330.
Hmmmm, I would not use a group name directly in my code (hard coded). Try to abstract it to a role like "HelloWorldAdmin" and have a role configured in the app.config. This one should be mapped to a user group. This would allow your users / admins to select a group and map it to the role (e.g. in case that the application admins are not you AD admins).
Have a look at http://msdn.microsoft.com/en-us/library/ms998314.aspx. HTH.
Are you absolutely sure that on a German-language system, the "BUILTIN\Administrators" will not work? I would have imagined even then, these basic group names should be valid. Yes, in your admin tools, it will show "Vordefiniert\ADministratoren" - but I would be surprised if the PrincipalPermission attribute would be language-dependant.
MArc
Related
We are currently working on a smaller ASP.NET MVC 5 application using ASP.NET Identity. It allows us to maintain different projects and their tasks. We recently implemented basic authentication so we are able to register a user with our site and login with them.
We want to be able to manage access rights on project basis so we can say for every single user that he has read, write, admin or no permissions for a specified project.
My first thought was that we can create a simple new table in our database which stores the user rights. But I feel that there might be a built-in way to achieve this with ASP.NET Identity.
So my question really is, which path we should follow - manually building a new table to administer the rights or use something built-in provided by ASP.NET Identity.
use something built-in provided by ASP.NET Identity
The only things you could use there are claims or roles and both are not built for what you want IMO.
So I would go with your own table which links the project to a user, e.g.:
public class UserProjectRights
{
[Key]
public ApplicationUser User { get; set; }
[Key]
public Project Project { get; set; }
public AccessRight Right { get; set; }
}
Then whenever you do some actions where a specific right is required you need to check for that. There are several ways how you could do that. In my app I created "access right check extensions" like the following (I have defined a common interface for all "access right entities" to "reuse" that method):
public static bool? CanView(this ApplicationUser user, Project project)
{
var userRight = project.Rights.FirstOrDefault(r => r.User == user);
return userRight == null ? (bool?)null : userRight.Right.HasFlag(AccessRight.View);
}
assuming AccessRight is an enum like:
[Flags]
public enum AccessRight
{
View,
Edit,
Admin
}
Then you can do something like the following in your logic:
if (user.CanView(project) == true)
{
// show project
}
I used bool? so I can implement different "default behaviour" as I know if null is returned there is no right defined.
I was wondering if anyone would be able to help me with the following?
I need some more complicated rules for authorisation in a webapp than just role, which I have working fine. Something along the lines of "Allow all Admins. Allow Buyers, provided they have the correct department ID and are allowed to see this customer's credentials".
I am using a custom identity and custom principal to store information such as whether a user is allowed to see all clients or which individual clients they may see. This information is retrieved from a database and added upon creation of the identity/principal.
I have created a custom permission that extends IPermission, ISecurityEncodable. Within this, I have modified the Demand() function to the following:
public void Demand()
{
this._identity = (UserIdentity)Thread.CurrentPrincipal.Identity;
if (Thread.CurrentPrincipal.IsInRole("Admin")) { }
else if ((Thread.CurrentPrincipal.IsInRole("Buyer")) &&
(this._identity.CanViewAllClients) &&
(this._identity.IsInDept(this._departmentID)) ) { }
else if ((Thread.CurrentPrincipal.IsInRole("Buyer")) &&
(this._identity.CanViewClient(this._requestedClient)) &&
(this._identity.IsInDept(this._departmentID)) ) { }
else { throw new SecurityException("Custom Permission Denied"); }
}
I then call this when I wish to authorise by using
CustomPermission custperm = new CustomPermission(requestedClient, reqClientDept);
custperm.Demand();
This works fine, but seems a messy, hacky way to do things. Especially since it would be nice to use my security roles as an attribute e.g.
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public class...
Perhaps there is a way to call [CustomPrincipalPermission(SecurityAction.Demand, Authorised = true)] with a custom IsAuthorised check? Is this possible? What would need to be implemented?
I apologise if there is a simple solution that I've missed online, but rest assured I have been checking for days now.
It seems like what you want is a declarative rather than a programmatic demand. In order to do so, you'll need to create a CustomPermissionAttribute based on your CustomPermission.
There's an example of a declarative demand of a custom permission here and details of creating a custom permission attribute here.
I'm implementing role based security using Microsoft's membership and role provider.
The theoretical problem I'm having is that you implement a specific role on a method such as:
[PrincipalPermissionAttribute(SecurityAction.Demand, Role="Supervisor")]
private void someMethod() {}
What if at some point down the road, I don't want Supervisors to access someMethod() anymore?
Wouldn't I have to change the source code to make that change? Am I missing something?
It seems there has to be some way to abstract the relationship between the supervisors role and the method so I can create a way in the application to change this coupling of role permission to method.
Any insight or direction would be appreciated. Thank you.
If you use the declarative approach, then yes - if you suddenly don't want members of the Supervisor to be able to call your method, you need to change your source code for that.
You can, however, also do all of this in code, programmatically:
private void someMethod()
{
WindowsPrincipal currentUser = (Thread.CurrentPrincipal as WindowsPrincipal);
if (currentUser != null)
{
if (currentUser.IsInRole("Supervisor"))
{
// do something here
}
}
}
You can always get the current Windows principal your Winforms app is running under, and then you can call the IsInRole method to check whether or not a given user is in a given role. Of course, you can also make all of this configurable, e.g. read the required role from a config file, and if you want to allow everyone in, you just simply change the role to be Users or something
PrincipalPermissionAttribute does not tend to be used in many applications I've worked on for the reason you've touched upon; the attribute applies a policy which can only be altered by a code change.
The alternative is to use the PrincipalPermission class directly. All security attributes resolve to similarly named classes and method calls at run time. In the case of your attribute, the following code is executed:
PrincipalPermission permission = new PrincipalPermission(null, "Supervisor");
permission.Demand(); // Throws SecurityException if user is not in the role.
If you use the permission classes directly, you gain more control over how your permissions are formed. You could have a database which you query to get a list of roles and perform a demand for them like this:
private void someMethod()
{
IEnumerable<string> roles = GetRolesForMethod("someMethod");
PrincipalPermission permission = null;
foreach(string role in roles)
{
if(permission == null)
{
permission = new PrincipalPermission(null, role);
}
else
{
permission = permission.Union(
new PrincipalPermission(null, role);
);
}
}
if(permission != null)
{
permission.Demand();
}
}
In my current asp.net mvc project a user should be able to log in. When logged in a set of preferences can optionally be set. Some of those preferences are general (e.g. prefered site language etc), but some are specific to this project only (pre-defined query filtering etc).
Since these preferences are present in a lot of different places of my site I would define this as cross-concern. Preferably I would have an attribute handle this rather than every action on it's own.
How can I design such an attribute that is generic enough to re-use in future projects yet knows enough about the current project to use all the project specific settings too?
--EDIT--
Getting and setting the preferences is not the problem. I connected a UserSettings class to the asp.net profile provider.
My problem is how to pull this cross concern out of my controllers into an attribute.
independently if you are storing that preferences in a text file, xml or database, wouldn't be easier to create a class (for example Utility.UserPreferences) that will load those preferences from the user and store them in a Session variable, then using an enum call them to retrieve / update
namespace Utility
{
public class UserPreferences
{
public UserPreferences(int userID)
{
// Load Preferences from text file, xml file or DB
string loadedPreferences = "us|20|yes|no";
HttpContext.Current.Session["userPreferences"] = loadedPreferences;
}
public void Savepreferences(string[] pref, int userID)
{
// Save preferences for that user
}
public static string GetPreferences(PreferencesType type)
{
string[] pref = HttpContext.Current.Session["userPreferences"].ToString().Split('|');
switch (type)
{
case PreferencesType.Language: return pref[0];
case PreferencesType.ShowHowManyResults: return pref[1];
case PreferencesType.ShowNavigation: return pref[2];
case PreferencesType.GetEmailAlerts: return pref[3];
}
}
public enum PreferencesType
{
Language, ShowHowManyResults, ShowNavigation, GetEmailAlerts
}
}
}
then ...
// Login sucessfully...
Utility.UserPreferences pref = new Utility.UserPreferences(CurrentUser.ID);
// to retrieve a preference
string language = Utility.UserPreferences.GetPreferences(
Utility.UserPreferences.PreferencesType.Language,
CurrentUser.ID);
it's just an idea... the way I would do it... it's simple and it's project(s) wide, cause you just need to change the class to hold more preferences...
For user preferences you should use the ASP.NET Profile Provider framework. Some resources:
ASP.NET Profile Providers
Implementing a Profile Provider
StackOverflow: Implementing Profile Provider in ASP.NET MVC
StackOverflow: Implementing a Custom Profile Provider in ASP.NET MVC
You could build attribute-based user preference handling on top of the Profile provider framework, but I imagine that sort of thing would be specific to your app.
Can anyone briefly explain what is the use of GenericIdentity and where to use it.
GenericIdentity and GenericPrincipal are the simplest way of describing a user as a "principal". This can be used for implementation-unaware security checking in an application - i.e. if the user logs in as "Fred" with the "User" and "Admin" permissions:
string[] roles = { "User", "Admin" };
Thread.CurrentPrincipal = new GenericPrincipal(
new GenericIdentity("Fred"), roles);
You might do this at the point of client login to a winform, or there are specific points to do this in WCF, ASP.NET, etc.
Then later code, without having to know how those permissions are handled, can check that permission - either via IsInRole, or declaratively:
[PrincipalPermission(SecurityAction.Demand, Role = "Admin")]
void SomeAdminFunction() { }
Some useful utility code here is null-safe wrappers around principal/identity:
public static string GetUsername() {
IPrincipal principal = Thread.CurrentPrincipal;
IIdentity identity = principal == null ? null : principal.Identity;
return identity == null ? null : identity.Name;
}
public static bool IsInRole(string role) {
IPrincipal principal = Thread.CurrentPrincipal;
return principal == null ? false : principal.IsInRole(role);
}
Then you might have some audit code in your DAL:
row.UpdatedBy = MyUtilityClass.GetUsername();
GenericPrincipal is useful for the simple cases of a plain username and set of known roles.
More sophisticated principal implementations might, for example, do "on demand" access checking - i.e. until you ask for the "Foo" role it doesn't know - it then finds out (by talking to a web-service, database, active-directory, etc) and caches the result for future access. This is useful when the list of potential roles is large, and the number of roles typically queried in reality is small.
You can also use a principal to store extra identity information that is only needed in certain contexts - for example, a security token. Callers might test the principal with as to see if it supports the extra data.
Using "principal" is useful because your logic processing code can talk about identity, without having to know whether this is winforms, ASP.NET, WCF, a windows service, etc - it is abstract. Additionally, some 3rd party code will also talk to the principal.
As another example - I wrote some example code here that shows how to use the principal to control access to winform controls via the designer (via an IExtenderProvider - which puts extra entries into the property grid in VS).
You can use GenericIdentity as a concrete implementation of Identity where you want to supply the details yourself, programmatically, about the current user. Pretty good if you have identified and authenticated the user yourself, through other channels.
GenericIdentity class can be used in conjunction with the GenericPrincipal class to create an authorization scheme that exists independent of a Windows domain.
GenericIdentity myIdentity = new GenericIdentity("MyUser");
Check out
http://msdn.microsoft.com/en-us/library/system.security.principal.genericidentity.aspx
You will find some examples up there. It represents a generic user.
Authentication and profile perissions.
GenericIdentity Class:-
The GenericIdentity class implements the IIdentity interface. It represents the identity of the user based on a custom authentication method defined by the application.
GenericPrincipal class:-
The GenericPrincipal class implements the IPrincipal interface. It represents users and roles that exist independent of Windows users and their roles. Essentially, the generic principal is a simple solution for application authentication and authorization.