Search code examples
c#asp.net-mvcasp.net-identityclaims-based-identityclaims

ASP.NET Identity and Claim-based


How to use claims? For example, I want to set access to each page (resource) for each user. I understand, I can do it using roles, but as I understand, claim-based is more effectively. But when I try to create a claim, I see the following method:

        userIdentity.AddClaim(new Claim(ClaimTypes.Role, "test role"));

first parameter of constructor of Claim class get ClaimTypes enum, which has many "strange" members like Email, Phone etc. I want to set that this claim and then check this claim to have access to certain resource. I'm on wrong way? How to do it?


Solution

  • From the code above, I am assuming you have already added the claim in startup class on authenticated of your provider as below.

    context.Identity.AddClaim(new Claim("urn:google:name", context.Identity.FindFirstValue(ClaimTypes.Name))); // added claim for reading google name
    context.Identity.AddClaim(new Claim("urn:google:email", context.Identity.FindFirstValue(ClaimTypes.Email))); // and email too
    

    Once you have added the claims in startup, when the request is actually processed check if its a callback and if yes, read the claims as below(in IHttpHandler).

    public void ProcessRequest(HttpContext context)
        {
            IAuthenticationManager authManager = context.GetOwinContext().Authentication;
            if (string.IsNullOrEmpty(context.Request.QueryString[CallBackKey]))
            {
                string providerName = context.Request.QueryString["provider"] ?? "Google";//I have multiple providers so checking if its google
                RedirectToProvider(context, authManager, providerName);
            }
            else
            {
                ExternalLoginCallback(context, authManager);
            }
        }
    

    If its 1st call redirect to provider

    private static void RedirectToProvider(HttpContext context, IAuthenticationManager authManager, string providerName)
        {
            var loginProviders = authManager.GetExternalAuthenticationTypes();
    
            var LoginProvider = loginProviders.Single(x => x.Caption == providerName);
    
            var properties = new AuthenticationProperties()
            {
                RedirectUri = String.Format("{0}&{1}=true", context.Request.Url, CallBackKey)
            };
    
            //string[] authTypes = { LoginProvider.AuthenticationType, DefaultAuthenticationTypes.ExternalCookie };
            authManager.Challenge(properties, LoginProvider.AuthenticationType);
    
            //without this it redirect to forms login page
            context.Response.SuppressFormsAuthenticationRedirect = true;
        }
    

    And finally read the claims you get back

    public void ExternalLoginCallback(HttpContext context, IAuthenticationManager authManager)
        {
            var loginInfo = authManager.GetExternalLoginInfo();
            if (loginInfo == null)
            {
                throw new System.Security.SecurityException("Failed to login");
            }
    
            var LoginProvider = loginInfo.Login.LoginProvider;
            var ExternalLoginConfirmation = loginInfo.DefaultUserName;
    
            var externalIdentity = authManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
            var emailClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email);
            var email = emailClaim.Value;
    
            var pictureClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type.Equals("picture"));
            var pictureUrl = pictureClaim.Value;
    
            LogInByEmail(context, email, LoginProvider); //redirects to my method of adding claimed user as logged in, you will use yours.
        }