Reputation: 941
I need to get UserId from Asp.Net user authorization system because most of my data is stored within SQL and using UserId as a marker which user owns this data. Using Owin OAuth 2.0 I can't get UserId using Identity, it returns null
. So I've come up with this solution:
Token provider
identity.AddClaim(new Claim("user_id", user.Id));
API
ClaimsPrincipal principal = Request.GetRequestContext().Principal as ClaimsPrincipal;
var userName = principal.Claims.Where(c => c.Type == "user_id").Single().Value;
Simpler API code
var userName = ClaimsPrincipal.Current.Claims.First(c => c.Type == "user_id").Value;
Is this approach good for enterprise business-level application, is it safe, secure and robust? Or will you (maybe) advice something else?
I just don't like the idea of passing UserId inside the token when this functionality is (probably) provided by Microsoft.AspNet.Identity (.NET itself), but as I couldn't make it work, this is my only option for now.
Anyway, I am partly using code from this great tutorial repository. As you can see, this controller has commented lines which are using Identity to get UserId. But this doesn't work for me, so I am using another commented line which uses claims.
Upvotes: 2
Views: 3406
Reputation: 2213
I am assuming identity object in the below code is of type ClaimsIdentity. How and where are you initializing this object ?
identity.AddClaim(new Claim("user_id", user.Id));
If you look at the default template that is generated for a web app in Visual Studio there will be a IdentityModel class where you can see code like below and this is called when you signin in ASP.Net Identity.
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
Also this is responsible for adding the default claims data and you can also extend this to add additional information like user phonenumber (primarily to avoid a round trip to database and store additional user information as claim).
So when are you creating the identity object ?
If you are question is if it is OK to add more information as claim I guess that should be OK. Also what is the output of
identity.GetUserId();
in your case?
You can further write your own IdentityExtensions class as explained in http://anthonychu.ca/post/aspnet-identity-20---logging-in-with-email-or-username/
Update 1 -
When you sign in using ASP.Net Identity system it calls GenerateUserIdentityAsync which internally calls CreateAsync method defined in UserClaimsPrincipalFactory class . Here is the code https://github.com/aspnet/Identity/blob/daa50df87feb9f1b59858a22f00a2984996738c6/src/Microsoft.AspNet.Identity/UserClaimsPrincipalFactory.cs . If you look at this method it actually does what you are doing explicitly
var id = new ClaimsIdentity(Options.Cookies.ApplicationCookieAuthenticationScheme, Options.ClaimsIdentity.UserNameClaimType, Options.ClaimsIdentity.RoleClaimType);
id.AddClaim(new Claim(Options.ClaimsIdentity.UserIdClaimType, userId)); .
So I believe that's what you also need to do
Upvotes: 0
Reputation: 239350
Since, you're using OWIN, I'm going to assume you're using ASP.NET Identity, as well. You don't need to store the user id as a claim. You can get it anytime you need via:
User.Identity.GetUserId()
If Intellisense freaks out, you just need to add the Microsoft.AspNet.Identity
namespace.
Upvotes: 4