]>
Commit | Line | Data |
---|---|---|
f1a0f3b7 | 1 | import { HttpStatusCode, OAuth2ErrorCode, UserRefreshToken } from '../../../../../shared/models' |
3545e72c | 2 | import { OAuthUserTokens, objectToUrlEncoded } from '../../../root-helpers' |
f1a0f3b7 C |
3 | import { peertubeLocalStorage } from '../../../root-helpers/peertube-web-storage' |
4 | ||
5 | export class AuthHTTP { | |
6 | private readonly LOCAL_STORAGE_OAUTH_CLIENT_KEYS = { | |
7 | CLIENT_ID: 'client_id', | |
8 | CLIENT_SECRET: 'client_secret' | |
9 | } | |
10 | ||
3545e72c | 11 | private userOAuthTokens: OAuthUserTokens |
f1a0f3b7 C |
12 | |
13 | private headers = new Headers() | |
14 | ||
15 | constructor () { | |
3545e72c | 16 | this.userOAuthTokens = OAuthUserTokens.getUserTokens(peertubeLocalStorage) |
f1a0f3b7 | 17 | |
3545e72c | 18 | if (this.userOAuthTokens) this.setHeadersFromTokens() |
f1a0f3b7 C |
19 | } |
20 | ||
3545e72c | 21 | fetch (url: string, { optionalAuth, method }: { optionalAuth: boolean, method?: string }) { |
f1a0f3b7 C |
22 | const refreshFetchOptions = optionalAuth |
23 | ? { headers: this.headers } | |
24 | : {} | |
25 | ||
3545e72c | 26 | return this.refreshFetch(url.toString(), { ...refreshFetchOptions, method }) |
f1a0f3b7 C |
27 | } |
28 | ||
29 | getHeaderTokenValue () { | |
49e7e4d9 C |
30 | if (!this.userOAuthTokens) return null |
31 | ||
3545e72c | 32 | return `${this.userOAuthTokens.tokenType} ${this.userOAuthTokens.accessToken}` |
f1a0f3b7 C |
33 | } |
34 | ||
35 | isLoggedIn () { | |
3545e72c | 36 | return !!this.userOAuthTokens |
f1a0f3b7 C |
37 | } |
38 | ||
39 | private refreshFetch (url: string, options?: RequestInit) { | |
40 | return fetch(url, options) | |
41 | .then((res: Response) => { | |
42 | if (res.status !== HttpStatusCode.UNAUTHORIZED_401) return res | |
43 | ||
44 | const refreshingTokenPromise = new Promise<void>((resolve, reject) => { | |
45 | const clientId: string = peertubeLocalStorage.getItem(this.LOCAL_STORAGE_OAUTH_CLIENT_KEYS.CLIENT_ID) | |
46 | const clientSecret: string = peertubeLocalStorage.getItem(this.LOCAL_STORAGE_OAUTH_CLIENT_KEYS.CLIENT_SECRET) | |
47 | ||
48 | const headers = new Headers() | |
49 | headers.set('Content-Type', 'application/x-www-form-urlencoded') | |
50 | ||
51 | const data = { | |
3545e72c | 52 | refresh_token: this.userOAuthTokens.refreshToken, |
f1a0f3b7 C |
53 | client_id: clientId, |
54 | client_secret: clientSecret, | |
55 | response_type: 'code', | |
56 | grant_type: 'refresh_token' | |
57 | } | |
58 | ||
59 | fetch('/api/v1/users/token', { | |
60 | headers, | |
61 | method: 'POST', | |
62 | body: objectToUrlEncoded(data) | |
63 | }).then(res => { | |
64 | if (res.status === HttpStatusCode.UNAUTHORIZED_401) return undefined | |
65 | ||
66 | return res.json() | |
67 | }).then((obj: UserRefreshToken & { code?: OAuth2ErrorCode }) => { | |
68 | if (!obj || obj.code === OAuth2ErrorCode.INVALID_GRANT) { | |
3545e72c | 69 | OAuthUserTokens.flushLocalStorage(peertubeLocalStorage) |
f1a0f3b7 C |
70 | this.removeTokensFromHeaders() |
71 | ||
72 | return resolve() | |
73 | } | |
74 | ||
3545e72c C |
75 | this.userOAuthTokens.accessToken = obj.access_token |
76 | this.userOAuthTokens.refreshToken = obj.refresh_token | |
77 | OAuthUserTokens.saveToLocalStorage(peertubeLocalStorage, this.userOAuthTokens) | |
f1a0f3b7 C |
78 | |
79 | this.setHeadersFromTokens() | |
80 | ||
81 | resolve() | |
82 | }).catch((refreshTokenError: any) => { | |
83 | reject(refreshTokenError) | |
84 | }) | |
85 | }) | |
86 | ||
87 | return refreshingTokenPromise | |
88 | .catch(() => { | |
3545e72c | 89 | OAuthUserTokens.flushLocalStorage(peertubeLocalStorage) |
f1a0f3b7 C |
90 | |
91 | this.removeTokensFromHeaders() | |
92 | }).then(() => fetch(url, { | |
93 | ...options, | |
94 | ||
95 | headers: this.headers | |
96 | })) | |
97 | }) | |
98 | } | |
99 | ||
100 | private setHeadersFromTokens () { | |
101 | this.headers.set('Authorization', this.getHeaderTokenValue()) | |
102 | } | |
103 | ||
104 | private removeTokensFromHeaders () { | |
105 | this.headers.delete('Authorization') | |
106 | } | |
107 | } |