Azure Active Directory Integration In Angular 9 And Web API Core 3.1

Introduction 

 
In this article, we will integrate the Azure Active Directory into an Angular application and get data from a secured web API using a JWT bearer token. There will be 3 steps to integrate the Azure Active Directory into our application.
  • Configure Azure active directory for our application:
    • Please log into the Azure portal using your credentials.
    • Select the Azure Active Directory icon/blade.



    • Select the App registration blade and then click new registration. Enter your application name.



    • In my case, the name was “azure-ad-integration”. Select the support account types. I selected “Accounts in this directory only”.

    • Then you can set “Redirect URI”, although it is an optional field. For my case, I selected “Web” and set its value to http://localhost:4200
    • Then click the “Register” button. You'll see the application's Overview or the main registration page.
    • The important details here are the client and tenant ids. Note these down in Notepad or similar, you'll need them later.
    • Then go to the "Authentication" blade and select "Access Tokens" and "ID tokens" from the implicit grant.
    • Then go to "Expose an API" then select "Add a scope" from Scopes defined by this API. Put all the necessary information and save it.

    • Your Azure application is ready for production.
  • Create an Angular 9 application

    • Create an angular application using the following command

      ng new azure-ad-client
    • Add a package using the following command:

      npm install --s @azure/msal-angular
 In your app.module.ts, add following code:
  1. const isIE = window.navigator.userAgent.indexOf('MSIE ') > -1 || window.navigator.userAgent.indexOf('Trident/') > -1;  
  2. @NgModule({  
  3.   declarations: [  
  4.     AppComponent,  
  5.     ProfileComponent  
  6.   ],  
  7.   imports: [  
  8.     BrowserModule,  
  9.     AppRoutingModule,  
  10.     HttpClientModule,  
  11.     MsalModule.forRoot({  
  12.       auth: {  
  13.         clientId: environment.clientId,  
  14.         authority: environment.authority,  
  15.         redirectUri: environment.redirectUrl,  
  16.         postLogoutRedirectUri: environment.postLogoutRedirectUri,  
  17.         navigateToLoginRequestUrl: true  
  18.       }, cache: {  
  19.           cacheLocation: 'localStorage',  
  20.           storeAuthStateInCookie: isIE, // set to true for IE 11  
  21.         },  
  22.   }, {  
  23.     popUp: !isIE,  
  24.     consentScopes: [  
  25.       'user.read',  
  26.       'openid',  
  27.       'profile',  
  28.     ],  
  29.     protectedResourceMap: [  
  30.       ['https://graph.microsoft.com/v1.0/me', ['user.read']]  
  31.     ]  
  32.   }),  
  33.   ],  
  34.   providers: [  
  35.     {  
  36.       provide: LocationStrategy,  
  37.       useClass: HashLocationStrategy  
  38.     },  
  39.     {  
  40.       provide: HTTP_INTERCEPTORS,  
  41.       useClass: MsalInterceptor,  
  42.       multi: true  
  43.     },  
  44.   MsalService,  
  45.   ApiService  
  46. ],  
  47.   bootstrap: [AppComponent]  
  48. })  
In your app-routing.module.ts file, add the following line:
  1. const routes: Routes = [  
  2.   {  
  3.     path: '',  
  4.     component: ProfileComponent,  
  5.     canActivate: [MsalGuard]  
  6.   }  
  7. ];  
  8.   
  9. @NgModule({  
  10.   imports: [RouterModule.forRoot(routes)],  
  11.   exports: [RouterModule]  
  12. })  
Create a new component called profile.
 
Create a new service in the called api.service.ts into an app/shared folder and add the following code:
  1. @Injectable({ providedIn: 'root' })  
  2. export class ApiService {  
  3.   
  4.   private baseUrl = environment.apiEndpoint;  
  5.   constructor(private http: HttpClient) { }  
  6.   
  7.   getWeathers(): Observable<IWeatherForecast[]> {  
  8.     // console.log('Token is ', localStorage.getItem('msal.idtoken'));  
  9.     const reqHeader = new HttpHeaders({  
  10.       'Content-Type''application/json',  
  11.       Authorization: 'Bearer ' + localStorage.getItem('msal.idtoken')  
  12.     });  
  13.     return this.http.get<IWeatherForecast[]>(this.baseUrl + 'home', { headers: reqHeader }).pipe(  
  14.       retry(1),  
  15.       catchError(this.errorHandl)  
  16.     );  
  17.   }  
  18.   // Error handling  
  19.   errorHandl(error) {  
  20.     let errorMessage = '';  
  21.     if (error.error instanceof ErrorEvent) {  
  22.       errorMessage = error.error.message;  
  23.     } else {  
  24.       errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;  
  25.     }  
  26.     return throwError(errorMessage);  
  27.   }  
  28. }  
