{"id":1384,"date":"2022-08-20T18:57:10","date_gmt":"2022-08-20T16:57:10","guid":{"rendered":"https:\/\/nguenkam.com\/blog\/?p=1384"},"modified":"2022-08-20T18:57:40","modified_gmt":"2022-08-20T16:57:40","slug":"handling-authentication-in-angular","status":"publish","type":"post","link":"https:\/\/nguenkam.com\/blog\/index.php\/2022\/08\/20\/handling-authentication-in-angular\/","title":{"rendered":"Handling Authentication in Angular"},"content":{"rendered":"\n<p><\/p>\n\n\n\n<p><strong>Security<\/strong> is an important aspect of a system. Authentication\u00a0belong to one of them. <\/p>\n\n\n\n<p>Authentication can be implemented in web applications in multiple ways like session-based, cookie-based, token-based, etc. Our main focus would be looking at token-based authentication.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" src=\"https:\/\/nguenkam.com\/blog\/wp-content\/uploads\/2022\/08\/image-5.png\" alt=\"\" class=\"wp-image-2099\" width=\"471\" height=\"363\" srcset=\"https:\/\/nguenkam.com\/blog\/wp-content\/uploads\/2022\/08\/image-5.png 818w, https:\/\/nguenkam.com\/blog\/wp-content\/uploads\/2022\/08\/image-5-300x231.png 300w, https:\/\/nguenkam.com\/blog\/wp-content\/uploads\/2022\/08\/image-5-768x592.png 768w\" sizes=\"(max-width: 471px) 100vw, 471px\" \/><\/figure><\/div>\n\n\n\n<p class=\"has-text-align-left\">In token-based authentication, basically user login in into the system and server send<span class=\"has-inline-color has-vivid-cyan-blue-color\"> <em>acces_token<\/em><\/span> and<span class=\"has-inline-color has-vivid-cyan-blue-color\"> <em>refresh_token<\/em><\/span> with its  <span class=\"has-inline-color has-vivid-cyan-blue-color\"><em>expiry<\/em> <\/span>if the user is validated. <\/p>\n\n\n\n<p>This part is simple, a user enters into a web application. After a user gets logged in, each API call has to be validated to maintain the data security of an application. We have to send\u00a0<code><em><strong>access_token<\/strong><\/em><\/code>\u00a0with each request.<\/p>\n\n\n\n<p>On server-side API, it extracts\u00a0<code><em><strong>access_token<\/strong><\/em><\/code>\u00a0from the request, verifies (inside Identity Server) if it is valid or not based on its expiry. And return a data if a token is not expired, or return 401 status if\u00a0<code>access_token<\/code>\u00a0is expired.<\/p>\n\n\n\n<p>We created services dedicated to making ajax calls. <em><span class=\"has-inline-color has-luminous-vivid-orange-color\">For authorization purposes, we\u2019ve to ensure Auth Header is getting passed with each request.<\/span><\/em><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { Injectable } from '@angular\/core';\r\nimport { HttpClient, HttpHeaders } from '@angular\/common\/http';\r\nimport { map } from 'rxjs\/operators';\r\n\r\n@Injectable()\r\nexport class AppService {\r\n\r\n  constructor(private http: HttpClient) { }\r\n\r\n  getCountries() {\r\n    const headers = new HttpHeaders();\r\n    headers.append('Authorization', `Bearer ${token}`);\r\n    return this.http.get('\/api\/country', { headers });\r\n  }\r\n}<\/code><\/pre>\n\n\n\n<p>for every Service (where we need Authorization), we will have to repeat the logic : It mean , ensure that Auth Header is getting passed with each request. \u00a0<em>This would violate the DRY (Don\u2019t Repeat Yourself). We should find a better way to do this, maybe something that could help us to intercept the\u00a0<code>http<\/code>\u00a0request before\/after it makes a call to Server.<\/em><\/p>\n\n\n\n<p><\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p><code><a rel=\"noreferrer noopener\" href=\"https:\/\/angular.io\/api\/common\/http\/HttpInterceptor\" target=\"_blank\">HttpInterceptor<\/a><\/code>is useful here to solve this problem. Basically it allows us to intercept\u00a0<code>http<\/code>\u00a0request \/ response and give access to manipulate it. Hence our generic logic to add header in the request can be kept here. Basic TokenInterceptor code may look like below.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { Injectable } from '@angular\/core';\r\nimport {\r\n  HttpRequest,\r\n  HttpHandler,\r\n  HttpEvent,\r\n  HttpInterceptor\r\n} from '@angular\/common\/http';\r\nimport { AuthService } from '.\/auth\/auth.service';\r\nimport { Observable } from 'rxjs';\r\n\r\n@Injectable()\r\nexport class AppHttpInterceptor implements HttpInterceptor {\r\n  \/\/ AuthService is holding \r\n  constructor(public auth: AuthService) {}\r\n  intercept(request: HttpRequest&lt;any>, next: HttpHandler): Observable&lt;HttpEvent&lt;any>> {\r\n    const token = window.localStorage.get('token');\r\n    request = request.clone({\r\n      setHeaders: {\r\n        Authorization: `Bearer ${token}`\r\n      }\r\n    });\r\n    return next.handle(request);\r\n  }\r\n}<\/code><\/pre>\n\n\n\n<p>In the above snippet, we have implements\u00a0<code>AppHttpInterceptorService<\/code>\u00a0class from\u00a0<code>HttpInterceptor<\/code>\u00a0a method. Then implemented an\u00a0<code><em><strong>intercept<\/strong><\/em><\/code> method that provides control to modify the request\/response. Thus we have kept adding a token to header part in there.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><span class=\"has-inline-color has-luminous-vivid-orange-color\">Extending\u00a0<strong><code>HTTP_INTECEPTORS<\/code>\u00a0<\/strong>provider is needed to take\u00a0<code>AppHttpInterceptorService<\/code>\u00a0in action. This can be registered inside your\u00a0<code><strong>app.module.ts<\/strong><\/code><\/span><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { HTTP_INTERCEPTORS } from '@angular\/common\/http';\r\nimport { AppHttpInterceptor } from '.\/AppHttpInterceptor';\r\n@NgModule({\r\n  bootstrap: &#91;AppComponent],\r\n  imports: &#91;...],\r\n  providers: &#91;\r\n    {\r\n      provide: HTTP_INTERCEPTORS,\r\n      useClass: AppHttpInterceptor,\r\n      multi: true\r\n    }\r\n  ]\r\n})\r\nexport class AppModule {}<\/code><\/pre>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Ideally AppHttpInterceptor should take care of the below things : <\/p>\n\n\n\n<ol><li>Add\u00a0<code>Authorization<\/code>\u00a0the header on each request<\/li><li>Allow requests which don\u2019t require token logic at all.<\/li><li>If the token expires, then it automatically refreshes the token.<\/li><\/ol>\n\n\n\n<p>Generally\u00a0<code>access_token<\/code>\u00a0have 60 minutes expiry for security reasons. After 60 minutes token\u00a0<code>access_token<\/code>become invalid and API could return a response with 401 status. To handle this case we\u2019ve to make a new token using\u00a0<code>refresh_token<\/code>\u00a0and use that token for further API calls.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { AuthService } from '.\/auth.service';\r\n\r\nimport { Injectable } from '@angular\/core';\r\nimport {\r\n  HttpRequest, HttpHandler, HttpInterceptor, HttpSentEvent,\r\n  HttpHeaderResponse, HttpProgressEvent, HttpResponse, HttpUserEvent\r\n} from '@angular\/common\/http';\r\nimport { Observable, BehaviorSubject, throwError} from 'rxjs';\r\nimport { catchError, switchMap, finalize, filter, take, map } from 'rxjs\/operators';\r\nimport { Router } from '@angular\/router';\r\nimport { JwtHelperService } from '@auth0\/angular-jwt';\r\n\r\nconst helper = new JwtHelperService();\r\n\/\/ You can add URL which don't need AUTH header\r\nconst whiteListUrls = &#91;'login', 'refreshToken'];\r\n\r\n@Injectable()\r\nexport class CustomHttpInterceptorService implements HttpInterceptor {\r\n  constructor(\r\n    private auth: AuthService,\r\n    private router: Router) {}\r\n\r\n    \/\/ Check expiry of token, first decode token\r\n    \/\/ extract data, and verify expiry timing wrt currentTime\r\n    \/\/ should be less that currentTime\r\n    private isTokenExpired(token): boolean {\r\n      const decoded = token &amp;&amp; helper.decodeToken(token);\r\n      const date = new Date().getTime();\r\n      return decoded &amp;&amp; new Date(decoded.exp * 1000).getTime() &lt;= date;\r\n    }\r\n\r\n    intercept(request: HttpRequest&lt;any>, next: HttpHandler): Observable&lt;HttpSentEvent | HttpHeaderResponse | HttpProgressEvent |\r\n      HttpResponse&lt;any> | HttpUserEvent&lt;any> | any> {\r\n      const token = localStorage.get('access_token');\r\n      const refresh_token = localStorage.get('access_token');\r\n      const isExpired = this.isTokenExpired(token);\r\n      \/\/ Directly allowed whitelisted URL's\r\n      if (whiteListUrls.find(w => request.url.includes(w)) || !isExpired) {\r\n        return next.handle(request);\r\n      }\r\n      \/\/ If accessToken is expired\r\n      if (isExpired) {\r\n        \/\/ Retreive new refresh_token\r\n        const refreshToken = this.auth.refreshToken(refresh_token).pipe(\r\n          \/\/ Applying catchError only to refreshToken call\r\n          catchError(_ => {\r\n            \/\/ Logout if refresh call fails\r\n            return this.logout() as any;\r\n          }),\r\n          switchMap((user: any) => {\r\n            \/\/ when new user token retrieved\r\n            if (user) {\r\n              \/\/ Update token locally\r\n              this.auth.updateTokens(user);\r\n              \/\/ Make the ajax call after by passing `accessToken`\r\n              return next.handle(this.addTokenToRequest(request, user.accessToken));\r\n            }\r\n            \/\/ Log out if there is no user\r\n            return this.logout() as any;\r\n          })\r\n        );\r\n        return refreshToken as any;\r\n      } else {\r\n        \/\/ Make normal ajax call just by passing token\r\n        return next.handle(this.addTokenToRequest(request, token));\r\n      }\r\n    }\r\n\r\n    private addTokenToRequest(request: HttpRequest&lt;any>, token: string): HttpRequest&lt;any> {\r\n      \/\/ Token appended in the request header.\r\n      return request.clone({ setHeaders: { Authorization: `Bearer ${token}`}});\r\n    }\r\n\r\n    private logout() {\r\n      this.auth.logout();\r\n      this.router.navigate(&#91;'login']);\r\n    }\r\n}<\/code><\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Security is an important aspect of a system. Authentication\u00a0belong to one of them. Authentication can be implemented in web applications in multiple ways like session-based, cookie-based, token-based, etc. Our main focus would be looking at token-based authentication. In token-based authentication, basically user login in into the system and server send acces_token and refresh_token with its [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1386,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[37],"tags":[385,232,386,231],"_links":{"self":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/1384"}],"collection":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=1384"}],"version-history":[{"count":3,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/1384\/revisions"}],"predecessor-version":[{"id":2101,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/1384\/revisions\/2101"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/media\/1386"}],"wp:attachment":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=1384"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=1384"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=1384"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}