I've followed the steps at this link to setup a custom signin page for Azure AD B2C:
Which are essentially:
- Create a custom HTML file:
<!DOCTYPE html>
<html>
<head>
<title>My Product Brand Name</title>
</head>
<body>
<div id="api"></div>
</body>
</html>
Upload it to a file hosting service
In
Azure AD B2C
>User Flows
>[ your_sign_in_flow ]
, set the following:
Use custom page content: YES
Custom page URI: [ paste the URL of your hosted file here ]
Click Save
Click
Run User Flow
to test the flow
That produces this login page:
Where the HTML of the api
div is:
<div id="api" data-name="Unified">
<div class="heading">
<h1 role="heading">Sign in</h1>
</div>
<div class="claims-provider-list-buttons social" aria-label="Sign in with your social account" role="form">
<div class="intro">
<h2 aria-level="1">Sign in with your social account</h2>
</div>
<div class="options">
<div>
<button class="accountButton firstButton claims-provider-selection" id="AzureADPeople" role="link" autofocus="">Azure AD People</button>
</div>
</div>
</div>
<div class="divider">
<h2>OR</h2>
</div>
<form id="localAccountForm" action="JavaScript:void(0);" class="localAccount" aria-label="Sign in with your email address">
<div class="intro">
<h2 aria-level="1">
Sign in with your email address
</h2>
</div>
<div class="error pageLevel" aria-hidden="true" role="alert" style="display: none;">
<p></p>
</div>
<div class="entry">
<div class="entry-item">
<label for="email">
Email Address
</label>
<div class="error itemLevel" aria-hidden="true" role="alert" style="display: none;">
<p></p>
</div>
<input type="email" id="email" name="Email Address" title="Please enter a valid Email Address" pattern="^[a-zA-Z0-9!#$%&'+^_`{}~-]+(?:\.[a-zA-Z0-9!#$%&'+^_`{}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$" autofocus="" placeholder="Email Address" aria-label="Email Address">
</div>
<div class="entry-item">
<div class="password-label">
<label for="password">Password</label>
<u><a id="forgotPassword" href="/<my-tenant-name>.onmicrosoft.com/B2C_1_signin1/api/CombinedSigninAndSignup/forgotPassword?csrf_token=****==&tx=StateProperties=****&p=B2C_1_signin1">Forgot your password?</a></u>
</div>
<div class="error itemLevel" aria-hidden="true" style="display: none;">
<p role="alert"></p>
</div>
<input type="password" id="password" name="Password" placeholder="Password" aria-label="Password" autocomplete="current-password" aria-required="true">
</div>
<div class="working"></div>
<div class="buttons">
<button id="next" type="submit" form="localAccountForm">Sign in</button>
</div>
</div>
</form>
</div>
In order to be able to customise this page, I need to know how to do the following:
- Remove text elements if I don't want them displayed
- Modify text elements if I want to change the text strings
- Style text elements if I want them to have different font stylings
- Wrap various elements in divs with particular classes to be able to apply a design
(eg display the different sign in options as inline-blocks side by side etc)
My question is:
Is it permissible to do all of this via JavaScript (and CSS to hide/style text elements)?
Technically I think I could do it, but I'm not sure if it is allowed or best practice.
This page has a list of guidelines for using JavaScript in Azure AD B2C custom pages:
One of them is:
Don't take a dependency on Azure AD B2C code or comments.
But I'm not sure how elements can be customised without being able to reference the code within the api
div.
For reference, the Page Layouts
page does have a Version
setting, which makes me think that, if we keep the same version selected, the contents of the api
div would be unlikely to change (and therefore not break any JavaScript referencing particular divs etc).
Proof of Concept
I was able to create this custom signin page:
With this custom HTML page:
<!DOCTYPE html>
<html>
<head>
<title>My Custom Login Page</title>
<!-- links to CSS framework -->
<script src="https://cdn.jsdelivr.net/npm/uikit@3.15.19/dist/js/uikit.min.js" integrity="sha256-gHEvLzvpjU93VFTgu5myAgmc+0I1CzBzYe0YhTJ8uqI=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/uikit@3.15.19/dist/js/uikit-icons.min.js" integrity="sha256-PxrcCuBlFkPVlPsGxNzt59W3EKYOH79z+v/tq9uFS2M=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.15.19/dist/css/uikit.min.css" integrity="sha256-f3SVFXP30MgahZ0Z7Lp1W02MuLgtiAtk8uFqTbGxNfY=" crossorigin="anonymous">
<!-- links to google fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Josefin+Sans:wght@200&family=Noto+Sans+Ethiopic:wght@300&display=swap" rel="stylesheet">
<!-- CSS styles -->
<style>
#api {
width: 300px;
padding: 25px 40px 40px 40px;
border: 1px solid #000;
margin: 0 auto;
margin-top: 50px;
}
.heading {
text-align: center;
}
h1 {
font-family: 'Josefin Sans';
color: #000;
text-decoration: none;
text-transform: uppercase;
font-size: 45px;
margin-bottom: 0px;
}
.tagline {
margin: -5px 0px 25px 0px;
padding: 0px;
display: block;
font-size: 14px;
color: #727272;
}
h2 {
font-size: 14px;
line-height: 12px !important;
margin-bottom: 10px;
}
.social {
margin-top: 30px;
}
#forgotPassword {
font-size: 14px;
margin-left: 5px;
text-transform: lowercase;
}
.uk-input:focus,
.uk-select:focus,
.uk-textarea:focus {
border-color: #e5e5e5 !important;
}
</style>
<!-- jQuery to get things looking the way I want -->
<script>
$(document).ready(function() {
console.log("document is ready apparently");
// hacky - put in a delay of 1 second to wait for the 'api' div content to be added
setTimeout(() => {
console.log("Delayed for 1 second.");
$(".heading h1").text("APP");
$( "<span class='tagline'>Tagline Goes Here</span>").insertAfter( ".heading h1" );
$("#localAccountForm .intro h2").text("External Users");
$(".social h2").text("Internal Users");
$("label[for='email'], label[for='password']").remove();
$("input").addClass("uk-input");
$("#email").addClass("uk-margin-small-bottom");
$("button").addClass("uk-button uk-button-default uk-button-small uk-margin-small-top");
$("#AzureADPeople").text("Single Sign-On");
$('.divider').remove();
$('.social').insertAfter('#localAccountForm');
$('.password-label').insertAfter('#password');
}, "1000");
});
</script>
</head>
<body>
<!-- this is the only thing required for a custom page -->
<div id="api"></div>
</body>
</html>