You are currently viewing Creating Custom Login Page in Azure AD B2C

Creating Custom Login Page in Azure AD B2C

Few months back, I was going through the MSAL and how Azure AD can be used with different types of applications, how authentication can be configured, etc.

This is an extension to the MSAL series posts written few months back. If you want to go through the previous posts in MSAL series, below are the links for ready reference.

Why this post ?

I received quite some comments mails about the MSAL series and how it is helping people. Some of the readers asked this question – can I use the Azure AD MSAL for authentication and still use my custom login page ? There is also stackoverflow question asking the same thing.

I have already covered in one of the posts in the series that the login pages are by default provided by Azure AD service. Those login pages can be customized and the brand information, colors, background images can be changed to make the look and feel similar to your web application. All those configurations are very easy and can be done very quickly.

If this is not sufficient, then you can go for having a custom login page. But obviously, in this case, the efforts required would be higher than just customizing the default pages. If you still want to go for it, then this post would cover the step by step information on how to set it up.

Please note that you should always have a look at the customization options provided by the the Company branding feature. Most of the customizations can be done using that feature as explained in my previous blog post. If this feature is not helping you to achieve the intended outcome, then only you should try the next steps.


For this demo, you will need Azure Subscription. If you don’t have an Azure subscription, create a free account before you begin.

Also, you can refer the article – Protect .NET Core Angular App with Azure AD B2C – to setup the Azure AD B2C and a web application which is protected by that AD instance.

The Idea

The idea is to have a custom HTML page instead of Azure AD’s login page, so that the consumer should be able to modify look and feel, theme etc. so that the page looks very similar to consumer’s site.

Please note that it does not cover showing login page as popup on the site.

So, let’s get started !

Custom HTML Rules

In this section, we are going to see how to create a custom HTML for the sign-in page. But before directly jumping into steps of creating the HTML, let’s first understand the rules to be taken care of.

  • The HTML can be either static HTML or it can also be a dynamic page created using .NET, PHP, etc.
  • The page can include CSS and JS, but it cannot include insecure elements like iframes, frames, or forms..
  • The only requirement from Azure AD is there should be an empty div element, with id="api"
  • You can host your new page on any public service, that supports HTTPS and CORS.
  • Using page layout version 1.2.0 and above, you can add the data-preload="true" attribute in your HTML tags to control the load order for CSS and JavaScript.  This would help in avoiding the flickering issues.
  • Safari, Mozilla, Chrome and Edge are the main supported browsers. For details about versions refer the documentation.
  • It is recommended to start from the source code of Azure AD B2C pages, host them, get them working, and then build on top of this to ensure everything works. Refer the exception.html for the source code of default pages.

High Level Steps

Below are high level steps for our intended setup:

  • Develop: Download and customized the default file
  • Prepare Host: We will use storage account for hosting the static HTML page. Once you understand the conceptual implementation, it should be easy to extend the concept and host the page anywhere publicly available CORS enabled HTTPS endpoint.
  • Publish the custom HTML file from step 1 to publicly available CORS enabled HTTPS endpoint.
  • CORS: Set cross-origin resource sharing (CORS) for your web app.
  • Update User Flow: Point your policy to your custom policy content URI.


I will skip explaining the below code. It is a HTML / CSS / JS combo with default div with id set to api. Just copy this to start setting up the custom page.

If you open the HTML file in browser, it should be rendered as shown in below snapshot:

Locally viewing the custom HTML

Prepare Host – Storage Account & Container

We will use simplest method – storage accounts and blob containers to host the web page. Please refer this previous blog post for step by step guide on how to create a storage account and a container.

Below snapshot shows important inputs on first screen of wizard. Rest of the inputs can be left to their default values.

Azure Portal: Create new storage account

Once storage account is created, create a blob container with name root. Below snapshot highlights the inputs required for this container creation. Please make sure you select public access level as shown in the snapshot.

Azure Portal: Create new container


Now, upload the file to the root container that we have created in previous step.

For this, you will have to open the container by clicking on it and then on the new panel, select Upload button from the Overview panel as shown below.

Clicking on upload will open a new right side panel, where you can select the file and keep rest of the inputs to their default values. Then click on Upload button on right hand side panel.

Azure Portal: upload a blob to the container


Now, let’s navigate to the storage account that you have created in previous step. Then select CORS option from the left side navigation and then enter below inputs:

  • Allowed Origins, Please replace tenant-name with the name of your Azure AD. Ensure that there is no trailing slash at the end of input URL.
  • Allowed Methods, select two options from dropdown GET and OPTIONS
  • Allowed Headers, enter ‘*
  • Exposed Headers, enter ‘*
  • Max Age, provide the value 200.

Once these inputs are provided, click on Save button to save the settings.

Azure Portal: set CORS for the storage account

For testing purpose, let’s add another entry.

Repeat the same steps to add another entry in the CORS settings table. This time use as the Allowed Origins url and rest of the inputs should be same as in previous row.