In your newly created component, please add the following lines of code: 
  1. export class ProfileComponent implements OnInit {  
  2.   
  3.   name: string;  
  4.   username: string;  
  5.   
  6.   public weatherData: IWeatherForecast[] = [];  
  7.   
  8.   constructor(private msalService: MsalService, private apiService: ApiService) { }  
  9.   
  10.   ngOnInit(): void {  
  11.     const account = this.msalService.getAccount();  
  12.     this.name = account.name;  
  13.     this.username = account.userName;  
  14.   
  15.     this.getWeatherinformation();  
  16.   }  
  17.   
  18.   getWeatherinformation() {  
  19.     this.apiService.getWeathers().subscribe(res => {  
  20.       // console.log('data: ', res);  
  21.       this.weatherData = res as IWeatherForecast[];  
  22.     });  
  23.   }  
  24.   
  25.   
  26.   logout() {  
  27.     localStorage.clear();  
  28.     this.msalService.logout();  
  29.   }  
  30. }  
In your profile.component.html, please add the following code:
  1. Name: {{name}}<br/>  
  2. Username: {{username}}  
  3. <br/>  
  4.   
  5. <h3>Data From Web API</h3>  
  6. <ul>  
  7.   <li *ngFor="let element of weatherData" [type]="element">  
  8.     {{element.date}}, {{element.summary}}, {{element.temperatureC}}, {{element.temperatureF}}  
  9.   </li>  
  10. </ul>  
  11. <button type='button' name='logOut' id='logout' (click)="logout()">Log Out</button>  
  • The client application is ready.
  • Create a Web API project:

    • After creating your API project, please add the following package:
      1. Microsoft.AspNetCore.Authentication.JwtBearer  
      2.   
      3. Microsoft.AspNetCore.Cors  
    • Add the following code into the Startup.cs file:
      1. public void ConfigureServices(IServiceCollection services)  
      2.         {  
      3.             services.AddControllers();  
      4.   
      5.             // Add Cors  
      6.             services.AddCors(o => o.AddPolicy("default", builder =>  
      7.             {  
      8.                 builder.AllowAnyOrigin()  
      9.                     .AllowAnyMethod()  
      10.                     .AllowAnyHeader();  
      11.             }));  
      12.   
      13.             services.AddAuthentication(o =>  
      14.             {  
      15.                 o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;  
      16.                 o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;  
      17.                 o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;  
      18.             }).AddJwtBearer(opt =>  
      19.             {  
      20.                 opt.IncludeErrorDetails = true;  
      21.                 opt.Authority = "https://login.microsoftonline.com/c1ec3067-d41e-4053-b90c-d7619dae7650/v2.0";  
      22.                 opt.Audience = "b9535469-bbe7-4a66-8823-4fef098be78e";  
      23.             });  
      24.         }  
      25.   
      26.         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.  
      27.         public void Configure(IApplicationBuilder app, IWebHostEnvironment env)  
      28.         {  
      29.             if (env.IsDevelopment()) app.UseDeveloperExceptionPage();  
      30.             // Enable Cors  
      31.             app.UseCors("default");  
      32.             app.UseRouting();  
      33.   
      34.             app.UseAuthentication();  
      35.             app.UseAuthorization();  
      36.   
      37.             app.UseEndpoints(endpoints => { endpoints.MapControllers(); });  
      38.         }  
    • Add a Controller and add the following code into that controller:
      1. using System;  
      2. using System.Collections.Generic;  
      3. using System.Linq;  
      4. using Microsoft.AspNetCore.Authentication.JwtBearer;  
      5. using Microsoft.AspNetCore.Authorization;  
      6. using Microsoft.AspNetCore.Mvc;  
      7. using Microsoft.Extensions.Logging;  
      8.   
      9. namespace azure_ad_webapi.Controllers  
      10. {  
      11.     [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]  
      12.     [Route("api/home")]  
      13.     [Consumes("application/json")]  
      14.     [Produces("application/json")]  
      15.     [ApiController]  
      16.     public class HomeController : ControllerBase  
      17.     {  
      18.         private static readonly string[] Summaries =  
      19.         {  
      20.             "Freezing""Bracing""Chilly""Cool""Mild""Warm""Balmy""Hot""Sweltering""Scorching"  
      21.         };  
      22.   
      23.         // private readonly ILogger<HomeController> _logger;  
      24.   
      25.         public HomeController()  
      26.         {  
      27.             //_logger = logger;  
      28.         }  
      29.   
      30.         [HttpGet]  
      31.         public IEnumerable<WeatherForecast> Get()  
      32.         {  
      33.             var rng = new Random();  
      34.             return Enumerable.Range(1, 5).Select(index => new WeatherForecast  
      35.                 {  
      36.                     Date = DateTime.Now.AddDays(index),  
      37.                     TemperatureC = rng.Next(-20, 55),  
      38.                     Summary = Summaries[rng.Next(Summaries.Length)]  
      39.                 })  
      40.                 .ToArray();  
      41.         }  
      42.     }  
      43. }  
All code is hosted in GitHub. You can check it for a better understanding. 


Similar Articles