I have been working on a web site (using ASP.NET C#) that uses both forms based and claims based authentication. I wanted to override the ClaimsIdentity class so I could implement a custom IsAuthenticated method and add more properties for the identity specific for the claims authentication.
I'm implementing a custom WSFederationAuthentionModule currently, but I was trying to figure out what module I should override (specifically what method) so I can set my custom identity/principal rather than the default ClaimsPrincipal?
So far I have looked at both the SessionAuthenticationModule and ClaimsPrincipalHTTPModule, but I could not figure out at what step the principal is set/the best way to override it.
Thanks
Addition:
Since I'm kind of new at this let me be sure this is correct: The way to set an identity is to set a custom principal which is set to use that identity:
System.Threading.Thread.CurrentPrincipal = customClaimsPrincipal;
Alternatively if a custom principal was not needed then the ClaimPrincipal class could be constructed with a ClaimsIdentityCollection.
There are several places you can do this, but if you are using the SessionAuthenticationModule, some of the process is not documented well which can make using a custom principal tricky. The rest of this answer explains one possible way to handle this when using the SessionAuthenticationModule.
Override the SessionAuthenticationModule.SetPrincipalFromSessionToken method.
The SessionAuthenticationModule stores the security token, principal, identities, and claims in a cookie and an in-memory cache to avoid having to make round-trips to the identity provider/token service on every request. What's not documented well is the existence of the cache and that it is the first place checked, then the cookie, and the limits on serializing the ClaimsPrincipal.
If you already set a custom principal in ClaimsAuthenticationManager.Authenticate and the cache is intact, your custom principal will most likely be there already since the cache stores native .NET objects. If you haven't yet set a custom principal, or the cache is not populated, then the security token will be retrieved from the FedAuth session cookie.
When the token is serialized/deserialized to/from the cookie, the process uses custom serialization that is only capable of reading and writing attributes of the IClaimsPrincipal and IClaimsIdentity interfaces (or the ClaimsPrinicpal and ClaimsIdentity classes - I can't remember which). Any custom principal and identity object attributes will not be included. It may be possible to override the serialization, but that requires several (3 IIRC) more layers of class overrides.
You'll also need to be aware of the fact that the base SetPrincipalFromSessionToken method creates a new ClaimsPrincipal object and sets it on the thread and context, so even if the sessionSecurityToken parameter contains a custom principal object, it will get translated back into a ClaimsPrincipal object.
Here's an example override method:
protected override void SetPrincipalFromSessionToken(SessionSecurityToken sessionSecurityToken)
{
SessionSecurityToken newToken = MyClaimsPrincipalUtility.CreateCustomClaimsPrincipalToken(sessionSecurityToken);
base.SetPrincipalFromSessionToken(newToken);
//the following lines need to be set after the base method call, because the base method overwrites the Principal object
HttpContext.Current.User = newToken.ClaimsPrincipal;
Thread.CurrentPrincipal = newToken.ClaimsPrincipal;
}
The base class (SessionAuthenticationModule) implementation looks like the following. So there are a couple different ways you can achieve the overriding and getting the custom claims principal.
protected virtual void SetPrincipalFromSessionToken(SessionSecurityToken sessionSecurityToken)
{
IClaimsPrincipal fromIdentities = ClaimsPrincipal.CreateFromIdentities(this.ValidateSessionToken(sessionSecurityToken));
HttpContext.Current.User = (IPrincipal) fromIdentities;
Thread.CurrentPrincipal = (IPrincipal) fromIdentities;
//tracing code removed
this.ContextSessionSecurityToken = sessionSecurityToken;
}
And just in case you're wondering, here's the base class implementation for SessionAuthenticationModule.ContextSessionSecurityToken.
public virtual SessionSecurityToken ContextSessionSecurityToken
{
get
{
return (SessionSecurityToken) HttpContext.Current.Items[(object) typeof (SessionSecurityToken).AssemblyQualifiedName];
}
internal set
{
HttpContext.Current.Items[(object) typeof (SessionSecurityToken).AssemblyQualifiedName] = (object) value;
}
}
You're correct in that HttpModules are the way to go in terms of extensibility, but make sure that whatever logic you implement doesn't inhibit the performance of your application. I've had websites go thoroughly berserk performance-wise after adding too many HttpModules to the application. It might be worth caching results of your queries, depending on what auth model you're using.
You need to figure out under what conditions you need to use your custom ClaimsPrincipal. Until you do this you're stabbing in the dark. Are there specific URLs for which you need claims authentication?
Related
I am trying to implement authentication for my web api.
I have read about different techniques of api authentication and the token technique is the most reasonable for me.
I read different articles about how to implement token based authentication in asp.net but they all rely on different libraries such as OAuth or Owin which also provide their own method of database interactions.
The thing is that I have already implemented database interaction with abstract repositories and entities and I would like to find out how can I implement api authentication easily and simply without interfering with my current design.
(By the way, my project is built on top of an empty web api project, so it doesn't come with all the bootstrap and authentication classes).
Thank you
One solution I've seen is to use .NET's HttpApplicationState class and store tokens in appstate; this way you're not directly messing with Session (which would be a REST antipattern), but you can still track all currently logged in users and use HttpContext/HttpActionContext to x-ref active tokens in the app. The benefit to using HttpActionContext is that it is thread-safe, whereas HttpContext is not, so you can lock the appstate, mess with the HttpContext of an individual request, and then unlock the appstate to allow other threads in.
Since locking/unlocking appstate does tie up the app, I'm not sure how well this solution scales, but here it is anyway . . .
General outline:
When a user first logs in, a token is generated for him/her and stored in appstate. Then you can tag any API calls that require authentication (or that need other information stored on that user) with a custom attribute that checks for that token in the appstate, sending the token name as a header in the API call (e.g. "{token-name: TOKEN}").
Here's a brief example:
[in Controller method first activated at login:]
CustomUserObject user = new CustomUserObject();
//store user props
string token = Guid.NewGuid().ToString();
//create AppState instance, mine's called _appState
//...
_appState.Lock();
_appState[token] = user;
_appState.UnLock();
//...
[Then in global.asax:]
public class CustomAuthorize : System.Web.Http.AuthorizeAttribute
{
HttpRequestMessage request = actionContext.ControllerContext.Request;
string token = string.Empty;
if (request.Headers.GetValues("token-name") != null)
{
token = request.Headers.GetValues("token-name").FirstOrDefault().ToString();
IAppStateService appService; //<--- I've created a custom service tier class for appstate stuff
//Get appState instance, however makes sense for you.
//I'm using repo pattern with UnitOfWork, so mine looks like this...
//"IContainer ioc = DependencyResolution.IoC.Initialize();"
//"IAppStateService appService = ioc.GetInstance<IAppStateService>();"
appService.SetHttpApplicationState(HttpContext.Current.Application);
bool isAuthorized = appService.CheckTokenAndDoStuff(token);
//inside that method ^^^ you'll do stuff like
//"_appState.Lock();"
//"if (_appState[token] == null) return false" (or whatever)
//"_appState.Unlock();"
}
if (isAuthorized)
{
HttpResponseMessage resp = request.CreateResponse(HttpStatusCode.OK);
resp.Headers.Add("AuthenticationToken", token);
resp.Headers.Add("WWW-Authenticate", "Basic");
resp.Headers.Add("AuthenticationStatus", "Authorized");
}
return isAuthorized;
}
[then in webapi]
[HttpPost]
[CustomAuthorize]
public HttpResponseMessage NameOfMethod(...)...
...and that should x-check your appstate for your user token for you. Just make sure to include your token in your request header, and make sure to include the Basic Auth info in your response header.
I am struggling a little bit to completely understand what is the correct way to implement a windows authentication and role based authorization scheme into an MVC4 application. When the user accesses the (intranet) website I currently have the following method check the user name against the against a database table
List<string> permissionList =
PermissionBo.GetUserPermissionsList(PermissionBo.ParseUserName(User.Identity.Name));
Permissions permissions = new Permissions(permissionList);
Then the following if state adds a role to a user object:
if (permissions.IsAdmin)
{
if(!Roles.RoleExists("UtilitiesToolAdmin"))
{
Roles.CreateRole("UtilitiesToolAdmin");
}
if(!Roles.IsUserInRole(User.Identity.Name, "UtilitiesToolAdmin"))
{
Roles.AddUsersToRole(new string[] { User.Identity.Name }, "UtilitiesToolAdmin");
}
}
I feel like this may be an incorrect way to go about implementing this, but I am not sure where I am going wrong. Is this sufficient to begin using the authorize attribute like so:
[Authorize(Roles="UtilitiesToolAdmin")]
public static void Foo()
{
return "Bar"
}
If not what am I missing?
If all you are doing is simple role checking, a custom Role Provider might be a bit of an overkill (Role Providers also provide facilities for managing the roles themselves). What you will end up with is a class full of
throw new NotImplementedException();
Instead, consider creating a custom user principal. The IPrincipal interface defines an IsInRole method that returns a bool. This is where you would put your custom role checks. The advantage of the custom user principal is that now all of the built in ASP.NET role-checking goodies should "just work" as long as you replace the default user principal object with your custom one early enough in the lifecycle.
This SO answer has one of the best examples I've seen of using a custom user principal with an MVC application.
I'm working on a project where users can log in and create as many number of "work projects" as they like, which are tied to their account Id. We're using OWIN and ASP.NET Identity 2.1.
All the MVC controller actions that respond to HTTP POST requests require the WorkProjectId to be passed in as a HTTP header. The logged in user should only ever be able to interact with WorkProjects that are associated with their login. This presents an important security consideration: is it best practice to interrogate what WorkProjectId are associated with the currently logged in user at the time the controller action is invoked, perhaps by using a custom attribute?
E.g.
[EnsureUserIsAllowedToDoAnythingToThisWPID]
public async Task UpdateWorkProjectTitle(ViewModel vm) {
...
}
Because the user can create as many WorkProjects as they see fit, I don't think I can do this with Claims based security. As far as I understand, if WorkProjectIds were somehow stored as Claims, if they were modified it would necessitate logging the user in and out whenever that happened ... which is obviously not acceptable.
So, to achieve what I need, is it "wrong" to store the Ids the logged in user has access to in session state? I've been burned very badly in the past on other projects with session state abuse (read: far too much data being serialised into session state) bringing the web servers to their knees due. I'd prefer to avoid it if there are equally simple approaches.
Thanks
Why not just add/remove claims for current user? On controller side via UserManager.AddClaim by pasting in logged-in-user id and desired Claim object (i.e. id of workProject?). As far as I know, storing user data (i.e. allowed WorkProjectIds) in cookies is preferable. And your custom authorize attribute will check if requested WorkProject is allowed for current user:
[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Method,
Inherited = true, AllowMultiple = true)]
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
private string _url; // path to action, also you can get it from request
private Operations _operation; // user requested action (CRUD? or administer, execute, etc.)
// example of usage as attribute [CustomAuthAttrib("some string", Operations.Create)]
public CustomAuthorizeAttribute(string url, Operations operation)
{
_url = url;
_operation = operation;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
// any httpContext.Request... operations
return base.AuthorizeCore(httpContext);
}
}
Here is my some raw listing, currently I'm facing somewhat similar problem. And, to access claims here probably you will need some extension methods that came within OWIN/Katana and/or ASP.NET Identity framework
I dont know how come the context principle is changing in AuthorisationManager. My code is like
public class AuthorisationManager : ClaimsAuthorizationManager
{
public override bool CheckAccess(AuthorizationContext context)
{
var resource = context.Resource.First().Value;
var action = context.Action.First().Value;
return context.Principal.HasClaim(resource, action);
}
public override void LoadCustomConfiguration(System.Xml.XmlNodeList nodelist)
{
base.LoadCustomConfiguration(nodelist);
}
}
I have list of items in GUI. It works fine first time but when I select second item the context.Principle is chnaged to GenericPrinciple.
Any idea will be helpfull on this.
OK - WPF.
Yeah I vaguely remember that there is some "feature" in WPF around Thread.CurrentPrincipal.
try
Thread.CurrentPrincipal = principal
AppDomain.CurrentDomain.SetThreadPrincipal(principal);
IIRC you maybe have to do that in the App class (ctor?).
"return context.Principal.HasClaim(resource, action);"
Well - typically there is no 1:1 corellation of claims and authorizatin "decisions". Also in typical scenarios claims only hold identity data - something data can be used later to base authorization decisions on. The authorization manager then uses its own data management to make those deicions.
Now since this is a client application (i didn't know that it was WPF) you may do things a little differently. In server applications your approach would scale very well.
In the documentation for ServiceStack, it says that the best practice is:
Normally ServiceStack calls the method bool HasPermission(string
permission) in IAuthSession. This method checks if the list
List Permissions in IAuthSession contains the required
permission.
IAuthSession is stored in a cache client as explained above You can
fill this list in the method OnAuthenticated you've overriden in the
first part of this tutorial.
I am integrating with an existing system, and have my custom BasicAuthProvider working (inherited from the base BasicAuthProvider). Authentication is working perfectly, now I am building out the Authorization portion. I plan on using the Permissions list as listed above, but I need access to the Route information to determine if a user has access to a particular resource. I see in the IAuthServiceBase there is an IRequestContext which has the absolute URL, but before going through and parsing that out, I figured there has to be a way to gain access to the ServiceStack Route structure to give me either the class name of the Service being requested, or the DTO the requested service is related to.
Here is the OnAuthenticated method from my BasicAuthProvider class:
public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo)
{
UserSession sess = (UserSession)session;
Model.User currentUser = UserRepository.GetUserByUsername(session.UserAuthName);
//Fill the IAuthSession with data which you want to retrieve in the app eg:
session.FirstName = currentUser.Person.FirstName;
session.LastName = currentUser.Person.LastName;
session.UserName = currentUser.User1;
sess.CurrentUser = currentUser;
//Important: You need to save the session!
authService.SaveSession(session, TimeSpan.FromDays(1));
}
Under MVC I have used some of the Raw Request Data to get the Controller and Action name before, to determine resource authorization, but this is the first project I am using ServiceStack with.
You may find the [RequiredPermission] attribute or even the implementation of it will help you, e.g. the 3rd parameter passed in a RequestFilter is the Request DTO.
And since a Request DTO maps 1:1 with the service, you can be sure that the request is destined for the IService<TRequest> (or its subclasses e.g. ServiceBase<T>, RestServiceBase<T>).
You can access the type of the service programatically as done in the FilterAttributeCache:
var serviceType = EndpointHost.Metadata.GetServiceTypeByRequest(requestDtoType);
I'm not sure of the exact context/use-case you're trying to support but using the [RequiredPermission] or [RequiredRole] attributes may have what you need which by default validates against the list of roles and permissions available in the built-in UserAuth table.
Externally you can use the /assignroles and /unassignroles web services (as part of the AuthorizationFeature plugin) to assign roles and permissions to users (it requires a user with the Admin role by default).
For more info see the documentation pages on Authentication/Authorization and Validation on the ServiceStack GitHub project wiki.