You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dlab.apache.org by an...@apache.org on 2019/10/16 10:16:59 UTC

[incubator-dlab] 03/06: [DLAB-1157]: added refresh token request on unauthorize

This is an automated email from the ASF dual-hosted git repository.

ankovalyshyn pushed a commit to branch DLAB-1157
in repository https://gitbox.apache.org/repos/asf/incubator-dlab.git

commit db02fbb61384dfe0d35586ac2e541bfb7b5e3011
Author: Andriana Kovalyshyn <An...@epam.com>
AuthorDate: Tue Oct 15 12:25:25 2019 +0300

    [DLAB-1157]: added refresh token request on unauthorize
---
 .../resources/webapp/src/app/app.routing.module.ts |  2 +-
 .../src/app/core/interceptors/error.interceptor.ts | 92 ++++++++++++++++------
 .../core/interceptors/http.token.interceptor.ts    |  9 +--
 .../services/applicationServiceFacade.service.ts   | 11 ++-
 4 files changed, 82 insertions(+), 32 deletions(-)

diff --git a/services/self-service/src/main/resources/webapp/src/app/app.routing.module.ts b/services/self-service/src/main/resources/webapp/src/app/app.routing.module.ts
index d0b33b9..0473332 100644
--- a/services/self-service/src/main/resources/webapp/src/app/app.routing.module.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/app.routing.module.ts
@@ -49,7 +49,7 @@ const routes: Routes = [{
     }, {
       path: 'resources_list',
       component: ResourcesComponent,
-      canActivate: [CheckParamsGuard]
+      canActivate: [AuthorizationGuard]
     }, {
       path: 'billing_report',
       component: ReportingComponent,
diff --git a/services/self-service/src/main/resources/webapp/src/app/core/interceptors/error.interceptor.ts b/services/self-service/src/main/resources/webapp/src/app/core/interceptors/error.interceptor.ts
index d492eda..b166a96 100644
--- a/services/self-service/src/main/resources/webapp/src/app/core/interceptors/error.interceptor.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/core/interceptors/error.interceptor.ts
@@ -18,41 +18,89 @@
  */
 
 import { Injectable } from '@angular/core';
+import { BehaviorSubject } from 'rxjs';
 import {
-    HttpInterceptor,
-    HttpRequest,
-    HttpHandler,
-    HttpEvent
+  HttpInterceptor,
+  HttpRequest,
+  HttpHandler,
+  HttpEvent,
+  HttpErrorResponse
 } from '@angular/common/http';
 
-import { Observable, throwError, of as observableOf } from 'rxjs';
-import { map, catchError } from 'rxjs/operators';
+import { Observable } from 'rxjs';
+import { _throw } from 'rxjs/observable/throw';
+import { switchMap, filter, take, catchError } from 'rxjs/operators';
 
-import { StorageService, AppRoutingService } from '../services';
+import { StorageService, AppRoutingService, ApplicationSecurityService } from '../services';
 import { HTTP_STATUS_CODES } from '../util';
 
 @Injectable() export class ErrorInterceptor implements HttpInterceptor {
+  private isRefreshing = false;
+  private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);
+
   constructor(
     private jwtService: StorageService,
-    private routingService: AppRoutingService
-  ) {}
+    private routingService: AppRoutingService,
+    private auth: ApplicationSecurityService
+  ) { }
 
   intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
-    return next.handle(request).pipe(
-      catchError(error => {
-        let url = error.url;
+    return next.handle(request).pipe(catchError(error => {
 
-        if (url.indexOf('?') > -1) {
-          url = url.substr(0, url.indexOf('?'));
+      if (error instanceof HttpErrorResponse) {
+        switch ((<HttpErrorResponse>error).status) {
+          case HTTP_STATUS_CODES.UNAUTHORIZED:
+            console.log('401');
+            return this.handleUnauthorized(request, next);
+          case HTTP_STATUS_CODES.BAD_REQUEST:
+            console.log('400');
+            return this.handleBadRequest(request, next);
+          default:
+            return _throw(error);
         }
+      } else {
+        return _throw(error);
+      }
+    }));
+  }
 
-        if ((error.status === HTTP_STATUS_CODES.UNAUTHORIZED) && !url.endsWith('login')) {
-          this.jwtService.destroyToken();
-          this.routingService.redirectToLoginPage();
-          return observableOf(error);
-        } else {
-          return throwError(error);
-        }
-      }));
+  private addToken(request: HttpRequest<any>, token: string) {
+    return request.clone({ setHeaders: { 'Authorization': `Bearer ${token}` } });
+  }
+
+  private handleUnauthorized(request: HttpRequest<any>, next: HttpHandler) {
+    if (!this.isRefreshing) {
+      this.isRefreshing = true;
+      this.refreshTokenSubject.next(null);
+
+      return this.auth.refreshToken().pipe(
+        switchMap((token: any) => {
+          this.isRefreshing = false;
+          this.refreshTokenSubject.next(this.addToken(request, token.access_token));
+          return next.handle(request);
+        }));
+
+    } else {
+      return this.refreshTokenSubject.pipe(
+        filter(token => {
+          debugger;
+          return token != null
+        }),
+        take(1),
+        switchMap(jwt => {
+          return next.handle(this.addToken(request, jwt));
+        }));
     }
+  }
+
+  private handleBadRequest(request: HttpRequest<any>, next: HttpHandler) {
+    return this.auth.logout().pipe(
+      switchMap((response: any) => {
+        const redirect_parameter = response.headers.get('Location');
+        redirect_parameter ? this.routingService.redirectToUrl(redirect_parameter) : this.routingService.redirectToLoginPage();
+        debugger;
+        return next.handle(request);
+      })
+    );
+  }
 }
