Angular Azure — Auth, CI/CD, IaC, and Serverless — Part 1

Jay Watson
4 min readMay 23, 2021

Want to do it all? SPA, serverless, cloud, authentication, CI/CD pipeline, and IaC? Follow along and start building. In this lesson, we’ll create an Angular app and implement AAD authentication. In Part 2, we’ll create the IaC (for our Azure resources) and our DevOps pipeline. In Part 3, we’ll implement Azure Functions (NestJS) with Azure Table Storage.

Get Started with Angular

Get started with Angular
Photo by Blake Connally on Unsplash

If you don’t have the Angular CLI, install it. Then, use the CLI to create and serve a new Angular app.

npm install -g @angular/cli
ng new angular-msal <-- make sure that you get Angular routing
cd angular-msal
ng serve

Great, you’re up and running! Let’s add our dependencies.

npm i @azure/msal-angular --save
npm i @azure/msal-browser --save

Now, let’s create a couple of components and a route guard.

ng generate component public
ng g c private <-- shorthand
ng generate guard msal <-- choose 'CanActivate'

Let’s make it look decent. Go ahead and add Meshki, a simple, dark-colored, responsive boilerplate, to your index.html file.

<!--add in <head> 
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/meshki/2.3.0/css/meshki.min.css">
<!--add before closing </body>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/meshki/2.3.0/js/meshki.min.js"></script>

Hi Ho, Hi Ho, Off to Azure We Go

Photo by Thilak Mohan on Unsplash

Now, login in to Azure and go to Active Directory and click on App Registrations. Create a new App Registration.

Register your Spa and enter http://localhost:4200 as the redirect url.

Once the App Registration is complete, get your Application (client) ID from the Overview section. We’re done here.

Back to that ng Life

Go to your App Module (app.module.ts) and add a MsalInstanceFactory function below your imports.

import { IPublicClientApplication, PublicClientApplication } from '@azure/msal-browser';import { MsalModule, MsalService, MSAL_INSTANCE } from '@azure/msal-angular';import { HttpClientModule } from '@angular/common/http';export function MsalInstanceFactory(): IPublicClientApplication { return new PublicClientApplication({  auth: {   clientId: 'your client id',   redirectUri: 'http://localhost:4200'  } });}

Now, update the imports and providers arrays within your NgModule.

imports: [ BrowserModule, AppRoutingModule, MsalModule, HttpClientModule],providers: [{ provide: MSAL_INSTANCE, useFactory: MsalInstanceFactory }, MsalService]

Update App Component (app.component.ts).

Add

  • An active account check to ngOnInit
  • Is logged in check method
  • Login method
  • Logout method
import { HttpClient } from '@angular/common/http';import { Component } from '@angular/core';import { MsalService } from '@azure/msal-angular';import { AuthenticationResult } from '@azure/msal-common';@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss']})export class AppComponent { title = 'MSAL Authentication';constructor (private _authService: MsalService) { }ngOnInit(): void { this._authService.instance.handleRedirectPromise().then(res => {  if (res != null && res.account != null) {   this._authService.instance.setActiveAccount(res.account)  } })}isLoggedIn(): boolean { return this._authService.instance.getActiveAccount() != null}login() { // popup login this._authService.loginPopup()  .subscribe((response: AuthenticationResult) => {   this._authService.instance.setActiveAccount(response.account);  }); }}

Update the App Component view (app.component.html).

<div class="container">
<nav>
<ul>
<li><a [routerLink]="['/public']" routerLinkActive="true">Public</a></li>
<li>
<a [routerLink]="['/private']" routerLinkActive="true" *ngIf="isLoggedIn()">Private</a>
</li>
<li>
<a href="https://borderliner.github.io/Meshki/" target="_blank">Meshki</a>
</li>
<li *ngIf="isLoggedIn()" class="float-right"><a (click)="logout()">Logout</a></li>
<li *ngIf="!isLoggedIn()" class="float-right"><a (click)="login()">Login</a></li>
</ul>
</nav>
<div class="content">
<div *ngIf="isLoggedIn()">
<h3>You are logged in.</h3>
</div>
<div *ngIf="!isLoggedIn()">
<h3>You are not logged in.</h3>
</div>
</div>
<router-outlet></router-outlet>
</div>

Update App Routing Module (app-routing.module.ts). Note, that we are protecting our Private Component with the MSAL Guard.

import { MsalGuard } from './msal.guard';import { PrivateComponent } from './private/private.component';import { PublicComponent } from './public/public.component';const routes: Routes = [ { path: 'public', component: PublicComponent }, { path: 'private', component: PrivateComponent, canActivate: [MsalGuard] }, { path: '**', component: PublicComponent }];

We may be using our MSAL Route Guard, but it doesn’t work. Let’s change that (msal.guard.ts). We’re simply injecting the MsalService and using it to check whether or not a user has a valid login.

constructor(private _msalService: MsalService) { }canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { return this._msalService.instance.getActiveAccount() ? true : false;}

We’re fin. Everything should work now!

Thanks for following along! Let me know how it went! I’ll leave you with a homework assignment (I used to be a teacher :) ) Get the user’s name and display that after the user logs in.

Photo by Roman Synkevych on Unsplash

GitHub Repo Link

--

--