Introduction
This blog is going to showcase to you how we can implement Azure AD with web API and Angular application.
![Azure AD Integration with Angular and ASP.NET Core Web API]()
To connect azure ad with angular and asp.net core web API 5.0.
There are four-step processes to implement Azure AD in angular and asp.net core web API.
Step 1
Create Azure AD Account and Register the SPA(Single Page Application ) application in Azure AD App Registration blade.
![Azure AD Integration with Angular and ASP.NET Core Web API]()
![Azure AD Integration with Angular and ASP.NET Core Web API]()
First, click on the App Registration button and then click on New Registration Button.
![Azure AD Integration with Angular and ASP.NET Core Web API]()
Fill in the Register Application Details.
![Azure AD Integration with Angular and ASP.NET Core Web API]()
![Azure AD Integration with Angular and ASP.NET Core Web API]()
After clicking on the Register button. SPA application successfully gets registered and on the overview page, you get the register application details like Client ID, Tenant ID, etc.
![Azure AD Integration with Angular and ASP.NET Core Web API]()
Step 2
Register Web API applications in the same way. But in the API registration process, we do not need to provide the application redirect URL because our SPA Application is used to redirect the page.
![Azure AD Integration with Angular and ASP.NET Core Web API]()
![Azure AD Integration with Angular and ASP.NET Core Web API]()
Then need to Expose An API,
![Azure AD Integration with Angular and ASP.NET Core Web API]()
![Azure AD Integration with Angular and ASP.NET Core Web API]()
After successfully exposing the API and scope has been added you need to go into the SPA application and add the permission for this API. Follow the process and click as per the number in below pic.
![Azure AD Integration with Angular and ASP.NET Core Web API]()
Step 3
Go to VS Code and Create New application in Angular, do the below changes. Add the below packages and do the npm install.
![Azure AD Integration with Angular and ASP.NET Core Web API]()
Add Auth-Config File and do the below settings as per the SPA application Registered.
![Azure AD Integration with Angular and ASP.NET Core Web API]()
Add below setting in App.Module.ts,
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { TodoEditComponent } from './todo-edit/todo-edit.component';
import { TodoViewComponent } from './todo-view/todo-view.component';
import { TodoService } from './todo.service';
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
import { IPublicClientApplication, PublicClientApplication, InteractionType } from '@azure/msal-browser';
import { MsalGuard, MsalInterceptor, MsalBroadcastService, MsalInterceptorConfiguration, MsalModule, MsalService, MSAL_GUARD_CONFIG, MSAL_INSTANCE, MSAL_INTERCEPTOR_CONFIG, MsalGuardConfiguration, MsalRedirectComponent } from '@azure/msal-angular';
import { msalConfig, loginRequest, protectedResources } from './auth-config';
export function MSALInstanceFactory(): IPublicClientApplication {
return new PublicClientApplication(msalConfig);
}
export function MSALInterceptorConfigFactory(): MsalInterceptorConfiguration {
const protectedResourceMap = new Map < string,
Array < string >> ();
protectedResourceMap.set(protectedResources.todoListApi.endpoint, protectedResources.todoListApi.scopes);
return {
interactionType: InteractionType.Redirect,
protectedResourceMap
};
}
export function MSALGuardConfigFactory(): MsalGuardConfiguration {
return {
interactionType: InteractionType.Redirect,
authRequest: loginRequest
};
}
@NgModule({
declarations: [
AppComponent,
HomeComponent,
TodoViewComponent,
TodoEditComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
AppRoutingModule,
HttpClientModule,
FormsModule,
MsalModule
],
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: MsalInterceptor,
multi: true
}, {
provide: MSAL_INSTANCE,
useFactory: MSALInstanceFactory
}, {
provide: MSAL_GUARD_CONFIG,
useFactory: MSALGuardConfigFactory
}, {
provide: MSAL_INTERCEPTOR_CONFIG,
useFactory: MSALInterceptorConfigFactory
},
MsalService,
MsalGuard,
MsalBroadcastService,
TodoService
],
bootstrap: [AppComponent, MsalRedirectComponent]
})
export class AppModule {}
App.Component Settings,
import { Component, OnInit, Inject, OnDestroy } from '@angular/core';
import { MsalService, MsalBroadcastService, MSAL_GUARD_CONFIG, MsalGuardConfiguration } from '@azure/msal-angular';
import { AuthenticationResult, InteractionStatus, InteractionType, PopupRequest, RedirectRequest } from '@azure/msal-browser';
import { Subject } from 'rxjs';
import { filter, takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy {
title = 'Azure Ad Testing Demo';
isIframe = false;
loginDisplay = false;
private readonly _destroying$ = new Subject < void > ();
constructor(@Inject(MSAL_GUARD_CONFIG) private msalGuardConfig: MsalGuardConfiguration, private authService: MsalService, private msalBroadcastService: MsalBroadcastService) {}
ngOnInit(): void {
this.isIframe = window !== window.parent && !window.opener;
/**
* You can subscribe to MSAL events as shown below. For more info,
* visit: https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-angular/docs/v2-docs/events.md
*/
this.msalBroadcastService.inProgress$.pipe(filter((status: InteractionStatus) => status === InteractionStatus.None), takeUntil(this._destroying$)).subscribe(() => {
this.setLoginDisplay();
});
}
setLoginDisplay() {
this.loginDisplay = this.authService.instance.getAllAccounts().length > 0;
}
login() {
if (this.msalGuardConfig.interactionType === InteractionType.Popup) {
if (this.msalGuardConfig.authRequest) {
this.authService.loginPopup({
...this.msalGuardConfig.authRequest
}
as PopupRequest).subscribe((response: AuthenticationResult) => {
this.authService.instance.setActiveAccount(response.account);
});
} else {
this.authService.loginPopup().subscribe((response: AuthenticationResult) => {
this.authService.instance.setActiveAccount(response.account);
});
}
} else {
if (this.msalGuardConfig.authRequest) {
this.authService.loginRedirect({
...this.msalGuardConfig.authRequest
}
as RedirectRequest);
} else {
this.authService.loginRedirect();
}
}
}
logout() {
this.authService.logout();
}
// unsubscribe to events when component is destroyed
ngOnDestroy(): void {
this._destroying$.next(undefined);
this._destroying$.complete();
}
}
app.component.html settings,
<mat-toolbar color="primary">
<a class="title" href="/">{{ title }}</a>
<div class="toolbar-spacer"></div>
<a mat-button [routerLink]="['todo-view']">TodoList</a>
<button mat-raised-button *ngIf="!loginDisplay" (click)="login()">Login</button>
<button mat-raised-button color="accent" *ngIf="loginDisplay" (click)="logout()">Logout</button>
</mat-toolbar>
<div class="container">
<!--This is to avoid reload during acquireTokenSilent() because of hidden iframe -->
<router-outlet *ngIf="!isIframe"></router-outlet>
</div>
<footer *ngIf="loginDisplay">
<mat-toolbar>
<div class="footer-text"> How did we do? </div>
</mat-toolbar>
</footer>
Index.html settings,
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>AzureDemoSPA</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.svg">
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>
<app-root></app-root>
<app-redirect></app-redirect>
</body>
</html>
Step 4 - Web API settings
In AppSettings.json file add your Registered API tenant and Client ID and Domain name information.
![Azure AD Integration with Angular and ASP.NET Core Web API]()
From Nuget Package manager add microsoft.identity.web package and do the changes in startup’s file.
using AzureAdAPIDemo.Models;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Identity.Web;
using Microsoft.OpenApi.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace AzureAdAPIDemo {
public class Startup {
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
public IConfiguration Configuration {
get;
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
// Setting configuration for protected web api
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddMicrosoftIdentityWebApi(Configuration);
// Creating policies that wraps the authorization requirements
services.AddAuthorization();
services.AddDbContext < TodoContext > (opt => opt.UseInMemoryDatabase("TodoList"));
services.AddControllers();
// Allowing CORS for all domains and methods for the purpose of the sample
// In production, modify this with the actual domains you want to allow
services.AddCors(o => o.AddPolicy("default", builder => {
builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
}));
services.AddSwaggerGen(c => {
c.SwaggerDoc("v1", new OpenApiInfo {
Title = "AzureAdAPIDemo", Version = "v1"
});
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "AzureAdAPIDemo v1"));
}
app.UseCors("default");
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
});
}
}
}
Then use [Authorize ] on any controller.
![Azure AD Integration with Angular and ASP.NET Core Web API]()
![Azure AD Integration with Angular and ASP.NET Core Web API]()
After clicking the login button,
![Azure AD Integration with Angular and ASP.NET Core Web API]()
Select the account and log in successfully.
![Azure AD Integration with Angular and ASP.NET Core Web API]()
Summary
Follow the above steps and secure your solutions.