{"id":35668,"date":"2019-03-08T06:00:17","date_gmt":"2019-03-08T13:00:17","guid":{"rendered":"http:\/\/devblogs.microsoft.com\/premier-developer\/?p=35668"},"modified":"2019-03-04T14:19:12","modified_gmt":"2019-03-04T21:19:12","slug":"angular-how-to-microsoft-adal-for-angular-6-with-configurable-settings","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/premier-developer\/angular-how-to-microsoft-adal-for-angular-6-with-configurable-settings\/","title":{"rendered":"Angular How-to: Microsoft ADAL for Angular 6+ with Configurable Settings"},"content":{"rendered":"<p><strong>Laurie Atkinson, Senior Consultant,<\/strong> Use the microsoft-adal-angular6 wrapper library to authenticate with Azure Active Directory in your Angular 6+ app.<\/p>\n<p><a href=\"https:\/\/www.npmjs.com\/package\/microsoft-adal-angular6\">Active Directory Authentication Library (ADAL) for Angular 6+<\/a> is a library for integrating Azure AD into your Angular app. However, its provided instructions and example application assume a hardcoded configuration and often your implementation needs to support configurable options. This post provides the modifications necessary to remove this limitation and offer a more realistic scenario.<\/p>\n<h2>Get the library<\/h2>\n<p>npm install microsoft-adal-angular6<\/p>\n<h2>Create a configuration file<\/h2>\n<p>Refer to <a href=\"https:\/\/devblogs.microsoft.com\/premier-developer\/angular-how-to-editable-config-files\/\">this post<\/a> for how to set up an editable configuration file that can be customized for multiple environments.<\/p>\n<p>Include a node in your configuration file in the format expected by the microsoft-adal-angular6 library.<\/p>\n<p>The endpoints property will be important for the Angular http interceptor to match which API calls should include the authentication token inserted into the header.<\/p>\n<p><strong>assets\\config\\config.dev.json<\/strong><\/p>\n<pre class=\"lang:js decode:true \">{\r\n    . . .,\r\n    \"adalConfig\": {\r\n        \"clientId\": \"&lt;client-id-here&gt;\",\r\n        \"tenant\": \"&lt;tenant-guid-here&gt;\",\r\n        \"cacheLocation\": \"localStorage\",\r\n        \"endpoints\": {\r\n            \"api\": \"&lt;client-id-here&gt;\"\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h2>Reference the ADAL module in your app<\/h2>\n<p>Do <em>not<\/em> call forRoot() on the MsAdalAngular6Module as shown in the library\u2019s documentation, because this forces you to provide the adalConfig object too soon in the bootstrapping process. The initialization of the modules listed in the imports section of the module declaration does not wait for the APP_INITIALIZER to complete. Instead declare it this way:<\/p>\n<p><strong>app.module.ts<\/strong><\/p>\n<pre class=\"lang:js decode:true \">@NgModule({\r\n   imports: [ MsAdalAngular6Module ],\r\n   declarations: [ . . . ],\r\n   providers: [ . . . ],\r\n   bootstrap: [ AppComponent ]\r\n})\r\nexport class AppModule { }\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h2>Initialize the ADAL configuration<\/h2>\n<p><a id=\"post-35668-_Hlk513023212\"><\/a> Instead of providing a hardcoded configuration object, retrieve the configuration settings from the JSON file illustrated above using Angular\u2019s APP_INITIALIZER feature. Then specify an alternate provider for the adalConfig parameter to the MsAdalAngular6Service constructor, which returns the retrieved config data instead of a hardcoded parameter.<\/p>\n<p>In addition, add the AuthenticationGuard service which is part of the microsoft-adal-angular6 library.<\/p>\n<p>With these changes, the AppModule should now look as follows:<\/p>\n<p><strong>app.module.ts<\/strong><\/p>\n<pre class=\"lang:js decode:true \">import { MsAdalAngular6Module, MsAdalAngular6Service, AuthenticationGuard\r\n  } from 'microsoft-adal-angular6';\r\n\r\nlet adalConfig: any; \/\/ will be initialized by APP_INITIALIZER\r\nexport function msAdalAngular6ConfigFactory() {\r\n  return adalConfig; \/\/ will be invoked later when creating MsAdalAngular6Service\r\n}\r\n\r\n\/\/ refer to:\r\n\/\/ https:\/\/devblogs.microsoft.com\/premier-developer\/angular-how-to-editable-config-files\/\r\n\/\/ for a description of the AppConfig service\r\nexport function initializeApp(appConfig: AppConfig) {\r\n  const promise = appConfig.load().then(() =&gt; {\r\n    adalConfig = {\r\n      tenant: AppConfig.settings.adalConfig.tenant,\r\n      clientId: AppConfig.settings.adalConfig.clientId,\r\n      redirectUri: window.location.origin,\r\n      endpoints: AppConfig.settings.adalConfig.endpoints,\r\n      navigateToLoginRequestUrl: false,\r\n      cacheLocation: AppConfig.settings.adalConfig.cacheLocation\r\n    };\r\n  });\r\n  return () =&gt; promise;\r\n}\r\n\r\n@NgModule({\r\n   imports: [ MsAdalAngular6Module ],\r\n   declarations: [ . . . ],\r\n   providers: [\r\n    {\r\n      provide: APP_INITIALIZER,\r\n      useFactory: initializeApp,\r\n      deps: [AppConfig],\r\n      multi: true\r\n    },\r\n    MsAdalAngular6Service,\r\n    {\r\n      provide: 'adalConfig',\r\n      useFactory: msAdalAngular6ConfigFactory,\r\n      deps: []\r\n    },\r\n    AuthenticationGuard\r\n   ],\r\n   bootstrap: [ AppComponent ]\r\n})\r\nexport class AppModule { }\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h2>Create an HttpInterceptor to insert the bearer token into API requests<\/h2>\n<p>The purpose of the endpoints property on the adalConfig object is to automatically populate the requests matching those endpoints with the token obtained by AAD. My experience is that this insertion does not occur automatically and instead requires a custom interceptor be provided.<\/p>\n<p><strong>insert-auth-token-interceptor.ts<\/strong><\/p>\n<pre class=\"lang:js decode:true \">import { Injectable } from '@angular\/core';\r\nimport { HttpInterceptor, HttpHandler, HttpRequest } from '@angular\/common\/http';\r\nimport { mergeMap } from 'rxjs\/operators';\r\nimport { MsAdalAngular6Service } from 'microsoft-adal-angular6';\r\n\r\n@Injectable()\r\nexport class InsertAuthTokenInterceptor implements HttpInterceptor {\r\n\r\n    constructor(private adal: MsAdalAngular6Service) { }\r\n\r\n    intercept(req: HttpRequest&lt;any&gt;, next: HttpHandler) {\r\n        \/\/ get api url from adal config\r\n        const resource = this.adal.GetResourceForEndpoint(req.url);\r\n        if (!resource || !this.adal.isAuthenticated) {\r\n            return next.handle(req);\r\n        }\r\n\r\n        \/\/ merge the bearer token into the existing headers\r\n        return this.adal.acquireToken(resource).pipe(\r\n            mergeMap((token: string) =&gt; {\r\n                const authorizedRequest = req.clone({\r\n                    headers: req.headers.set('Authorization', `Bearer ${token}`),\r\n                });\r\n                return next.handle(authorizedRequest);\r\n        }));\r\n    }\r\n}\r\n<\/pre>\n<p><strong>app.module.ts<\/strong><\/p>\n<pre class=\"lang:js decode:true \">@NgModule({\r\n   . . .\r\n   providers: [\r\n    {\r\n      provide: HTTP_INTERCEPTORS,\r\n      useClass: InsertAuthTokenInterceptor\r\n    },\r\n   . . .\r\n})\r\nexport class AppModule { }\r\n<\/pre>\n<p>With these modifications, your Angular app should be ready to start using Azure AD and the ADAL library for authentication. For more details on library usage, refer to the documentation here: <a href=\"https:\/\/www.npmjs.com\/package\/microsoft-adal-angular6\">https:\/\/www.npmjs.com\/package\/microsoft-adal-angular6<\/a>.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Laurie Atkinson, Senior Consultant explains how to use the microsoft-adal-angular6 wrapper library to authenticate with Azure Active Directory in your Angular 6+ apps.<\/p>\n","protected":false},"author":582,"featured_media":37840,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[25,129,1],"tags":[84,51],"class_list":["post-35668","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure","category-premier","category-permierdev","tag-adal","tag-angular"],"acf":[],"blog_post_summary":"<p>Laurie Atkinson, Senior Consultant explains how to use the microsoft-adal-angular6 wrapper library to authenticate with Azure Active Directory in your Angular 6+ apps.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts\/35668","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/users\/582"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/comments?post=35668"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts\/35668\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/media\/37840"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/media?parent=35668"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/categories?post=35668"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/tags?post=35668"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}