aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/shared/auth
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/shared/auth')
-rw-r--r--client/src/app/shared/auth/auth-http.service.ts93
-rw-r--r--client/src/app/shared/auth/auth-interceptor.service.ts62
-rw-r--r--client/src/app/shared/auth/index.ts2
3 files changed, 63 insertions, 94 deletions
diff --git a/client/src/app/shared/auth/auth-http.service.ts b/client/src/app/shared/auth/auth-http.service.ts
deleted file mode 100644
index 0fbaab0a8..000000000
--- a/client/src/app/shared/auth/auth-http.service.ts
+++ /dev/null
@@ -1,93 +0,0 @@
1import { Injectable } from '@angular/core'
2import {
3 ConnectionBackend,
4 Headers,
5 Http,
6 Request,
7 RequestMethod,
8 RequestOptions,
9 RequestOptionsArgs,
10 Response,
11 XHRBackend
12} from '@angular/http'
13import { Observable } from 'rxjs/Observable'
14
15import { AuthService } from '../../core'
16
17@Injectable()
18export class AuthHttp extends Http {
19 constructor (backend: ConnectionBackend, defaultOptions: RequestOptions, private authService: AuthService) {
20 super(backend, defaultOptions)
21 }
22
23 request (url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
24 if (!options) options = {}
25
26 options.headers = new Headers()
27 this.setAuthorizationHeader(options.headers)
28
29 return super.request(url, options)
30 .catch((err) => {
31 if (err.status === 401) {
32 return this.handleTokenExpired(url, options)
33 }
34
35 return Observable.throw(err)
36 })
37 }
38
39 delete (url: string, options?: RequestOptionsArgs): Observable<Response> {
40 if (!options) options = {}
41 options.method = RequestMethod.Delete
42
43 return this.request(url, options)
44 }
45
46 get (url: string, options?: RequestOptionsArgs): Observable<Response> {
47 if (!options) options = {}
48 options.method = RequestMethod.Get
49
50 return this.request(url, options)
51 }
52
53 post (url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
54 if (!options) options = {}
55 options.method = RequestMethod.Post
56 options.body = body
57
58 return this.request(url, options)
59 }
60
61 put (url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
62 if (!options) options = {}
63 options.method = RequestMethod.Put
64 options.body = body
65
66 return this.request(url, options)
67 }
68
69 private handleTokenExpired (url: string | Request, options: RequestOptionsArgs) {
70 return this.authService.refreshAccessToken()
71 .flatMap(() => {
72 this.setAuthorizationHeader(options.headers)
73
74 return super.request(url, options)
75 })
76 }
77
78 private setAuthorizationHeader (headers: Headers) {
79 headers.set('Authorization', this.authService.getRequestHeaderValue())
80 }
81}
82
83export function useFactory (backend: XHRBackend, defaultOptions: RequestOptions, authService: AuthService) {
84 return new AuthHttp(backend, defaultOptions, authService)
85}
86
87export const AUTH_HTTP_PROVIDERS = [
88 {
89 provide: AuthHttp,
90 useFactory,
91 deps: [ XHRBackend, RequestOptions, AuthService ]
92 }
93]
diff --git a/client/src/app/shared/auth/auth-interceptor.service.ts b/client/src/app/shared/auth/auth-interceptor.service.ts
new file mode 100644
index 000000000..1e890d8f3
--- /dev/null
+++ b/client/src/app/shared/auth/auth-interceptor.service.ts
@@ -0,0 +1,62 @@
1import { Injectable, Injector } from '@angular/core'
2import {
3 HttpInterceptor,
4 HttpRequest,
5 HttpEvent,
6 HttpHandler, HTTP_INTERCEPTORS
7} from '@angular/common/http'
8import { Observable } from 'rxjs/Observable'
9
10import { AuthService } from '../../core'
11import 'rxjs/add/operator/switchMap'
12
13@Injectable()
14export class AuthInterceptor implements HttpInterceptor {
15 private authService: AuthService
16
17 // https://github.com/angular/angular/issues/18224#issuecomment-316957213
18 constructor (private injector: Injector) {}
19
20 intercept (req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
21 if (this.authService === undefined) {
22 this.authService = this.injector.get(AuthService)
23 }
24
25 const authReq = this.cloneRequestWithAuth(req)
26
27 // Pass on the cloned request instead of the original request
28 // Catch 401 errors (refresh token expired)
29 return next.handle(authReq)
30 .catch(err => {
31 if (err.status === 401) {
32 return this.handleTokenExpired(req, next)
33 }
34
35 return Observable.throw(err)
36 })
37 }
38
39 private handleTokenExpired (req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
40 return this.authService.refreshAccessToken()
41 .switchMap(() => {
42 const authReq = this.cloneRequestWithAuth(req)
43
44 return next.handle(authReq)
45 })
46 }
47
48 private cloneRequestWithAuth (req: HttpRequest<any>) {
49 const authHeaderValue = this.authService.getRequestHeaderValue()
50
51 if (authHeaderValue === null) return req
52
53 // Clone the request to add the new header
54 return req.clone({ headers: req.headers.set('Authorization', authHeaderValue) })
55 }
56}
57
58export const AUTH_INTERCEPTOR_PROVIDER = {
59 provide: HTTP_INTERCEPTORS,
60 useClass: AuthInterceptor,
61 multi: true
62}
diff --git a/client/src/app/shared/auth/index.ts b/client/src/app/shared/auth/index.ts
index 0f2bfb0d6..84a07196f 100644
--- a/client/src/app/shared/auth/index.ts
+++ b/client/src/app/shared/auth/index.ts
@@ -1 +1 @@
export * from './auth-http.service' export * from './auth-interceptor.service'