In my code (ASP.NET Identity 2.1) I set claims as follows:
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
OAuthDefaults.AuthenticationType);
ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager,
CookieAuthenticationDefaults.AuthenticationType);
AuthenticationProperties properties = CreateProperties(
user.UserName,
oAuthIdentity,
user.FirstName,
user.LastName,
user.Organization);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(cookiesIdentity);
}
Here is the CreateProperites method where then claims for roles are added:
public static AuthenticationProperties CreateProperties(
string userName,
ClaimsIdentity oAuthIdentity,
string firstName,
string lastName,
int organization)
{
IDictionary<string, string> data = new Dictionary<string, string>
{
{ "userName", userName},
{ "firstName", firstName},
{ "lastName", lastName},
{ "organization", organization.ToString()},
{ "roles",string.Join(":",oAuthIdentity.Claims.Where(c=> c.Type == ClaimTypes.Role).Select(c => c.Value).ToArray())}
};
return new AuthenticationProperties(data);
}
On my client I issue a request for a token and receive it back like this:
this.$http({
method: 'POST',
url: '/Token',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
data: 'grant_type=password&username=' + encodeURIComponent(userName) + '&password=' + encodeURIComponent(password),
})
.success((data: any, status, headers, cfg) => {
self.data.roles = data.roles;
I can see that self.data.roles is correctly populated with the roles. Now back on the server I would like to check the contents of the roles claim. Can someone help by telling me how to do this? I know I can do the following in a method:
[HttpGet]
[Route("Retrieve")]
public async Task<IHttpActionResult> Retrieve()
{
var x = User;
x gets the value of the
System.Security.Claims.ClaimsPrinciple and
System.Security.Claims.ClaimsIdentity
but within x I cannot find the information on the claims themselves.
Note that I did try a suggestion posted before on SO:
var identity = (ClaimsIdentity)User.Identity;
IEnumerable<Claim> claims = identity.Claims;
// The following line returns null
var roles = identity.Claims.Where(r => r.Type == "roles").FirstOrDefault();
But I still cannot inside of claims find the information that I have related to the roles claim. I know it must be there as it gets to the client.
Please note I am looking for the "roles" claim specifically. Not any system generated claim. But the one I tried to add myself that contains an concatenated list of the roles.
Did you try this?
var roleClaims = identity.Claims.Where(c => c.Type == ClaimTypes.Role);
UPDATE
First of all, you are not adding a claim. You are adding some data into the properties dictionary of the AuthenticationTicket
. This data happens to be comma separated roles and the key you have chosen to name is "roles". So, this is not a claim.
When you say it does not work for me, I believe you want to find the comma separated value you put in the dictionary. If that is the case, you cannot retrieve it from User
in controller. When you send a bearer token, the bearer token authentication middleware reads the token, gets the ClaimsIdentity
from the token and sets that in the context so that you can read that off User
.
Anything you put in the AuthenticationTicket
is for the middleware (actually handler) to use. So, if you want to get any data from AuthenticationTicket
, you need to call AuthenticateAsync
on the bearer middleware yourself. By doing var result = await AuthenticationManager.AuthenticateAsync(OAuthDefaults.AuthenticationType);
, you now are getting the entire ticket and not just the ClaimsIdentity
. By looking at the result
, you should be able to get your comma separated roles but then understand, the bearer middleware has already done that for you once and you are calling it again.
BTW, if you want to add a custom claim, then you need to add it to the oAuthIdentity
in GrantResourceOwnerCredentials
.
public override async Task GrantResourceOwnerCredentials(
OAuthGrantResourceOwnerCredentialsContext context)
{
// snip
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
OAuthDefaults.AuthenticationType);
oAuthIdentity.AddClaim(new Claim("urn:roles", "a,b,c");
}
If you do it like this, you can read from User
.
var myRoleClaims = identity.Claims.Where(c => c.Type == "urn:roles");
I think the issue is that you are looking at the wrong authenticationType, User.Identity maps to the cookie and the 'active' authenticationType which is: CookieAuthenticationDefaults.AuthenticationType
To look at the claimsIdentity with your roles, you probably need to call IAuthenticationManager.Authenticate(OAuthDefaults.AuthenticationType) and then I think you will see the roleClaims that you expect.
Edit: added an example
var result = await AuthenticationManager.AuthenticateAsync(OAuthDefaults.AuthenticationType);
// do something with result.Identity
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