Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Hosted-services / Azure

Custom Authorization for Azure AD B2C

4.00/5 (1 vote)
26 Nov 2015CPOL1 min read 22.8K  
Custom Authorization for Azure AD B2C

Introduction

Custom authorization for Azure active directory B2C using OWIN.

Background

Azure Active Directory B2C is a highly available, global, identity management service for consumer-facing applications that scales to hundreds of millions of identities.

There are no specific roles that are supported in B2C yet, but as a work-around, this can be achieved by making use of attributes. PS: Azure AD B2C is still in preview and is planned to be rolled out by MAY '16.

Using the Code

Authentication

C#
public static string SignUpPolicyId = ConfigurationManager.AppSettings["b2c:SignUpPolicyId"];
        public static string SignInPolicyId = ConfigurationManager.AppSettings["b2c:SignInPolicyId"];
        public static string ProfilePolicyId = ConfigurationManager.AppSettings["b2c:UserProfilePolicyId"];

        private static string clientIdB2C = ConfigurationManager.AppSettings["b2c:ClientId"];

        public static string aadInstanceB2C = ConfigurationManager.AppSettings["b2c:AadInstance"];
        private static string tenantIdB2C = ConfigurationManager.AppSettings["b2c:Tenant"];
        private static string postLogoutRedirectUriB2C = ConfigurationManager.AppSettings["b2c:RedirectUri"];
        public static readonly string Authority = aadInstance + tenantId;
        string graphResourceId = "https://graph.windows.net";
        OpenIdConnectAuthenticationOptions options = new OpenIdConnectAuthenticationOptions
            {
                // These are standard OpenID Connect parameters, with values pulled from web.config
                ClientId = clientIdB2C,
                RedirectUri = postLogoutRedirectUriB2C,
                AuthenticationType = "B2C",
                PostLogoutRedirectUri = postLogoutRedirectUriB2C,


                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    //AuthenticationFailed = AuthenticationFailed,
                    RedirectToIdentityProvider = OnRedirectToIdentityProvider,
                  
                },
                Scope = "openid",
                ResponseType = "id_token",
                ConfigurationManager = new PolicyConfigurationManager(
                    string.Format(CultureInfo.InvariantCulture, aadInstanceB2C + 
                    "", tenantIdB2C, "/v2.0", OIDCMetadataSuffix),
                    new string[] { SignUpPolicyId, SignInPolicyId, ProfilePolicyId }),


                // This piece is optional - it is used for displaying the user's name in the navigation bar.
                TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = "name",
                },
            };
            app.UseOpenIdConnectAuthentication(options);

If user id has to be passed to the authentication page from application's custom input, add the below code in OnRedirectToIdentityProvide? method.

C#
if (notification.OwinContext.Authentication.AuthenticationResponseChallenge.
	Properties.Dictionary.ContainsKey("login_hint"))?{

                notification.ProtocolMessage.LoginHint = notification.OwinContext.
                Authentication.AuthenticationResponseChallenge.Properties.Dictionary["login_hint"];
//Dictionary["login_hint"] will be fetched from the login method
        }

Now, from the controller, call the authentication challenge, specifying the signin policy ID and any other custom parameters (ex: login_hint) in the Sign In method.

C#
HttpContext.GetOwinContext().Authentication.Challenge(
                             new AuthenticationProperties(
                                 new Dictionary<string, string>
                                 {
                             {Startup.PolicyKey, Startup.SignInPolicyId}, {"login_hint", UserID }
//login_hint is an optional parameter which is passed to populate the user ID in the AD login page
                                 })
                             {
                                 RedirectUri = "/",
                             }, "B2C");

Once the authentication challenge is called, it routes to the appropriate AD login page when the authentication is taken care and will be routed back to the application (with url specified in postloguturl).

In Azure B2C, as roles are supported (at least for now, create an attribute for every user while signing up to authorize users on specific roles / attributes. Custom attributes are not supported in B2C yet, but the value of an attribute is a free text. For example, consider setting the JobTitle attribute of a user as 'Administrator' (can be set from Azure portal for a simple test).

Once the attribute is set, get the claim details of the user signed in which will return all attributes associated with the user account.

C#
var UserRole = (from claim in ClaimsPrincipal.Current.Claims 
	where claim.Type.Equals("jobTitle") select claim.Value).FirstOrDefault();

UserRole will now contain 'Administrator' as value based on which we can authorize the user. This can be overwritten in ?OnAuthorization method to create a custom authorization attribute and can be called in the below way.

In controller:

C#
[CustomAuthorize("Administrator")]
        public ActionResult Claims_Admin()
        {          
            return View("ClaimsAdmin");
        }

Extended Authorization:

C#
public override void OnAuthorization(System.Web.Mvc.AuthorizationContext context)
        {
          if (context.RequestContext.HttpContext.Request.IsAuthenticated)
            {
                var UserRole = (from claim in ClaimsPrincipal.Current.Claims where 
		claim.Type.Equals("jobTitle") select claim.Value).FirstOrDefault();

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)