Building a Simple Sign-In Page with MSAL.js for Microsoft Identities
In this post I will discuss how I used MSAL.js to build a simple sign-in experience for Microsoft Identities, and some of the things I learned along the way.
I have worked with a lot of different people to onboard to Microsoft’s Identity system. Whether it be app registration, app development, or even debugging the login experience, people quickly learn that authentication and authorization isn’t always as straightforward as one might expect.
It is for that reason I think it is really important to build minimal, complete, and verifiable examples of the authentication process. I previously had built a minimal authentication sample for ADAL .NET using PowerShell, and this ended up having a number of different uses.
I want to do the same for MSAL.js!
- Create a login page
- Does not require a ‘web server’, just simple web hosting
- Can obtain an Access Token for a custom resource, with custom scopes
- (Stretch Goal) Allow a user to use their own App ID for getting an access token
Starting with a Minimal example
Although there is a
minimal.html file, I would not start there, since I do not feel that it follows the best practices of using the library. Instead, start with the
index.html which is still very raw, but includes an
applicationConfig object, functionalizes the login flow, and also has a basic UX.
One of the important things I came to realize was the importance of creating a global variable for the
MSAL.UserAgentApplication object. It seems to do a lot of different things like listen for the callback from the popup window that gets created, and captures the returned ID and access token to be ingested by the
acquireToken functions. I had mistakenly wrapped this variable into my login function, and the results were… weird.
When using the popup experience, the redirection happened WITHIN the popup itself rather than the main page where the sign-in experience was initiated.
This was a really awful experience, which then made me go down the path of switching
loginRedirect so that the user would stay on the same page the whole time. However, this then caused issues where the ID token would just end up in the URL as a fragment (
#) and the callback function which turned an ID token into an access token would not work anymore!
When I first was building this page, I actually ignored these problems, since I was working on a Hackathon, and I just needed to keep building. However, I can say that all of this really was caused simply by NOT having the
UserAgentApplication object in the global context.
SO DON’T DO THAT!
A working sample
You can find the end result of my simple sign-in page here:
Source code is on GitHub.
The page currently will sign you in, and get an access token to the Microsoft Graph with the scope
user.read. Additionally, it will show you your ID token and access token as both a raw JWT and in its decoded JSON format, which I teach how to do here.
Besides showing off MSAL.js in a really simple website, I think this app will be useful when trying to use other tools like Postman where you will need to have a valid access token, and generating one may not be so straight forward to the end user.
While this sample in its current form is pretty cool, it does not satisfy all the goals I listed above. That will be the next step for me on this project. I still need to figure out exactly how to call a custom API using a V2 application (which may not even be possible to configure right now until a new UX which a co-worker of mine is working on becomes available). However, allowing a user to input custom scopes should be really easy, and if others configure their own App ID to have my website as a redirect url, then I could see using a custom App ID to be really easy too.
I will be making this updates in the same GitHub I listed above, and you should see the changes directly on the same page as before! I hope this was useful for some of you, and if there are additional things I could add to make this project work better for you, just let me know through a GitHub issue.