DEV Community

Cover image for How to Integrate Azure Active Directory B2C in ASP.NET 4.5 WebAPI
Shahzada Fahad Ashraf
Shahzada Fahad Ashraf

Posted on

How to Integrate Azure Active Directory B2C in ASP.NET 4.5 WebAPI

Hey there, my fellow tech-savvy readers!

Now, picture this: you've got a trusty ASP.NET 4.5 WebAPI application chugging along like a well-oiled machine, doing its thing, and you're thinking, "Why change something that works just fine?" 💼🕶️

But as the tech world evolves faster than a cheetah chasing its morning coffee, I started feeling the pressure once I set sails to incorporate Azure Active Directory B2C into my relatively older codebase. 💨☁️

And there's the rub! 🌶️ Integrating ADB2C into this tried-and-true ASP.NET version came to me like introducing a jazz band to a black-tie ball. 😂🎷

But fear not as I'm here to help you navigate these waters with a smile on your face and a skip in your step. 💃🕺

I'll show you how to combine the old and the new in a seamless dance that'll make your ASP.NET 4.5 WebAPI look and feel like it's on cloud nine! ☁️💫

So grab your coding wands, and let's sprinkle some Azure Active Directory B2C fairy dust over your beloved ASP.NET 4.5 WebAPI! 🧙‍♂️✨

Assumptions

At this point, I'm assuming the following:

  1. You have already set up your Azure Account
  2. You already have the necessary information and credentials required to create the hand-shake between Azure and your ASP.NET App
  3. You have already defined scopes, and policies

Step 1

Start by adding the necessary credentials and information in your Web.config file. Per my experience, you're going to be needing the following

<add key="AZB2C:AadInstance" value="https://<YOUR_AZURE_DOMAIN>.b2clogin.com/{0}/{1}/v2.0/.well-known/openid-configuration" />
<add key="AZB2C:Tenant" value="<YOUR_AZURE_DOMAIN>.onmicrosoft.com" />
<add key="AZB2C:TenantId" value="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" />
<add key="AZB2C:ClientId" value="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" />
<add key="AZB2C:ClientSecret" value="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" />
<add key="AZB2C:RedirectUri" value="http://localhost:3000/" />
<add key="AZB2C:SignUpSignInPolicyId" value="SIGN_IN_POLICY_NAME" />
<add key="AZB2C:ResetPasswordPolicyId" value="PASSWORD_RESET_POLICY_NAME" />
<add key="AZB2C:SOME_SCOPE_NAME" value="Scope.Something.Something" />
<add key="AZB2C:ANOTHER_SCOPE_NAME" value="Scope.Yes.AnotherSomething" />
Enter fullscreen mode Exit fullscreen mode

We are going to be basing our code off of these credentials.

Step 2

Create a *civilized * way of using these environment variables in your code by creating a static class that extracts all the env variables from the Web.config into a Static Class Instance. This way, you can easily access these environment variables all across your application.

    public static class AzureEnvironmentVariables
    {
        public static string AadInstance = ConfigurationManager.AppSettings["AZB2C:AadInstance"];
        public static string Tenant = ConfigurationManager.AppSettings["AZB2C:Tenant"];
        public static string TenantId = ConfigurationManager.AppSettings["AZB2C:TenantId"];

        public static string ClientId = ConfigurationManager.AppSettings["AZB2C:ClientId"];
        public static string ClientSecret = ConfigurationManager.AppSettings["AZB2C:ClientSecret"];
        public static string RedirectUri = ConfigurationManager.AppSettings["AZB2C:RedirectUri"];

        public static string SignUpSignInPolicyId = ConfigurationManager.AppSettings["AZB2C:SignUpSignInPolicyId"];
        public static string ResetPasswordPolicyId = ConfigurationManager.AppSettings["AZB2C:ResetPasswordPolicyId"];

        public static string DefaultPolicy = SignUpSignInPolicyId;

        public static string FirstScope = AadInstance + ConfigurationManager.AppSettings["api:SOME_SCOPE_NAME"];
        public static string SecondScope = AadInstance + ConfigurationManager.AppSettings["api:ANOTHER_SCOPE_NAME"];
        public static string[] Scopes = new string[] { FirstScope, SecondScope };

        public static string B2CAuthority = string.Format(AadInstance, Tenant, DefaultPolicy);
        public static string WellKnownMetadata = $"{AadInstance}/v2.0/.well-known/openid-configuration?p={SignUpSignInPolicyId}";
    }
