Adding authentication role as claim

In my ASP.NET MVC app I want to add a role to the user, and then authenticate various parts of the web app with this. I have followed the process outlined here How to include Authorization Extension data (groups/roles/permissions) into issued tokens? - Auth0 Community, which means I have a rule

    function (user, context, callback) {
      var namespace = 'https://mydomain.com/';
      context.idToken[namespace + 'roles'] = user.roles;  
      callback(null, user, context);
    }

and I have enabled the authorization extension. My custom rule is after the authorization rule.

My returned claims still don’t include the roles section though.

What am I missing?

Hi @me5

Your rule should be adding your claim to the user when the user is requested via GetUserInfoAsync

There is a property called AdditionalClaims on the user, you need to get these and use them to create the ClaimsPrinciple to have these available on the asp.net user context, you can do something like the following, in your Login Action:

[HttpPost]
        public async Task<IActionResult> Login(LoginViewModel model)
        {
              
            if (ModelState.IsValid)
            {
                try
                {
                    var client = new AuthenticationApiClient(new Uri($"https://{Auth0Settings.Domain}/"));

                    var result = await client.GetTokenAsync(new ResourceOwnerTokenRequest
                    {
                        ClientId = Auth0Settings.ClientId,
                        ClientSecret = Auth0Settings.ClientSecret,
                        Scope = "openid profile",
                        Realm = Auth0Settings.DatabaseConnection,
                        Username = model.EmailAddress,
                        Password = model.Password
                    });

                    var user = await client.GetUserInfoAsync(result.AccessToken);

                    // Get Additional Claims
                    var additionalClaims = (user.AdditionalClaims ?? new Dictionary<string, JToken>()).ToList();

                    var claims = new List<Claim>()
                    {
                        new Claim(ClaimTypes.NameIdentifier, user.UserId),
                        new Claim(ClaimTypes.Name, user.UserId)
                    };

                    var rolesClaim = additionalClaims.Where(x => x.Key == $"{Auth0Settings.ClaimsNamespace}roles").Select(x => x.Value.ToString()).FirstOrDefault();

// … other claims

                    if (rolesClaim != null) { claims.Add(new Claim("roles", rolesClaim)); }
                    // .. other claims
                    

                    var claimsIdentity = new List<ClaimsIdentity> { new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme) };

                    var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);

                      
                   await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal);
                       
                    return RedirectToLocal(model.ReturnUrl);
                }
                catch (Exception exception)
                {
                    ModelState.AddModelError("", exception.Message);
                }
            }

            return View(model);
        }

Thanks for that very thorough answer. Does this mean I can’t use the oAuth connections to Facebook etc. due to the ResourceOwnerTokenRequest object needing username and password?

I haven’t used other types of connections, but you should be able to use any type of connection for authentication, and once authenticated then use the API to add and retrieve additional user data after the authentication has taken place.