Angular and Azure AD
Hello, world! In this post I do a basic implementation of an Angular6 Single Page Application (SPA) using Azure AD to authenticate users. It assumes you have an Azure AD domain and Angular6 experience.
By clicking on New application registration, a form is displayed with some information required:
Name identifies the application to use the information stored in Azure AD. Application type must be Web app / API and for the Sign-on URL the development URL used by Angular6 is used (http://localhost:4200). Once the Create button is clicked and the application is created, the following information is shown:
The most important data is the Application ID which will be used later from within Angular.
Intentionally it has been named after the one used during the Azure AD application registration but it doesn't have to be so. Authentication is to take place in the AuthService created with the following CLI command:
The project should partially look like this in Visual Studio Code:
Back in the AuthService, an import statement is required:
...and it is ready to interact with Azure AD. It starts with creating an instance of Msal.UserAgentApplication as shown below:
Where several interesting things happen:
More interesting points are to be explained:
And below is the modified app.component.ts
Or, if you prefer, npm like this:
And one of the most beautiful pages in the world is shown:
As it can be seen, there are no username and password input fields because that's one point of using an Identity Provider like Azure AD. When the user clicks on the Login button, she will be redirected to the login page in the configured Azure AD domain (in this case, illyum):
After entering the user address and clicking Next, the page for entering the password is shown:
And, after entering the password and clicking Sign in, only for the first login, the consent page appears:
This is where the user gives permissions for the application to sign her in, read her profile, and access her data anytime. This is related to OAuth2 and Microsoft Graph that I will talk about those in a future post. After clicking Accept, the user is officially logged in. From here, all she can do is click on the logout button and confirm the action.
Ok, I think it's enough for now. The code is available here for this and future commits. Of course, you have to use your Azure AD domain and related stuff. In the next article, Angular6 and Azure AD with a Better UX, I am going to improve the SPA UX and do some work with the Identity Token. See you there...
Note: I strongly recommend you to read about OpenID, OAuth2, and how Microsoft supports those. In particular, take a look at "OAuth 2.0 - Looking Back and Moving On" by Eran Hammer. It's awesome!
Azure AD
Azure AD plays the role of an Identity Provider or IdP. It supports OpenID and OAuth so everything you learn about those are more than very welcome to have a better understanding of what is setup and configured in the Azure portal starting with the app registration in the domain where it will be used. In this case, it is an Angular6 SPA web app in my domain (illyum). Below is the Azure portal page where the registration takes place:![]() |
Azure AD Application Registration |
By clicking on New application registration, a form is displayed with some information required:
Name identifies the application to use the information stored in Azure AD. Application type must be Web app / API and for the Sign-on URL the development URL used by Angular6 is used (http://localhost:4200). Once the Create button is clicked and the application is created, the following information is shown:
The most important data is the Application ID which will be used later from within Angular.
Note: In terms of OAuth2, a SPA requires the implicit flow or client-based flow.
Angular6
Now, it is time to use the Angular CLI to create the SPA like this:ng new ng6aad
ng generate service core/auth
Microsoft Authentication Library (MSAL)
Microsoft provides libraries for a number of programming languages that allows writing applications to interact with Azure AD. For Angular6 the Microsoft Authentication Library for JavaScript (MSAL.js) will be used through npm like this:npm install msal --save-dev
import * as Msal from 'msal';
import * as Msal from 'msal'; import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class AuthService { private userAgentApplication: Msal.UserAgentApplication; constructor() { this.userAgentApplication = new Msal.UserAgentApplication( '55f4dfa9-2425-44f0-83a6-d3464b2a7eaa', 'https://login.microsoftonline.com/illyum.onmicrosoft.com', null ); } }
- It creates and holds a reference to an instance of Msal.UserAgentApplication.
- The first ctor argument is the Application ID obtained during registration. In this case 55f4dfa9-2425-44f0-83a6-d3464b2a7eaa. In the OpenID lexicon this is the Client ID and it should be considered a synonym for Application ID.
- The second argument is the Authority: a URL indicating a directory that MSAL can request tokens from. It is of the form https://<instance>/<tenant> where <instance> is the directory host (e.g. https://login.microsoftonline.com) and
is an identifier within the directory itself which, in this case, is illyum.onmicrosoft.com and it certainly will be different in yours. - Hard-coded credentials, keys, or any type of secret is not to be handled like this in a production environment but that's another topic.
import * as Msal from 'msal'; import { Injectable } from '@angular/core'; import { Observable, from } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class AuthService { private userAgentApplication: Msal.UserAgentApplication; constructor() { this.userAgentApplication = new Msal.UserAgentApplication( '55f4dfa9-2425-44f0-83a6-d3464b2a7eaa', 'https://login.microsoftonline.com/illyum.onmicrosoft.com', null ); } public login(): Observable<string> { const graphScopes = ['user.read']; const promise = this.userAgentApplication.loginPopup(graphScopes); promise.catch(error => console.log(`loginPopup error = ${error}`)); return from(promise); } public logout(): void { this.userAgentApplication.logout(); } }
- MSAL.UserAgentApplication provides the method loginPopup for the user to authenticate by redirecting her to the Azure AD login page.
- The argument graphScopes put us in contact with Microsoft Graph, another important piece of Azure AD that is beyond this post but I promise to treat in a future post. At this point, it should be enough to say that ['user.read'] will ask user's consent for the app to read her data.
- AuthService delegates the logout method to the MSAL.UserAgentApplication logout method.
- console.log is not the kind of logging to be used in a production environment but that's another topic.
<div style="text-align:center"> <h1> Welcome to {{ title }}! </h1> </div> <button (click)='login()'>Login</button> <button (click)='logout()'>Logout</button>
import { Component } from '@angular/core'; import { AuthService } from './core/auth.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Angular and Azure AD'; constructor(private authService: AuthService) { } login(): void { this.authService.login(); } logout(): void { this.authService.logout(); } }
Running the Angular6 SPA
It's time to use the Angular CLI to start the SPA like this:ng serve --open
npm start
As it can be seen, there are no username and password input fields because that's one point of using an Identity Provider like Azure AD. When the user clicks on the Login button, she will be redirected to the login page in the configured Azure AD domain (in this case, illyum):
After entering the user address and clicking Next, the page for entering the password is shown:
And, after entering the password and clicking Sign in, only for the first login, the consent page appears:
This is where the user gives permissions for the application to sign her in, read her profile, and access her data anytime. This is related to OAuth2 and Microsoft Graph that I will talk about those in a future post. After clicking Accept, the user is officially logged in. From here, all she can do is click on the logout button and confirm the action.
Ok, I think it's enough for now. The code is available here for this and future commits. Of course, you have to use your Azure AD domain and related stuff. In the next article, Angular6 and Azure AD with a Better UX, I am going to improve the SPA UX and do some work with the Identity Token. See you there...
Thank you very much for sharing this.
ReplyDeleteDo you have plans to share how to design and implement equivalent operations but with AWS?
Yes, AWS is coming to a post near you!
Delete