diff options
Diffstat (limited to 'client/src/standalone/videos/shared/auth-http.ts')
-rw-r--r-- | client/src/standalone/videos/shared/auth-http.ts | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/client/src/standalone/videos/shared/auth-http.ts b/client/src/standalone/videos/shared/auth-http.ts new file mode 100644 index 000000000..0356ab8a6 --- /dev/null +++ b/client/src/standalone/videos/shared/auth-http.ts | |||
@@ -0,0 +1,105 @@ | |||
1 | import { HttpStatusCode, OAuth2ErrorCode, UserRefreshToken } from '../../../../../shared/models' | ||
2 | import { objectToUrlEncoded, UserTokens } from '../../../root-helpers' | ||
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 | |||
11 | private userTokens: UserTokens | ||
12 | |||
13 | private headers = new Headers() | ||
14 | |||
15 | constructor () { | ||
16 | this.userTokens = UserTokens.getUserTokens(peertubeLocalStorage) | ||
17 | |||
18 | if (this.userTokens) this.setHeadersFromTokens() | ||
19 | } | ||
20 | |||
21 | fetch (url: string, { optionalAuth }: { optionalAuth: boolean }) { | ||
22 | const refreshFetchOptions = optionalAuth | ||
23 | ? { headers: this.headers } | ||
24 | : {} | ||
25 | |||
26 | return this.refreshFetch(url.toString(), refreshFetchOptions) | ||
27 | } | ||
28 | |||
29 | getHeaderTokenValue () { | ||
30 | return `${this.userTokens.tokenType} ${this.userTokens.accessToken}` | ||
31 | } | ||
32 | |||
33 | isLoggedIn () { | ||
34 | return !!this.userTokens | ||
35 | } | ||
36 | |||
37 | private refreshFetch (url: string, options?: RequestInit) { | ||
38 | return fetch(url, options) | ||
39 | .then((res: Response) => { | ||
40 | if (res.status !== HttpStatusCode.UNAUTHORIZED_401) return res | ||
41 | |||
42 | const refreshingTokenPromise = new Promise<void>((resolve, reject) => { | ||
43 | const clientId: string = peertubeLocalStorage.getItem(this.LOCAL_STORAGE_OAUTH_CLIENT_KEYS.CLIENT_ID) | ||
44 | const clientSecret: string = peertubeLocalStorage.getItem(this.LOCAL_STORAGE_OAUTH_CLIENT_KEYS.CLIENT_SECRET) | ||
45 | |||
46 | const headers = new Headers() | ||
47 | headers.set('Content-Type', 'application/x-www-form-urlencoded') | ||
48 | |||
49 | const data = { | ||
50 | refresh_token: this.userTokens.refreshToken, | ||
51 | client_id: clientId, | ||
52 | client_secret: clientSecret, | ||
53 | response_type: 'code', | ||
54 | grant_type: 'refresh_token' | ||
55 | } | ||
56 | |||
57 | fetch('/api/v1/users/token', { | ||
58 | headers, | ||
59 | method: 'POST', | ||
60 | body: objectToUrlEncoded(data) | ||
61 | }).then(res => { | ||
62 | if (res.status === HttpStatusCode.UNAUTHORIZED_401) return undefined | ||
63 | |||
64 | return res.json() | ||
65 | }).then((obj: UserRefreshToken & { code?: OAuth2ErrorCode }) => { | ||
66 | if (!obj || obj.code === OAuth2ErrorCode.INVALID_GRANT) { | ||
67 | UserTokens.flushLocalStorage(peertubeLocalStorage) | ||
68 | this.removeTokensFromHeaders() | ||
69 | |||
70 | return resolve() | ||
71 | } | ||
72 | |||
73 | this.userTokens.accessToken = obj.access_token | ||
74 | this.userTokens.refreshToken = obj.refresh_token | ||
75 | UserTokens.saveToLocalStorage(peertubeLocalStorage, this.userTokens) | ||
76 | |||
77 | this.setHeadersFromTokens() | ||
78 | |||
79 | resolve() | ||
80 | }).catch((refreshTokenError: any) => { | ||
81 | reject(refreshTokenError) | ||
82 | }) | ||
83 | }) | ||
84 | |||
85 | return refreshingTokenPromise | ||
86 | .catch(() => { | ||
87 | UserTokens.flushLocalStorage(peertubeLocalStorage) | ||
88 | |||
89 | this.removeTokensFromHeaders() | ||
90 | }).then(() => fetch(url, { | ||
91 | ...options, | ||
92 | |||
93 | headers: this.headers | ||
94 | })) | ||
95 | }) | ||
96 | } | ||
97 | |||
98 | private setHeadersFromTokens () { | ||
99 | this.headers.set('Authorization', this.getHeaderTokenValue()) | ||
100 | } | ||
101 | |||
102 | private removeTokensFromHeaders () { | ||
103 | this.headers.delete('Authorization') | ||
104 | } | ||
105 | } | ||