Kaynağa Gözat

feat(admin-ui): Support bearer token auth method

Relates to #138
Michael Bromley 6 yıl önce
ebeveyn
işleme
c31a383952

+ 1 - 1
admin-ui/src/app/core/providers/local-storage/local-storage.service.ts

@@ -1,7 +1,7 @@
 import { Location } from '@angular/common';
 import { Injectable } from '@angular/core';
 
-export type LocalStorageKey = 'activeChannelToken';
+export type LocalStorageKey = 'activeChannelToken' | 'authToken';
 export type LocalStorageLocationBasedKey = 'shippingTestOrder' | 'shippingTestAddress';
 const PREFIX = 'vnd_';
 

+ 13 - 1
admin-ui/src/app/data/data.module.ts

@@ -25,7 +25,7 @@ export function createApollo(
     localStorageService: LocalStorageService,
     fetchAdapter: FetchAdapter,
 ): ApolloClientOptions<any> {
-    const { apiHost, apiPort, adminApiPath } = getAppConfig();
+    const { apiHost, apiPort, adminApiPath, tokenMethod } = getAppConfig();
     const host = apiHost === 'auto' ? `${location.protocol}//${location.hostname}` : apiHost;
     const port = apiPort === 'auto' ? (location.port === '' ? '' : `:${location.port}`) : `:${apiPort}`;
     const apolloCache = new InMemoryCache({
@@ -54,6 +54,18 @@ export function createApollo(
                     };
                 }
             }),
+            setContext(() => {
+                if (tokenMethod === 'bearer') {
+                    const authToken = localStorageService.get('authToken');
+                    if (authToken) {
+                        return {
+                            headers: {
+                                authorization: `Bearer ${authToken}`,
+                            },
+                        };
+                    }
+                }
+            }),
             createUploadLink({
                 uri: `${host}${port}/${adminApiPath}`,
                 fetch: fetchAdapter.fetch,

+ 23 - 1
admin-ui/src/app/data/providers/interceptor.ts

@@ -10,6 +10,8 @@ import { Injectable, Injector } from '@angular/core';
 import { Router } from '@angular/router';
 import { Observable } from 'rxjs';
 import { tap } from 'rxjs/operators';
+import { DEFAULT_AUTH_TOKEN_HEADER_KEY } from 'shared/shared-constants';
+import { AdminUiConfig } from 'shared/shared-types';
 
 import { getAppConfig } from '../../app.config';
 import { AuthService } from '../../core/providers/auth/auth.service';
@@ -27,13 +29,19 @@ export const AUTH_REDIRECT_PARAM = 'redirectTo';
  */
 @Injectable()
 export class DefaultInterceptor implements HttpInterceptor {
+    private readonly tokenMethod: AdminUiConfig['tokenMethod'] = 'cookie';
+    private readonly authTokenHeaderKey: string;
+
     constructor(
         private dataService: DataService,
         private injector: Injector,
         private authService: AuthService,
         private router: Router,
         private localStorageService: LocalStorageService,
-    ) {}
+    ) {
+        this.tokenMethod = getAppConfig().tokenMethod;
+        this.authTokenHeaderKey = getAppConfig().authTokenHeaderKey || DEFAULT_AUTH_TOKEN_HEADER_KEY;
+    }
 
     intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
         this.dataService.client.startRequest().subscribe();
@@ -41,6 +49,7 @@ export class DefaultInterceptor implements HttpInterceptor {
             tap(
                 event => {
                     if (event instanceof HttpResponse) {
+                        this.checkForAuthToken(event);
                         this.notifyOnError(event);
                         this.dataService.client.completeRequest().subscribe();
                     }
@@ -105,4 +114,17 @@ export class DefaultInterceptor implements HttpInterceptor {
         const notificationService = this.injector.get<NotificationService>(NotificationService);
         notificationService.error(message, vars);
     }
+
+    /**
+     * If the server is configured to use the "bearer" tokenMethod, each response should be checked
+     * for the existence of an auth token.
+     */
+    private checkForAuthToken(response: HttpResponse<any>) {
+        if (this.tokenMethod === 'bearer') {
+            const authToken = response.headers.get(this.authTokenHeaderKey);
+            if (authToken) {
+                this.localStorageService.set('authToken', authToken);
+            }
+        }
+    }
 }

+ 2 - 0
packages/common/src/shared-types.ts

@@ -72,4 +72,6 @@ export interface AdminUiConfig {
     apiHost: string | 'auto';
     apiPort: number | 'auto';
     adminApiPath: string;
+    tokenMethod: 'cookie' | 'bearer';
+    authTokenHeaderKey: string;
 }