Enter fullscreen mode Exit fullscreen mode

Step 3

Create your auth provider

No go ahead and create a new file in your App_Start folder called Startup.Auth.cs

In this file, you are going to create a Startup Extension Method that will be triggered on Startup time and register your Auth Provider, called Startup.Auth into your application.

public partial class Startup
    {
        public static string AadInstance = AzureEnvironmentVariables.AadInstance;
        public static string Tenant = AzureEnvironmentVariables.Tenant;
        public static string TenantId = AzureEnvironmentVariables.TenantId;
        public static string ClientId = AzureEnvironmentVariables.ClientId;
        public static string SignUpSignInPolicy = AzureEnvironmentVariables.SignUpSignInPolicyId;
        public static string DefaultPolicy = SignUpSignInPolicy;

        public void ConfigureAuth(IAppBuilder app)
        {
            TokenValidationParameters tvps = new TokenValidationParameters
            {
                ValidAudience = ClientId,
                AuthenticationType = Startup.DefaultPolicy,
                SaveSigninToken = true,
            };

            string metadataEndpoint = String.Format(AadInstance, Tenant, DefaultPolicy);

            app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
            {
                AccessTokenFormat = new JwtFormat(tvps, new OpenIdConnectCachingSecurityTokenProvider(metadataEndpoint))
            });
        }
    }

    public class OpenIdConnectCachingSecurityTokenProvider : IIssuerSecurityKeyProvider
    {
        public ConfigurationManager<OpenIdConnectConfiguration> _configManager;
        private string _issuer;
        private IEnumerable<SecurityKey> _keys;
        private readonly string _metadataEndpoint;

        private readonly ReaderWriterLockSlim _synclock = new ReaderWriterLockSlim();

        public OpenIdConnectCachingSecurityTokenProvider(string metadataEndpoint)
        {
            _metadataEndpoint = metadataEndpoint;
            _configManager = new ConfigurationManager<OpenIdConnectConfiguration>(metadataEndpoint, new OpenIdConnectConfigurationRetriever());

            RetrieveMetadata();
        }


        public string Issuer
        {
            get
            {
                RetrieveMetadata();
                _synclock.EnterReadLock();
                try
                {
                    return _issuer;
                }
                finally
                {
                    _synclock.ExitReadLock();
                }
            }
        }

        public IEnumerable<SecurityKey> SecurityKeys
        {
            get
            {
                RetrieveMetadata();
                _synclock.EnterReadLock();
                try
                {
                    return _keys;
                }
                finally
                {
                    _synclock.ExitReadLock();
                }
            }
        }

        private void RetrieveMetadata()
        {
            _synclock.EnterWriteLock();
            try
            {
                OpenIdConnectConfiguration config = Task.Run(_configManager.GetConfigurationAsync).Result;
                _issuer = config.Issuer;
                _keys = config.SigningKeys;
            }
            finally
            {
                _synclock.ExitWriteLock();
            }
        }
    }
Enter fullscreen mode Exit fullscreen mode

Step 4

Now go ahead and call your Startup extension method in the Configurations function within your Startup.cs file to actually register your Auth Provider.

    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);

            HttpConfiguration config = new HttpConfiguration();
            WebApiConfig.Register(config);
        }
    }
Enter fullscreen mode Exit fullscreen mode

Step 5

Finally, add the Authorize annotation in your controllers on the Endpoints that you'd like to protect and avoid any unauthorized access.

[Authorize]
public class YourAwesomeApiController: ApiController
Enter fullscreen mode Exit fullscreen mode

And there you have it! 🎉✨

You've now unlocked the secrets of integrating Azure Active Directory B2C in your ASP.NET 4.5 WebAPI, proving once and for all that old dogs can learn some fantastic new tricks! 🐶🎩

Happy coding and may your cloud adventures be filled with endless fun and success! 🌌💖✨

Top comments (0)