The site allows you to send the XHR request to local or remote URL.

Navigate to and enter the remote URL of your HTML page. The URL of HTML page would be something like, where storage-account-name should be replaced by the actual name of the storage account. Then hit the Send Request button.

This should return XHR Status: 200 in the response. If it is not 200 OK response, then you might have missed a step in CORS configuration so validate your settings before proceeding further.

Update User Flow

If you do not know about user flows, I would suggest to please go through this post to get the basic concepts.

So, switch to the Azure AD B2C directory now and search for Azure AD B2C in the search box and select the entry. Then select User Flows under Policies. Select the user flow which is applicable for the site and then select Page layouts menu option from the next page.

In the user flow page layouts, select Unified sign up or sign in page entry and then provide below inputs:

  • Use custom page content should be toggled and set it to Yes.
  • Custom Page URI should be set to the, where storage-account-name should be replaced by the actual name of the storage account.

Let other inputs as they are. Then click on Save button.

Azure Portal: Update user flow page layouts


To verify the changes, you can either run the user flow from edit page layout screen OR you can try to access the protected application via browser. If you are not logged in to it, the Azure AD would show our custom html on the login page.

The login page would look something similar to the below snapshot.

Azure AD B2C: Custom HTML for unified sign in page.

Yay, we have successfully configured custom HTML for the Azure AD B2C login page. The sign in section is still not fully styled, but I hope you have got the conceptual idea.

As recommended in the documentation, you can start with the HTML and CSS of the default pages and then build up on that template to achieve the intended result.

I hope you liked this new article from the Azure AD series. Let me know your thoughts.

Leave a ReplyCancel reply

This Post Has 18 Comments

  1. Viktor Balassa

    Hy Manoj Choudhari,

    thanks you blog post about custom site in AD!
    As I understand your approach you were wrap an exsisting custom policy (

    ) content within custom html code. Is this statement true? If yes do u know any solution to manipulate (Add new, modify existing) the elements under the

    part and not using custom JS?



    1. Manoj Choudhari
      Manoj Choudhari

      If I understand correctly, you are asking if [div id=’api’] contents can be changed or not. As per documentation they cannot be changed. Hope this helps.

      1. Viktor Balassa

        Yep that was I asked. Thanks the answer!
        Also can u verify my other statement: the solution of this blogpost is kind of wrapping the azure content ([div id=’api’]) into a custom html structure?


      2. Manoj Choudhari
        Manoj Choudhari

        Yes. That is the solution provided in the blogpost.

  2. sachingangarde

    Hey, how to associate this User Flow with tenant applications? I have followed same steps but still seeing default login UI for tenant applications.

    1. Manoj Choudhari
      Manoj Choudhari

      Without looking your code, I cannot tell which step has gone wrong. But these steps should certainly show you custom login page.
      Make sure that you are working with Azure AD B2C tenant and not B2B tenant.

      Also, below are the mistakes I did while working on this POC. Probably, you also might have missed one of those things:
      – Correct user flow is not modified
      – Information is modified, but save button is not hit after changing the URL.

      I hope this information helps you.

    1. Manoj Choudhari
      Manoj Choudhari

      Glad to know the article helped. I never personally tried it, but I think the steps should be almost the same.

  3. madhurabindu

    Thank you for this post.

    I am trying to create a singin with phone.
    This documentation seems to suggest the sign in with phone will have first step phone number, second page country code and then verification code

    I have a requirement to make all three into a single page.
    From your article i understand that HTML customization is milited to the look and feel and I will not be able to play with what is in


    div id=”api”> is that correct?

    Secondly I am exploring custom policies and thats no piece of cake either. Do you have blog posts and know of articles that cover what I am looking for?
    Lastly, is there anyway that I can create new elements using javascript and achieve this?

    1. Manoj Choudhari
      Manoj Choudhari

      My thoughts:
      1. I think you cannot modify div id=’api’
      2. I do not understand what do you mean by “making 3 into a single page”. Three pages have different URLs and you can either customize the page (by changing policies – or you can completely try to create a custom HTML similar to what explained in this article to make sure three pages look similar, but I think they cannot be “made into a single page”.


    This Post is very helpful.
    Can I host custom login page within the application instead of Storage Accounts.

    1. Manoj Choudhari
      Manoj Choudhari

      You can host the page anywhere. As long as it is reachable from Azure AD B2C and CORS are allowing requests from Azure AD B2C, it should be ideally fine.

      1. Manoj Choudhari
        Manoj Choudhari

        Hey Alok, I never tried this before. I will post an article in case I find any information around this.

  5. mohammed nathar

    i am trying to run my custom page in localhost:3000. but i am unable to see the screen ( blank ) but if i host it in blob container the screen is visible.
    i would like to know if its even possible to use localhost or not.
    is hosting in public access point the only approach. Please let me know

    1. Manoj Choudhari
      Manoj Choudhari

      as far as I know I think public access site is the only option.