]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/standalone/videos/shared/auth-http.ts
Merge branch 'release/4.2.0' into develop
[github/Chocobozzz/PeerTube.git] / client / src / standalone / videos / shared / auth-http.ts
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 }