I am using the excellent Thinktecture.IdentityModel library for performing authentication/authorization in an ASP.NET Web API project which will be consumed from mobile devices and possibly web clients. I am using basic authentication to authenticate mobile clients to access the web api, and utilizing the built in SessionToken generation that the Thinktecture.IdentityModel presents. However I have some concerns as to how to revoke claims added to a ClaimsIdentity claims collection, which are then (I think) encoded into the SessionToken provided to a client...
Here is what I have so far:
Following the examples in the IdentityModel sample project, I have created the following class
public static class SecurityConfig
{
public static void ConfigureGlobal(HttpConfiguration globalConfig)
{
globalConfig.MessageHandlers.Add(new AuthenticationHandler(CreateConfiguration()));
}
public static AuthenticationConfiguration CreateConfiguration()
{
var authentication = new AuthenticationConfiguration()
{
ClaimsAuthenticationManager = new MyClaimsTransformer(),
RequireSsl = false, //TODO:TESTING only
EnableSessionToken = true,
SessionToken = new SessionTokenConfiguration()
{
EndpointAddress = "/Authenticate"
}
};
authentication.AddBasicAuthentication(Membership.ValidateUser);
return authentication;
}
}
Which is called from my Global.asax class like so
SecurityConfig.ConfigureGlobal(GlobalConfiguration.Configuration);
The mobile devices collects the username and password from an individual, and set the authentication header properly and supplies the credentials to the necessary web endpoint http://myhost/api/Authenticate
On the server, my Membership.ValidatUser is called with the username/password, and if validated, the Authenticate method of MyClaimsTransformer
is called.
public class ClaimsTransformer : ClaimsAuthenticationManager
{
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (!incomingPrincipal.Identity.IsAuthenticated)
{
return base.Authenticate(resourceName, incomingPrincipal);
}
return incomingPrincipal;
}
}
The mobile client then receives back a token, which it can pass along in the authentication header of any subsequent requests.
This all works great.
Now what I would like to do, is in the ClaimsTransformer, add some code that would do something like the following pseudocode.
var nameClaim = incomingPrincipal.Claims.First(c => c.Type == ClaimTypes.Name);
//Using value in nameClaim lookup roles or permissions for this user.
var someListofRoles = SomeMethodToGetRoles(nameClaim.Value);
//Add user roles to the Claims collection of the ClaimsPrincipal.
foreach(var role in someListOfRoles)
{
incomingPrincipal.Identities.First().AddClaim(new Claim("Role", role.Name));
}
My hope was to limit the number of times I need to request the list of roles or permissions for a given user from the database, as well as make it convenient for checking these roles/permissions in a custom AuthorizeAttribute.
However as I started adding this, I began to think of scenarios where a user would have been logged in and would have received this token, but through some action by a different user of the system would have had their roles changed or revoked. The initial user would still have this token with a list of now expired roles/permissions and would have access to whatever until the token expired, or would have been given new access to something but would not actually receive that access until they somehow logout.
Is there a mechanism for invalidating a SessionToken created in this way? Or, if I found some way to know a change has been made to a users roles/permissions, how would I modify the claims and reissue a SessionToken in a seamless fashion?
Also, how does one just entirely revoke a SessionToken, ie if I wanted to 'logout' a user, how would that work?