6

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.

2 Answers 2

6

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");

Sign up to request clarification or add additional context in comments.

2 Comments

This does not work for me. I am wanting to find the contents of my own claim I added not the one added with a ClaimTypes.Role. Thanks.
Thanks for your advice. I really wish there were more examples out there. I spent a lot of time looking at different web links but didn't find anything recent and the technologies are changing so fast it is very hard for me to keep up.
1

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

4 Comments

Can you give me an example of where I would need to call this. Do I need to put this in the controller? If you could give me a 3-4 line code example then I can try it out. Thank you.
Sure, you should be able to do something like that in the controller to get out the claims identity
Will that go to the database? I was hoping to have the "roles" claim sent to the browser and then to have it returned to the server each time and have it available for me to get but not from the database?
No that doesn't go to the database, it will just be hitting whatever auth middleware you have configured for the authtype, which is your OAuth.AuthenticationType middleware

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.