8

I am having an issue understanding the claims, especially roles.

Following gives me two roles assigned to the user

var roles = UserManager.GetRolesAsync(user.Id).Result;

But when i get the claims and iterate through it, I only get the first role. I don't get both the roles. Please note that I haven't setup any roles in the claims at the time of login.

Action Code

IEnumerable<Claim> claims = null;
var identity = HttpContext.User.Identity as ClaimsIdentity;
if (identity != null && identity.Claims != null && identity.Claims.Any())
{
    claims = identity.Claims;
}
return View(claims);

and the corresponding view code

@model IEnumerable<System.Security.Claims.Claim>
@{
    ViewBag.Title = "Display Claims";
}

<h2>Display Claims</h2>

@if (Model == null)
{
    <p class="alert-danger">No claims found</p>
}
else
{
    <table class="table table-bordered">
        <tr>
            <th>Subject</th>
            <th>Issuer</th>
            <th>Type</th>
            <th>Value</th>
        </tr>
        @foreach (var claim in Model.OrderBy(x => x.Type))
        {
            <tr>
                <td>@claim.Subject.Name</td>
                <td>@claim.Issuer</td>
                <td>@Html.ClaimType(claim.Type)</td>
                <td>@claim.Value</td>
            </tr>
        }
    </table> 
}

and here is the output. What am I missing here?

enter image description here

And the table has the two roles

enter image description here

Update #1

I added first name and last name as remote claims, logged in and both the roles are now displaying. I didn't change any thing. So now i am more confused...

enter image description here

Here is the provider to add remote claims

public static class ClaimsUserInfoProvider
    {
        public static IEnumerable<Claim> GetClaims(ClaimsIdentity user, ApplicationUser applicationUser)
        {
            var claims = new List<Claim>();

            claims.Add(CreateClaim(ClaimTypes.GivenName, applicationUser.FirstName + " " + applicationUser.LastName));

            return claims;
        }

        private static Claim CreateClaim(string type, string value)
        {
            return new Claim(type, value, ClaimValueTypes.String, "RemoteClaims");
        }
    }

and the login action to use the claims provider

[HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Login(LoginViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = await UserManager.FindAsync(model.UserName, model.Password);
                if (user == null)
                {
                    ModelState.AddModelError("", "Invalid user name or password.");
                }
                else
                {
                    var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
                    //add claims
                    identity.AddClaims(ClaimsUserInfoProvider.GetClaims(identity, user));

                    AuthenticationManager.SignOut();
                    AuthenticationManager.SignIn(new AuthenticationProperties
                    {
                        IsPersistent = model.RememberMe
                    }, identity);
                    if (!String.IsNullOrEmpty(model.ReturnUrl))
                    {
                        return Redirect(model.ReturnUrl);
                    }
                    return RedirectToAction("Index", "Home");
                }
            }
            return View(model);
        }
learning...
  • 3,104
  • 10
  • 58
  • 96
  • This answer may help http://stackoverflow.com/questions/21688928/asp-net-identity-get-all-roles-of-logged-in-user – r lo Nov 27 '15 at 02:47
  • I looked at this before but couldn't understand it. For the last hour or so i have been reading about it and now this makes more sense. I have put update #1 in my question post. Both roles are now displaying, don't know why these were not displaying earlier. – learning... Nov 27 '15 at 02:50
  • I'll ask a silly question - did you clear the cookies in a browser? Did you log-out and log-in again? – trailmax Nov 28 '15 at 23:44
  • Infact i did, i have placed update#1.. both the roles are now showing. – learning... Nov 29 '15 at 03:00
  • I had read somewhere that the membership provider does not support claims by default like it is with users and roles. my 2 cents – sino Feb 04 '16 at 04:20
  • My guess would be that auth cookie was created before second role was added. And cookie is not automatically updated when the second role was added. Basically you were looking on a stale data in cookie. – trailmax Apr 21 '16 at 11:04

1 Answers1

1

It is hard to tell for certain but I think what happened here is that Claims were cached in the cookie that is used for authenticating the user. When a user first logs in the claims are read from the database, a cookie is created with the claims and stored on the users browser. All further requests read the users claim information from the cookie until it expires. I have a detailed blog post on I wrote awhile back on ASP.NET Identity Cookie Expiration for more information on how to manage expiration.

Some of your wording suggests (only a guess on my part) that the roles were added after the user had already signed in and therefor the roles were not added to the cookie and would not print out. The claims refreshed when you added the code to add the names because one of few reasons:

  1. The cookie had expired and you had to do a fresh login.
  2. You signed out (which removed the cookie) and then did a fresh login.
  3. You stayed logged in but when you reposted to the login action you have a call to signout and then signin which refreshed the cookie:

    AuthenticationManager.SignOut(); AuthenticationManager.SignIn(new AuthenticationProperties

You can duplicate the behavior you where experiencing:

  1. Make sure the user is signed out
  2. Remove the user's roles from the AspNetUserRoles table
  3. Signing the user in
  4. Add the roles back the user in the AspNetUserRoles table (either manually or by some Action via your application where you manage roles for users)
  5. Print out the roles
  6. You will not see the roles in the print out.
  7. Next sign the user out and sign them back in and you will then see the expected roles.

Each time you add a role or claim you will need to have user manually log out or you can make a call that refreshes the cookie as I mentioned earlier. This answer here gives some context on how to refresh the cookie effectively.

Community
  • 1
  • 1
jsturtevant
  • 2,560
  • 1
  • 23
  • 23