{"id":9205,"date":"2017-04-26T18:49:00","date_gmt":"2017-04-26T18:49:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/premier_developer\/?p=9205"},"modified":"2019-03-05T15:04:24","modified_gmt":"2019-03-05T22:04:24","slug":"using-adal-with-angular2","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/premier-developer\/using-adal-with-angular2\/","title":{"rendered":"Using ADAL with Angular2"},"content":{"rendered":"<p>In this post,\u00a0 Senior Application Development Manager, <a href=\"https:\/\/www.linkedin.com\/in\/vsaroopchand\/\">Vishal Saroopchand<\/a>, walks us through an example of ADAL with Angular2.<\/p>\n<hr \/>\n<p>The primary goal of this post is to give a high level walkthrough on how to use ADAL (<a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/active-directory\/develop\/active-directory-authentication-libraries\">Azure AD Authentication Library<\/a>) with Angular2. ADAL ships with support for Angular1; however, there are no clear guidance for Angular2 at the time of this post. We will focus on the core ADAL.js library without any other dependencies.<\/p>\n<h2><b>Initializing our sample project<\/b><\/h2>\n<p>We will take a simple bare-bone Angular2 starter as our starting point. To get started clone the angular2-seed starter project from <a href=\"https:\/\/github.com\/angular\/angular2-seed\">https:\/\/github.com\/angular\/angular2-seed<\/a><\/p>\n<p>Next, we want to add <b>ADAL.js<\/b>, ADAL Type Definitions and <b>expose-loader<\/b> using NPM<\/p>\n<blockquote>\n<pre class=\"lang:default decode:true\">npm install adal-angular --save\r\n\r\nnpm install expose-loader --save\r\n\r\nnpm install @types\/adal --save-dev<\/pre>\n<\/blockquote>\n<h2><b>Register your application with your Azure Active Directory<\/b><\/h2>\n<p>Use the following instructions to create a registration for your sample web app.<\/p>\n<p><a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/active-directory\/active-directory-app-registration\">https:\/\/docs.microsoft.com\/en-us\/azure\/active-directory\/active-directory-app-registration<\/a><\/p>\n<p>Now that we have all the prerequisites, let&#8217;s get started with the Angular2 artifacts.<\/p>\n<h2><b>The ADAL Helper Services<\/b><\/h2>\n<p>Let&#8217;s start by adding a sub folder &#8220;services&#8221; for all our core services for authentication.<\/p>\n<p>First, we will need to provide configuration information about our AAD application. Add a file <b>config.service.ts<\/b> with the following<\/p>\n<pre class=\"lang:default decode:true \">import { Injectable } from '@angular\/core';\r\n\r\n@Injectable()\r\n\r\nexport class ConfigService {\r\n\r\nconstructor() {\r\n\r\n\u00a0\u00a0\u00a0 }\r\n\r\npublic get getAdalConfig(): any {\r\n\r\nreturn {\r\n\r\ntenant: 'ENTER YOUR TENANT ID',\r\n\r\nclientId: 'ENTER YOUR CLIENT ID',\r\n\r\nredirectUri: window.location.origin + '\/',\r\n\r\npostLogoutRedirectUri: window.location.origin + '\/'\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 };\r\n\r\n\u00a0\u00a0\u00a0 }\r\n\r\n}<\/pre>\n<p>The important settings are <b>tenant<\/b> and <b>clientId<\/b> from your Azure Active Directory application registration.<\/p>\n<p>Next, we need to create a wrapper over ADAL.js and the <b>ApplicationContext<\/b> object. Add a new file <b>adal.service.ts<\/b> with the following<\/p>\n<pre class=\"lang:default decode:true \">import { ConfigService } from '.\/config.service';\r\n\r\nimport { Injectable } from '@angular\/core';\r\n\r\nimport 'expose-loader?AuthenticationContext!..\/..\/..\/node_modules\/adal-angular\/lib\/adal.js';\r\n\r\nlet createAuthContextFn: adal.AuthenticationContextStatic = AuthenticationContext;\r\n\r\n@Injectable()\r\n\r\nexport class AdalService {\r\n\r\nprivate context: adal.AuthenticationContext;\r\n\r\nconstructor(private configService: ConfigService) {\r\n\r\nthis.context = new createAuthContextFn(configService.getAdalConfig);\r\n\r\n\u00a0\u00a0\u00a0 }\r\n\r\nlogin() {\r\n\r\nthis.context.login();\r\n\r\n\u00a0\u00a0\u00a0 }\r\n\r\nlogout() {\r\n\r\nthis.context.logOut();\r\n\r\n\u00a0\u00a0\u00a0 }\r\n\r\nhandleCallback() {\r\n\r\nthis.context.handleWindowCallback();\r\n\r\n\u00a0\u00a0\u00a0 }\r\n\r\npublic get userInfo() {\r\n\r\nreturn this.context.getCachedUser();\r\n\r\n\u00a0\u00a0\u00a0 }\r\n\r\npublic get accessToken() {\r\n\r\nreturn this.context.getCachedToken(this.configService.getAdalConfig.clientId);\r\n\r\n\u00a0\u00a0\u00a0 }\r\n\r\npublic get isAuthenticated() {\r\n\r\nreturn this.userInfo &amp;&amp; this.accessToken;\r\n\r\n\u00a0\u00a0\u00a0 }\r\n\r\n}<\/pre>\n<p>Regarding this line of code:<\/p>\n<pre class=\"lang:default decode:true\">import 'expose-loader?AuthenticationContext!..\/..\/..\/node_modules\/adal-angular\/lib\/adal.js';<\/pre>\n<p>Here we use Express Loader to inject Adal.js in the global object. We do this because ADAL does not play nicely with CommonJS pattern. For more information on Express Loader, see <a href=\"https:\/\/github.com\/webpack-contrib\/expose-loader\">https:\/\/github.com\/webpack-contrib\/expose-loader<\/a><\/p>\n<p>Next, we will add a <b>CanActivate<\/b> guard to check if <b>AuthenticationContext.UserInfo<\/b> is set before loading feature modules. We will use this guard to ensure authenticated users can view our secure assets.<\/p>\n<pre class=\"lang:default decode:true\">import { Observable } from 'rxjs\/Observable';\r\n\r\nimport { Injectable } from '@angular\/core';\r\n\r\nimport { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, NavigationExtras } from '@angular\/router';\r\n\r\nimport { AdalService } from '.\/..\/services\/adal.service';\r\n\r\n@Injectable()\r\n\r\nexport class AuthenticationGuard implements CanActivate {\r\n\r\nconstructor(private router: Router, private adalService: AdalService) {\r\n\r\n\u00a0\u00a0\u00a0 }\r\n\r\ncanActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {\r\n\r\nlet navigationExtras: NavigationExtras = {\r\n\r\nqueryParams: { 'redirectUrl': route.url }\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 };\r\n\r\nif (!this.adalService.userInfo) {\r\n\r\nthis.router.navigate(['login'], navigationExtras);\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\r\nreturn true;\r\n\r\n\u00a0\u00a0\u00a0 }\r\n\r\n}<\/pre>\n<h3><b>Handling the OAuth handshake<\/b><\/h3>\n<p>Our code is partially completed. If we were to call login method on AdalService it will throw an exception as follow:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/31\/2019\/04\/clip_image00271.jpg\"><img decoding=\"async\" style=\"padding-top: 0px; padding-left: 0px; padding-right: 0px; border-width: 0px;\" title=\"clip_image002[7]\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/31\/2019\/04\/clip_image0027_thumb.jpg\" alt=\"clip_image002[7]\" width=\"1028\" height=\"60\" border=\"0\" \/><\/a><\/p>\n<p>The callback from the Service Provider is using #\/id_token which Angular2 router cannot understand. To address this, we will add a callback route to digest the <b>JWT Token<\/b> then redirect to our destination page.<\/p>\n<p>Let&#8217;s start by adding another folder <b>login-callback<\/b> with the following components<\/p>\n<h3>A Component<\/h3>\n<pre class=\"lang:default decode:true\">import { Component, OnInit } from '@angular\/core';\r\n\r\nimport { Router } from '@angular\/router';\r\n\r\nimport { AdalService } from '.\/..\/services\/adal.service';\r\n\r\n@Component({\r\n\r\ntemplate: '&lt;div&gt;Please wait...&lt;\/div&gt;'\r\n\r\n})\r\n\r\nexport class OAuthCallbackComponent implements OnInit {\r\n\r\nconstructor(private router: Router, private adalService: AdalService) {\r\n\r\n\u00a0\u00a0\u00a0 }\r\n\r\nngOnInit() {\r\n\r\nif (!this.adalService.userInfo) {\r\n\r\nthis.router.navigate(['login']);\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } else {\r\n\r\nthis.router.navigate(['home']);\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\r\n\u00a0\u00a0\u00a0 }\r\n\r\n}<\/pre>\n<h3>A Guard<\/h3>\n<pre class=\"lang:default decode:true\">import { Injectable } from '@angular\/core';\r\n\r\nimport { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular\/router';\r\n\r\nimport { AdalService } from '.\/..\/services\/adal.service';\r\n\r\n@Injectable()\r\n\r\nexport class OAuthCallbackHandler implements CanActivate {\r\n\r\nconstructor(private router: Router, private adalService: AdalService) {\r\n\r\n\u00a0\u00a0\u00a0 }\r\n\r\ncanActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {\r\n\r\nthis.adalService.handleCallback();\r\n\r\nif (this.adalService.userInfo) {\r\n\r\nvar returnUrl = route.queryParams['returnUrl'];\r\n\r\nif (!returnUrl) {\r\n\r\nthis.router.navigate(['home']);\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } else {\r\n\r\nthis.router.navigate([returnUrl], { queryParams: route.queryParams });\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\r\nelse {\r\n\r\nthis.router.navigate(['login']);\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\r\nreturn false;\r\n\r\n\u00a0\u00a0\u00a0 }\r\n\r\n}<\/pre>\n<h3>A Module<\/h3>\n<pre class=\"lang:default decode:true\">import { NgModule } from '@angular\/core';\r\n\r\nimport { OAuthCallbackComponent } from '.\/oauth-callback.component';\r\n\r\nimport { OAuthCallbackHandler } from '.\/oauth-callback.guard';\r\n\r\n@NgModule({\r\n\r\nimports: [],\r\n\r\ndeclarations: [ OAuthCallbackComponent],\r\n\r\nproviders: [OAuthCallbackHandler]\r\n\r\n})\r\n\r\nexport class OAuthHandshakeModule { }<\/pre>\n<p>Next, we will register the route for &#8220;id_token&#8221; to be handled by <b>OAuthCallbackComponent<\/b> and <b>OAuthCallbackGuard<\/b>. Go to <b>app.routes.ts<\/b> and add the following Route<\/p>\n<pre class=\"lang:default decode:true\">{ path: 'id_token', component: OAuthCallbackComponent, canActivate: [OAuthCallbackHandler] },<\/pre>\n<p>Also, make login our default route<\/p>\n<pre class=\"lang:default decode:true \">{ path: '', redirectTo: 'login', pathMatch: 'full' },<\/pre>\n<p>We can also guard additional routes by registering the <b>AuthenticationGuard<\/b> on existing routes<\/p>\n<pre class=\"lang:default decode:true \">{ path: 'home', component: HomeComponent, canActivate: [AuthenticationGuard] },<\/pre>\n<p>Finally, let\u2019s update HomeComponent&#8217;s constructor to log the <b>UserProfile<\/b> and <b>JWT Token<\/b> as a test<\/p>\n<pre class=\"lang:default decode:true \">constructor(private adalService: AdalService){\r\n\r\nconsole.log('User info from JWT');\r\n\r\nconsole.log(this.adalService.userInfo);\r\n\r\nconsole.log('JWT Token');\r\n\r\nconsole.log(this.adalService.accessToken);\r\n\r\n\u00a0 }<\/pre>\n<p>There are some additional pieces in place but the steps above are the important bits. You can find the complete working example here: <a href=\"https:\/\/github.com\/vsaroopchand\/angular2-seed\">https:\/\/github.com\/vsaroopchand\/angular2-seed<\/a><\/p>\n<h2><b>The end result<\/b><\/h2>\n<p>Trigger login in your application by invoking login on AdalService. Here we use a button to trigger the call.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/31\/2019\/04\/clip_image00451.jpg\"><img decoding=\"async\" style=\"padding-top: 0px; padding-left: 0px; padding-right: 0px; border-width: 0px;\" title=\"clip_image004[5]\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/31\/2019\/04\/clip_image0045_thumb.jpg\" alt=\"clip_image004[5]\" width=\"644\" height=\"283\" border=\"0\" \/><\/a><\/p>\n<p>This will redirect to <a href=\"https:\/\/login.microsoftonline.com\">https:\/\/login.microsoftonline.com<\/a> for authentication using OAuth Client Flow<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/31\/2019\/04\/clip_image00651.jpg\"><img decoding=\"async\" style=\"padding-top: 0px; padding-left: 0px; padding-right: 0px; border-width: 0px;\" title=\"clip_image006[5]\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/31\/2019\/04\/clip_image0065_thumb.jpg\" alt=\"clip_image006[5]\" width=\"613\" height=\"484\" border=\"0\" \/><\/a><\/p>\n<p>After successfully login, you will redirect back to the application which will handle the JWT token<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-35795\" src=\"http:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/ang1.jpg\" alt=\"\" width=\"1028\" height=\"294\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/ang1.jpg 1028w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/ang1-300x86.jpg 300w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/ang1-768x220.jpg 768w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/ang1-1024x293.jpg 1024w\" sizes=\"(max-width: 1028px) 100vw, 1028px\" \/><\/p>\n<p>From here, you can use the <b>JWT Token<\/b> to query <b>Azure Graph<\/b> or setting it as <b>Bearer<\/b> token for delegation to your own backend services.<\/p>\n<hr align=\"center\" size=\"3\" width=\"100%\" \/>\n<p><a href=\"https:\/\/blogs.msdn.com\/b\/premier_developer\/archive\/2014\/09\/15\/welcome.aspx\"><strong>Premier Support for Developers<\/strong><\/a> provides strategic technology guidance, critical support coverage, and a range of essential services to help teams optimize development lifecycles and improve software quality.\u00a0 Contact your Application Development Manager (ADM) or <a href=\"https:\/\/blogs.msdn.microsoft.com\/premier_developer\/contact-us\/\"><b>email us<\/b><\/a> to learn more about what we can do for you.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this post,\u00a0 Senior Application Development Manager, Vishal Saroopchand, walks us through an example of ADAL with Angular2. The primary goal of this post is to give a high level walkthrough on how to use ADAL (Azure AD Authentication Library) with Angular2. ADAL ships with support for Angular1; however, there are no clear guidance for [&hellip;]<\/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],"tags":[134,84,3],"class_list":["post-9205","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure","tag-active-directory","tag-adal","tag-team"],"acf":[],"blog_post_summary":"<p>In this post,\u00a0 Senior Application Development Manager, Vishal Saroopchand, walks us through an example of ADAL with Angular2. The primary goal of this post is to give a high level walkthrough on how to use ADAL (Azure AD Authentication Library) with Angular2. ADAL ships with support for Angular1; however, there are no clear guidance for [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts\/9205","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=9205"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts\/9205\/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=9205"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/categories?post=9205"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/tags?post=9205"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}