diff --git a/services/self-service/src/main/resources/webapp/src/app/core/interceptors/http.token.interceptor.ts b/services/self-service/src/main/resources/webapp/src/app/core/interceptors/http.token.interceptor.ts
index ad33ef2..ce476b4 100644
--- a/services/self-service/src/main/resources/webapp/src/app/core/interceptors/http.token.interceptor.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/core/interceptors/http.token.interceptor.ts
@@ -19,17 +19,12 @@
 
 import { Injectable } from '@angular/core';
 import { StorageService } from '../services/storage.service';
-import {
-    HttpInterceptor,
-    HttpRequest,
-    HttpHandler,
-    HttpEvent
-} from '@angular/common/http';
+import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
 
 import { Observable } from 'rxjs';
 
 @Injectable() export class HttpTokenInterceptor implements HttpInterceptor {
-  constructor(private jwtService: StorageService) {}
+  constructor(private jwtService: StorageService) { }
 
   intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
     const token = this.jwtService.getToken();
diff --git a/services/self-service/src/main/resources/webapp/src/app/core/services/applicationServiceFacade.service.ts b/services/self-service/src/main/resources/webapp/src/app/core/services/applicationServiceFacade.service.ts
index 52bfb54..67c7010 100644
--- a/services/self-service/src/main/resources/webapp/src/app/core/services/applicationServiceFacade.service.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/core/services/applicationServiceFacade.service.ts
@@ -35,6 +35,7 @@ export class ApplicationServiceFacade {
   private static readonly LOGIN = 'login';
   private static readonly LOGOUT = 'logout';
   private static readonly AUTHORIZE = 'authorize';
+  private static readonly REFRESH_TOKEN = 'refresh_token';
   private static readonly OAUTH = 'oauth';
   private static readonly ACCESS_KEY = 'access_key';
   private static readonly ACTIVE_LIST = 'active_list';
@@ -75,7 +76,7 @@ export class ApplicationServiceFacade {
   private static readonly PROJECT = 'project';
   private static readonly USER_PROJECT = 'project/me';
   private static readonly ENDPOINT = 'endpoint';
-  private accessTokenKey: string = 'access_token';
+
   private requestRegistry: Dictionary<string>;
 
   constructor(private http: HttpClient) {
@@ -107,6 +108,12 @@ export class ApplicationServiceFacade {
       });
   }
 
+  public buildRefreshToken(param: any): Observable<any> {
+    return this.buildRequest(HTTPMethod.POST,
+      this.requestRegistry.Item(ApplicationServiceFacade.REFRESH_TOKEN) + param,
+      null);
+  }
+
   public buildLocationCheck(): Observable<any> {
     return this.buildRequest(HTTPMethod.GET,
       this.requestRegistry.Item(ApplicationServiceFacade.OAUTH),
@@ -588,6 +595,7 @@ export class ApplicationServiceFacade {
     this.requestRegistry.Add(ApplicationServiceFacade.LOGIN, '/api/user/login');
     this.requestRegistry.Add(ApplicationServiceFacade.LOGOUT, '/api/oauth/logout');
     this.requestRegistry.Add(ApplicationServiceFacade.AUTHORIZE, '/api/oauth/authorize');
+    this.requestRegistry.Add(ApplicationServiceFacade.REFRESH_TOKEN, '/api/oauth/refresh');
     this.requestRegistry.Add(ApplicationServiceFacade.ACTIVE_LIST, '/api/environment/user');
     this.requestRegistry.Add(ApplicationServiceFacade.FULL_ACTIVE_LIST, '/api/environment/all');
     this.requestRegistry.Add(ApplicationServiceFacade.ENV, '/api/environment');
@@ -626,7 +634,6 @@ export class ApplicationServiceFacade {
 
     // Environment Health Status
     this.requestRegistry.Add(ApplicationServiceFacade.ENVIRONMENT_HEALTH_STATUS, '/api/infrastructure/status');
-    this.requestRegistry.Add(ApplicationServiceFacade.ENVIRONMENT_HEALTH_STATUS, '/api/infrastructure/status');
     this.requestRegistry.Add(ApplicationServiceFacade.META_DATA, '/api/infrastructure/meta');
     this.requestRegistry.Add(ApplicationServiceFacade.EDGE_NODE_START, '/api/infrastructure/edge/start');
     this.requestRegistry.Add(ApplicationServiceFacade.EDGE_NODE_STOP, '/api/infrastructure/edge/stop');


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@dlab.apache.org
For additional commands, e-mail: commits-help@dlab.apache.org