OpenID Connect, outlined by RFC-6749, allows web based clients to authenticate end users with identity providers and acquire access-token to be used to access web resources, API’s, protected by OAuth 2.0 compatible frameworks.

Azure Active Directory is a identity management service offered by Microsoft hosted on Azure cloud platform. It offers management of user, group and roles within cloud instance of Active Directory. AAD supports all the handshakes outlined by RFC-6749. With a vast library of documents from Microsoft, it’s easy to go through the how-tos and quickly spin up a web app authenticating with AAD. But within the tutorials they mostly use complex libraries like ADAL.Js or MSAL.Js for client side authentication with AAD. The libraries are no-doubt very convenient to use and have lot of features. But libraries hides the inner management of urls and the parameters are requested with.

In this post we are going to examine the implicit grant of OIDC with AAD by creating a very simple web app. The source of the web app is available on GitHub and hosted at coderuse.github.io/aad-implicit-flow. Here we are not exploring the implicit flow in whole, rather trying to understand the redirections happens during the auhtentication. I would recommend to go through the links provided here for starter to understand better.

When we are working with browser for OAuth-2.0 authentication, it needs to be understood that urls that are being redirected to and from are very important. All the parameters are needed to be passed via urls and the responses are also needed to be parsed from urls. For this we need some utility methods to parse urls for response. These methods are taken from ADAL.Js.

The process starts with checking whether the access token is present in the url or not. For that we are using the following method.

function isSignInProgress() {
var result = false;

var hash = window.location.hash;
if (hash) {
hash = getHash(hash);
var parameters = deserialize(hash);
if (parameters) {
if (parameters.hasOwnProperty('error_description')) {
var errorDescription = parameters['error_description'];
return {
error: {
description: errorDescription
}
};
}
else if (parameters.hasOwnProperty('access_token')) {
return parameters['access_token'];
}
}
}

return result;
}

We invoke the above method from a time elapsed method by setTimeout like the following.

var intrvl = setInterval(function () {
var accessToken = isSignInProgress();
if (accessToken) {
clearInterval(intrvl);
if (accessToken.error) {
console.log(accessToken.error.description);
return;
}
else {
document.getElementById('id-access-token').value = accessToken;
console.log(accessToken);
}
}
// else { redirect to the provider to acquire token
// loginRedirect(tenant, clientId, scope);
//}
}, 3000);

Need for this timeout is to prevent auto-redirection. To take the input from user, the need to auto redirect the login page to authentication provider does not arise here. But in actual application, the required information are already present. So, no need to wait for login initiation by user, like we are doing in the demo app. Typically the page should be redirected from the else block of the above method.

function loginRedirect(tenant, clientId, scope) {
var loginUri = 'https://login.microsoftonline.com/' + tenant + '/oauth2/v2.0/authorize?';
var params = [];
params.push('client_id=' + clientId);
params.push('response_type=id_token token');
params.push('redirect_uri=https://coderuse.github.io/aad-implicit-flow/');
params.push('scope=openid ' + scope);
params.push('response_mode=fragment');
params.push('state=12345');
params.push('nonce=678910');
loginUri += decodeURIComponent(params.join('&'));

window.location.replace(loginUri);
}

Here we are using id_token token to get the access token in a single redirection. The recommended way of doing this is to first acquire the id_token and then acquire the access_token silently(without any further user inputs) via an iframe. But in reality, the second part, creating iframe and all does not work due to the restrictions posed by the modern browsers. And iframes should be discarded by all means in production deployments. And it’s really difficult to work with iframes on Cordova. So, a second redirection or creating a popup window with proper url containing the id_token is required to be invoked to get the access token.

Though implicit flow is recommended for browser app. In my opinion auth code flow is more appropriate than the prior one. We will have one more post with auth code flow.