Azure AD Auth with MSAL in Angular and ASP.NET Core API
Learn how to implement Azure AD authentication in your Angular app using MSAL and connect it securely with ASP.NET Core Web API. Step-by-step setup included.
This part 2 is continuous of Part-1 where we covered the JWT authentication API code.
You will start by installing the all the Pre-requisition to create Angular project if you have not created you can CLICK HERE to follow the steps and create new Angular project to start with JWT Authentication.
Before we start actual implementation, let’s briefly understand what JWT is.
JWT stands for JSON Web Token and it's an open source standard that states how to securely exchange information between client and server.
You can install JWT Authentication in your Angular 8 application and where you can use like sessions and cookies.
Before we start JWT Authentication we require to install the below package.
npm install @auth0/angular-jwt
Step 1: Login Component
Step 2: Storing JWT token to client-Side and it used
Step 3: Sending JWT token on each API request.
Step 4: Validating each request on client-side
We require to create new component for login and below is code for HTML and Typescript code.
<form (ngSubmit)="onLogin()" [formGroup]="loginForm" novalidate>
<div class="form-width">
<div class="form-label">
<span>Email</span>
</div>
<div class="form-control">
<input type="email" formControlName="email" placeholder="Email" required spellcheck="false"
autocapitalize="off" name="email" autocomplete="off"><br/>
<div class="validationError" *ngIf="isSubmitted && formControls.email.errors">
<div *ngIf="formControls.email.errors.required">Email is required</div>
</div>
</div>
<div class="form-label">
<span>Password</span>
</div>
<div class="form-control">
<input type="password" formControlName="password" placeholder="Password" required autocomplete="off"><br/>
<div class="validationError" *ngIf="isSubmitted && formControls.password.errors">
<div *ngIf="formControls.password.errors.required">Password is required</div>
</div>
</div>
<div class="submit-button">
<button color="primary" type="submit">
Login
</button>
</div>
</div>
<div class="errorMessage">
{{errorMessage}}
</div>
</form>
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { Router } from '@angular/router';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import 'rxjs';
import { Observable } from 'rxjs';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
errorMessage = '';
loginForm: FormGroup;
isSubmitted = false;
@Output() loggedIn: EventEmitter = new EventEmitter();
@Output() logInFailure: EventEmitter = new EventEmitter();
constructor(
private router: Router,
private formBuilder: FormBuilder
) {
this.loginForm = this.formBuilder.group({
email: ['', Validators.required],
password: ['', Validators.required]
});
}
ngOnInit(): void {
}
get formControls(): any {
return this.loginForm.controls;
}
onLogin(): void {
this.isSubmitted = true;
if (this.loginForm.invalid) {
return;
}
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
const loginModel = {
this.loginForm.value.email,
this.loginForm.value.password
};
this.http.post(‘api/login’, loginModel, httpOptions)
.subscribe(
(data: any) => {
if (data.success) {
localStorage.setItem('LoggedInUser', JSON.stringify(data));
this.router.navigate(['/home]);
} else {
this.errorMessage = data.errorMessage;
this.logInFailure.emit(true);
}
},
(error: any) => {
this.errorMessage = 'API is unreachable. Please check your internet connection.';
this.logInFailure.emit(true);
}
);
}
}
….
this.http.post(‘api/login’, loginModel, httpOptions)
.subscribe(
(data: any) => {
if (data.success) {
localStorage.setItem('LoggedInUser', JSON.stringify(data));
localStorage.setItem(‘token’, data.access_token);
this.router.navigate(['/home]);
} else {
this.errorMessage = data.errorMessage;
this.logInFailure.emit(true);
}
},
(error: any) => {
this.errorMessage = 'API is unreachable. Please check your internet connection.';
this.logInFailure.emit(true);
}
);
….
To sending each request to JWT token while call API need to override the http request and for that require to create http Interceptor.
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { AuthenticationService } from '../services/authentication.service';
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(public authenticationService: AuthenticationService) {
}
intercept(request: HttpRequest, newRequest: HttpHandler): Observable> {
const authtoken = this.authenticationService.authenticationToken.value;
if (authtoken !== '') {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${authtoken}`
}
});
}
return newRequest.handle(request);
}
}
To validate each request on the client side on each routing of the page require to create the common auth.gurd service and which we can add in routing module.
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { AuthenticationService } from '../services/authentication.service';
import { JwtHelperService } from '@auth0/angular-jwt';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AuthGuardService implements CanActivate {
constructor(public authService: AuthenticationService,
private router: Router) {}
canActivate(): Observable |Promise | boolean {
const userData = this.authService.getLoggedInUserData();
if (userData === undefined) {
this.router.navigate(['/']);
return false;
} else {
const token = userData.access_token;
const helper = new JwtHelperService();
const isExpired = helper.isTokenExpired(token);
if (isExpired) {
this.router.navigate(['/']);
return false;
}
}
return true;
}
}
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './home';
import { LoginComponent } from './login';
import { AuthGuard } from './AuthGuardService ;
const appRoutes: Routes = [
{
path: '',
component: HomeComponent,
canActivate: [AuthGuard]
},
{
path: 'login',
component: LoginComponent
},
// otherwise redirect to home
{ path: '**', redirectTo: '' }
];
export const routing = RouterModule.forRoot(appRoutes);
I hope that this post helps with that and that you enjoyed it!
Learn how to implement Azure AD authentication in your Angular app using MSAL and connect it securely with ASP.NET Core Web API. Step-by-step setup included.
Step-by-step guide to implement Google OAuth2 authentication in ASP.NET Core. Secure your app with Google sign-in, token validation, and user claims.
Learn how to implement Facebook OAuth2 login in ASP.NET Core. Step-by-step guide to configure app ID, secret, and secure authentication with user claims.
Learn how to implement JWT authentication using ASP.NET Core backend and Angular 8 frontend. Secure your app with token-based login in this step-by-step guide.
Get in touch with Prishusoft – your trusted partner for custom software development. Whether you need a powerful web application or a sleek mobile app, our expert team is here to turn your ideas into reality.