My WebAPI 2 application has a custom authorization filter which checks for an access token. If the token is present, and the API has the attribute, then I check if there exists a user which maps to that token.
Due to the nature of the API, most methods run in the context of a particular user (i.e. "POST api/profile" to update a user's profile). In order to do this, I need information on the target user which I get from the access token.
[Current Implementation, happens within attribute of type AuthorizeAttribute]
if( myDBContext.MyUsers.Count( x => x.TheAccessToken == clientProvidedToken ) ){
IPrincipal principal = new GenericPrincipal( new GenericIdentity( myAccessToken ), new string[] { "myRole" } );
Thread.CurrentPrincipal = principal;
HttpContext.Current.User = principal;
return true;
}
This works fine, and I'm able to then use the access token to do a second lookup in the Method. But since I already do a lookup at auth time, I don't want to waste another DB call.
[What I'd like to do (but obviously doesn't work)]
MyUser user = myDBContext.MyUsers.FirstOrDefault( x => x.TheAccessToken == clientProvidedToken );
if( user != null ){
// Set *SOME* property to the User object, such that it can be
// access in the body of my controller method
// (e.g. /api/profile uses this object to load data)
HttpContext.Current.User = user;
return true;
}
You could use your own principal class. Maybe something like:
public class MyPrincipal : GenericPrincipal
{
public MyPrincipal(IIdentity identity, string[] roles)
: base(identity, roles)
{
}
public MyUser UserDetails {get; set;}
}
Then your action filter could do:
MyUser user = myDBContext.MyUsers.FirstOrDefault( x => x.TheAccessToken == clientProvidedToken );
if(user != null)
{
MyPrincipal principal = new MyPrincipal( new GenericIdentity( myAccessToken ), new string[] { "myRole" } );
principal.UserDetails = user;
Thread.CurrentPrincipal = principal;
HttpContext.Current.User = principal;
return true;
}
return false;
And subsequently in your actual method, you can take the current user, check if it's of type MyPrincipal
and if so cast it and then access the UserDetails:
...
MyUser currentUser = null;
MyPrincipal curPrincipal = HttpContext.Current.User as MyPrincipal;
if (curPrincipal != null)
{
currentUser = curPrincipal.UserDetails;
}
...
I haven't actaully tried this code, so there might be typos...
You could use a ClaimsIdentity/ClaimsPrincipal
and add the Claims
you need later in your controller, for example the actors ID or other values you need.
I've made an example which sets claims to the Actor but if it better suits you you could also at Claims directly to the current User.
var identity = new ClaimsIdentity(HttpContext.Current.User.Identity);
identity.Actor = new ClaimsIdentity();
identity.Actor.AddClaim(new Claim("Your", "Values"));
var principal = new ClaimsPrincipal(identity);
Thread.CurrentPrincipal = principal;
HttpContext.Current.User = Thread.CurrentPrincipal;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With