@jbrowse/plugin-authentication 2.5.0 → 2.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/DropboxOAuthModel/configSchema.d.ts +3 -14
- package/dist/DropboxOAuthModel/configSchema.js +0 -9
- package/dist/DropboxOAuthModel/index.js +0 -1
- package/dist/DropboxOAuthModel/model.d.ts +35 -33
- package/dist/DropboxOAuthModel/model.js +26 -36
- package/dist/DropboxOAuthModel/util.d.ts +1 -0
- package/dist/DropboxOAuthModel/util.js +27 -0
- package/dist/ExternalTokenModel/ExternalTokenEntryForm.d.ts +2 -1
- package/dist/ExternalTokenModel/ExternalTokenEntryForm.js +10 -12
- package/dist/ExternalTokenModel/configSchema.js +0 -1
- package/dist/ExternalTokenModel/index.js +0 -1
- package/dist/ExternalTokenModel/model.js +0 -1
- package/dist/GoogleDriveOAuthModel/GoogleDriveFilehandle.d.ts +15 -0
- package/dist/GoogleDriveOAuthModel/GoogleDriveFilehandle.js +19 -0
- package/dist/GoogleDriveOAuthModel/configSchema.d.ts +0 -5
- package/dist/GoogleDriveOAuthModel/configSchema.js +0 -1
- package/dist/GoogleDriveOAuthModel/index.js +0 -1
- package/dist/GoogleDriveOAuthModel/model.d.ts +36 -121
- package/dist/GoogleDriveOAuthModel/model.js +38 -52
- package/dist/GoogleDriveOAuthModel/util.d.ts +1 -0
- package/dist/GoogleDriveOAuthModel/util.js +16 -0
- package/dist/HTTPBasicModel/HTTPBasicLoginForm.d.ts +2 -1
- package/dist/HTTPBasicModel/HTTPBasicLoginForm.js +17 -22
- package/dist/HTTPBasicModel/configSchema.js +0 -1
- package/dist/HTTPBasicModel/index.js +0 -1
- package/dist/HTTPBasicModel/model.d.ts +36 -4
- package/dist/HTTPBasicModel/model.js +24 -10
- package/dist/OAuthModel/configSchema.d.ts +0 -8
- package/dist/OAuthModel/configSchema.js +1 -10
- package/dist/OAuthModel/index.js +0 -1
- package/dist/OAuthModel/model.d.ts +103 -18
- package/dist/OAuthModel/model.js +165 -114
- package/dist/OAuthModel/util.d.ts +7 -0
- package/dist/OAuthModel/util.js +59 -0
- package/dist/index.d.ts +7 -433
- package/dist/index.js +0 -1
- package/dist/util.d.ts +6 -0
- package/dist/util.js +22 -0
- package/esm/DropboxOAuthModel/configSchema.d.ts +3 -14
- package/esm/DropboxOAuthModel/configSchema.js +0 -9
- package/esm/DropboxOAuthModel/index.js +0 -1
- package/esm/DropboxOAuthModel/model.d.ts +35 -33
- package/esm/DropboxOAuthModel/model.js +26 -36
- package/esm/DropboxOAuthModel/util.d.ts +1 -0
- package/esm/DropboxOAuthModel/util.js +23 -0
- package/esm/ExternalTokenModel/ExternalTokenEntryForm.d.ts +2 -1
- package/esm/ExternalTokenModel/ExternalTokenEntryForm.js +10 -12
- package/esm/ExternalTokenModel/configSchema.js +0 -1
- package/esm/ExternalTokenModel/index.js +0 -1
- package/esm/ExternalTokenModel/model.js +0 -1
- package/esm/GoogleDriveOAuthModel/GoogleDriveFilehandle.d.ts +15 -0
- package/esm/GoogleDriveOAuthModel/GoogleDriveFilehandle.js +15 -0
- package/esm/GoogleDriveOAuthModel/configSchema.d.ts +0 -5
- package/esm/GoogleDriveOAuthModel/configSchema.js +0 -1
- package/esm/GoogleDriveOAuthModel/index.js +0 -1
- package/esm/GoogleDriveOAuthModel/model.d.ts +36 -121
- package/esm/GoogleDriveOAuthModel/model.js +37 -50
- package/esm/GoogleDriveOAuthModel/util.d.ts +1 -0
- package/esm/GoogleDriveOAuthModel/util.js +12 -0
- package/esm/HTTPBasicModel/HTTPBasicLoginForm.d.ts +2 -1
- package/esm/HTTPBasicModel/HTTPBasicLoginForm.js +18 -23
- package/esm/HTTPBasicModel/configSchema.js +0 -1
- package/esm/HTTPBasicModel/index.js +0 -1
- package/esm/HTTPBasicModel/model.d.ts +36 -4
- package/esm/HTTPBasicModel/model.js +24 -10
- package/esm/OAuthModel/configSchema.d.ts +0 -8
- package/esm/OAuthModel/configSchema.js +1 -10
- package/esm/OAuthModel/index.js +0 -1
- package/esm/OAuthModel/model.d.ts +103 -18
- package/esm/OAuthModel/model.js +164 -87
- package/esm/OAuthModel/util.d.ts +7 -0
- package/esm/OAuthModel/util.js +29 -0
- package/esm/index.d.ts +7 -433
- package/esm/index.js +0 -1
- package/esm/util.d.ts +6 -0
- package/esm/util.js +17 -0
- package/package.json +4 -6
- package/dist/DropboxOAuthModel/configSchema.js.map +0 -1
- package/dist/DropboxOAuthModel/index.js.map +0 -1
- package/dist/DropboxOAuthModel/model.js.map +0 -1
- package/dist/ExternalTokenModel/ExternalTokenEntryForm.js.map +0 -1
- package/dist/ExternalTokenModel/configSchema.js.map +0 -1
- package/dist/ExternalTokenModel/index.js.map +0 -1
- package/dist/ExternalTokenModel/model.js.map +0 -1
- package/dist/GoogleDriveOAuthModel/configSchema.js.map +0 -1
- package/dist/GoogleDriveOAuthModel/index.js.map +0 -1
- package/dist/GoogleDriveOAuthModel/model.js.map +0 -1
- package/dist/HTTPBasicModel/HTTPBasicLoginForm.js.map +0 -1
- package/dist/HTTPBasicModel/configSchema.js.map +0 -1
- package/dist/HTTPBasicModel/index.js.map +0 -1
- package/dist/HTTPBasicModel/model.js.map +0 -1
- package/dist/OAuthModel/configSchema.js.map +0 -1
- package/dist/OAuthModel/index.js.map +0 -1
- package/dist/OAuthModel/model.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/esm/DropboxOAuthModel/configSchema.js.map +0 -1
- package/esm/DropboxOAuthModel/index.js.map +0 -1
- package/esm/DropboxOAuthModel/model.js.map +0 -1
- package/esm/ExternalTokenModel/ExternalTokenEntryForm.js.map +0 -1
- package/esm/ExternalTokenModel/configSchema.js.map +0 -1
- package/esm/ExternalTokenModel/index.js.map +0 -1
- package/esm/ExternalTokenModel/model.js.map +0 -1
- package/esm/GoogleDriveOAuthModel/configSchema.js.map +0 -1
- package/esm/GoogleDriveOAuthModel/index.js.map +0 -1
- package/esm/GoogleDriveOAuthModel/model.js.map +0 -1
- package/esm/HTTPBasicModel/HTTPBasicLoginForm.js.map +0 -1
- package/esm/HTTPBasicModel/configSchema.js.map +0 -1
- package/esm/HTTPBasicModel/index.js.map +0 -1
- package/esm/HTTPBasicModel/model.js.map +0 -1
- package/esm/OAuthModel/configSchema.js.map +0 -1
- package/esm/OAuthModel/index.js.map +0 -1
- package/esm/OAuthModel/model.js.map +0 -1
- package/esm/index.js.map +0 -1
- package/src/DropboxOAuthModel/configSchema.ts +0 -77
- package/src/DropboxOAuthModel/index.ts +0 -2
- package/src/DropboxOAuthModel/model.tsx +0 -141
- package/src/ExternalTokenModel/ExternalTokenEntryForm.tsx +0 -57
- package/src/ExternalTokenModel/configSchema.ts +0 -36
- package/src/ExternalTokenModel/index.ts +0 -2
- package/src/ExternalTokenModel/model.tsx +0 -70
- package/src/GoogleDriveOAuthModel/configSchema.ts +0 -61
- package/src/GoogleDriveOAuthModel/index.ts +0 -2
- package/src/GoogleDriveOAuthModel/model.tsx +0 -174
- package/src/HTTPBasicModel/HTTPBasicLoginForm.tsx +0 -71
- package/src/HTTPBasicModel/configSchema.ts +0 -43
- package/src/HTTPBasicModel/index.ts +0 -2
- package/src/HTTPBasicModel/model.tsx +0 -70
- package/src/OAuthModel/configSchema.ts +0 -98
- package/src/OAuthModel/index.ts +0 -2
- package/src/OAuthModel/model.tsx +0 -348
- package/src/__snapshots__/index.test.js.snap +0 -8
- package/src/index.test.js +0 -96
- package/src/index.ts +0 -108
package/src/OAuthModel/model.tsx
DELETED
|
@@ -1,348 +0,0 @@
|
|
|
1
|
-
import { ConfigurationReference, getConf } from '@jbrowse/core/configuration'
|
|
2
|
-
import { InternetAccount } from '@jbrowse/core/pluggableElementTypes/models'
|
|
3
|
-
import { isElectron, UriLocation } from '@jbrowse/core/util'
|
|
4
|
-
import { Instance, types } from 'mobx-state-tree'
|
|
5
|
-
import jwtDecode, { JwtPayload } from 'jwt-decode'
|
|
6
|
-
|
|
7
|
-
// locals
|
|
8
|
-
import { OAuthInternetAccountConfigModel } from './configSchema'
|
|
9
|
-
|
|
10
|
-
interface OAuthData {
|
|
11
|
-
client_id: string
|
|
12
|
-
redirect_uri: string
|
|
13
|
-
response_type: 'token' | 'code'
|
|
14
|
-
scope?: string
|
|
15
|
-
code_challenge?: string
|
|
16
|
-
code_challenge_method?: string
|
|
17
|
-
token_access_type?: string
|
|
18
|
-
state?: string
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function fixup(buf: string) {
|
|
22
|
-
return buf.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '')
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const stateModelFactory = (configSchema: OAuthInternetAccountConfigModel) => {
|
|
26
|
-
return InternetAccount.named('OAuthInternetAccount')
|
|
27
|
-
.props({
|
|
28
|
-
type: types.literal('OAuthInternetAccount'),
|
|
29
|
-
configuration: ConfigurationReference(configSchema),
|
|
30
|
-
})
|
|
31
|
-
.views(() => {
|
|
32
|
-
let codeVerifier: string | undefined = undefined
|
|
33
|
-
return {
|
|
34
|
-
get codeVerifierPKCE() {
|
|
35
|
-
if (codeVerifier) {
|
|
36
|
-
return codeVerifier
|
|
37
|
-
}
|
|
38
|
-
const array = new Uint8Array(32)
|
|
39
|
-
globalThis.crypto.getRandomValues(array)
|
|
40
|
-
codeVerifier = fixup(Buffer.from(array).toString('base64'))
|
|
41
|
-
return codeVerifier
|
|
42
|
-
},
|
|
43
|
-
}
|
|
44
|
-
})
|
|
45
|
-
.views(self => ({
|
|
46
|
-
get authEndpoint(): string {
|
|
47
|
-
return getConf(self, 'authEndpoint')
|
|
48
|
-
},
|
|
49
|
-
get tokenEndpoint(): string {
|
|
50
|
-
return getConf(self, 'tokenEndpoint')
|
|
51
|
-
},
|
|
52
|
-
get needsPKCE(): boolean {
|
|
53
|
-
return getConf(self, 'needsPKCE')
|
|
54
|
-
},
|
|
55
|
-
get clientId(): string {
|
|
56
|
-
return getConf(self, 'clientId')
|
|
57
|
-
},
|
|
58
|
-
get scopes(): string {
|
|
59
|
-
return getConf(self, 'scopes')
|
|
60
|
-
},
|
|
61
|
-
/**
|
|
62
|
-
* OAuth state parameter: https://www.rfc-editor.org/rfc/rfc6749#section-4.1.1
|
|
63
|
-
* Can override or extend if dynamic state is needed.
|
|
64
|
-
*/
|
|
65
|
-
state(): string | undefined {
|
|
66
|
-
return getConf(self, 'state') || undefined
|
|
67
|
-
},
|
|
68
|
-
get responseType(): 'token' | 'code' {
|
|
69
|
-
return getConf(self, 'responseType')
|
|
70
|
-
},
|
|
71
|
-
get hasRefreshToken(): boolean {
|
|
72
|
-
return getConf(self, 'hasRefreshToken')
|
|
73
|
-
},
|
|
74
|
-
get refreshTokenKey() {
|
|
75
|
-
return `${self.internetAccountId}-refreshToken`
|
|
76
|
-
},
|
|
77
|
-
}))
|
|
78
|
-
.actions(self => ({
|
|
79
|
-
storeRefreshToken(refreshToken: string) {
|
|
80
|
-
localStorage.setItem(self.refreshTokenKey, refreshToken)
|
|
81
|
-
},
|
|
82
|
-
removeRefreshToken() {
|
|
83
|
-
localStorage.removeItem(self.refreshTokenKey)
|
|
84
|
-
},
|
|
85
|
-
retrieveRefreshToken() {
|
|
86
|
-
return localStorage.getItem(self.refreshTokenKey)
|
|
87
|
-
},
|
|
88
|
-
async exchangeAuthorizationForAccessToken(
|
|
89
|
-
token: string,
|
|
90
|
-
redirectUri: string,
|
|
91
|
-
): Promise<string> {
|
|
92
|
-
const data = {
|
|
93
|
-
code: token,
|
|
94
|
-
grant_type: 'authorization_code',
|
|
95
|
-
client_id: self.clientId,
|
|
96
|
-
code_verifier: self.codeVerifierPKCE,
|
|
97
|
-
redirect_uri: redirectUri,
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const params = new URLSearchParams(Object.entries(data))
|
|
101
|
-
|
|
102
|
-
const response = await fetch(self.tokenEndpoint, {
|
|
103
|
-
method: 'POST',
|
|
104
|
-
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
105
|
-
body: params.toString(),
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
if (!response.ok) {
|
|
109
|
-
let errorMessage
|
|
110
|
-
try {
|
|
111
|
-
errorMessage = await response.text()
|
|
112
|
-
} catch (error) {
|
|
113
|
-
errorMessage = ''
|
|
114
|
-
}
|
|
115
|
-
throw new Error(
|
|
116
|
-
`Failed to obtain token from endpoint: ${response.status} (${
|
|
117
|
-
response.statusText
|
|
118
|
-
})${errorMessage ? ` (${errorMessage})` : ''}`,
|
|
119
|
-
)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const accessToken = await response.json()
|
|
123
|
-
if (accessToken.refresh_token) {
|
|
124
|
-
this.storeRefreshToken(accessToken.refresh_token)
|
|
125
|
-
}
|
|
126
|
-
return accessToken.access_token
|
|
127
|
-
},
|
|
128
|
-
async exchangeRefreshForAccessToken(
|
|
129
|
-
refreshToken: string,
|
|
130
|
-
): Promise<string> {
|
|
131
|
-
const data = {
|
|
132
|
-
grant_type: 'refresh_token',
|
|
133
|
-
refresh_token: refreshToken,
|
|
134
|
-
client_id: self.clientId,
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const params = new URLSearchParams(Object.entries(data))
|
|
138
|
-
|
|
139
|
-
const response = await fetch(self.tokenEndpoint, {
|
|
140
|
-
method: 'POST',
|
|
141
|
-
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
142
|
-
body: params.toString(),
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
if (!response.ok) {
|
|
146
|
-
self.removeToken()
|
|
147
|
-
let text = await response.text()
|
|
148
|
-
try {
|
|
149
|
-
const obj = JSON.parse(text)
|
|
150
|
-
if (obj.error === 'invalid_grant') {
|
|
151
|
-
this.removeRefreshToken()
|
|
152
|
-
}
|
|
153
|
-
text = obj?.error_description ?? text
|
|
154
|
-
} catch (e) {
|
|
155
|
-
/* just use original text as error */
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
throw new Error(
|
|
159
|
-
`Network response failure — ${response.status} (${
|
|
160
|
-
response.statusText
|
|
161
|
-
}) ${text ? ` (${text})` : ''}`,
|
|
162
|
-
)
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const accessToken = await response.json()
|
|
166
|
-
if (accessToken.refresh_token) {
|
|
167
|
-
this.storeRefreshToken(accessToken.refresh_token)
|
|
168
|
-
}
|
|
169
|
-
return accessToken.access_token
|
|
170
|
-
},
|
|
171
|
-
}))
|
|
172
|
-
.actions(self => {
|
|
173
|
-
let listener: (event: MessageEvent) => void
|
|
174
|
-
let refreshTokenPromise: Promise<string> | undefined = undefined
|
|
175
|
-
return {
|
|
176
|
-
// used to listen to child window for auth code/token
|
|
177
|
-
addMessageChannel(
|
|
178
|
-
resolve: (token: string) => void,
|
|
179
|
-
reject: (error: Error) => void,
|
|
180
|
-
) {
|
|
181
|
-
listener = event => {
|
|
182
|
-
// this should probably get better handling, but ignored for now
|
|
183
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
184
|
-
this.finishOAuthWindow(event, resolve, reject)
|
|
185
|
-
}
|
|
186
|
-
window.addEventListener('message', listener)
|
|
187
|
-
},
|
|
188
|
-
deleteMessageChannel() {
|
|
189
|
-
window.removeEventListener('message', listener)
|
|
190
|
-
},
|
|
191
|
-
async finishOAuthWindow(
|
|
192
|
-
event: MessageEvent,
|
|
193
|
-
resolve: (token: string) => void,
|
|
194
|
-
reject: (error: Error) => void,
|
|
195
|
-
) {
|
|
196
|
-
if (
|
|
197
|
-
event.data.name !== `JBrowseAuthWindow-${self.internetAccountId}`
|
|
198
|
-
) {
|
|
199
|
-
return this.deleteMessageChannel()
|
|
200
|
-
}
|
|
201
|
-
const redirectUriWithInfo = event.data.redirectUri
|
|
202
|
-
const fixedQueryString = redirectUriWithInfo.replace('#', '?')
|
|
203
|
-
const redirectUrl = new URL(fixedQueryString)
|
|
204
|
-
const queryStringSearch = redirectUrl.search
|
|
205
|
-
const urlParams = new URLSearchParams(queryStringSearch)
|
|
206
|
-
if (urlParams.has('access_token')) {
|
|
207
|
-
const token = urlParams.get('access_token')
|
|
208
|
-
if (!token) {
|
|
209
|
-
return reject(new Error('Error with token endpoint'))
|
|
210
|
-
}
|
|
211
|
-
self.storeToken(token)
|
|
212
|
-
return resolve(token)
|
|
213
|
-
}
|
|
214
|
-
if (urlParams.has('code')) {
|
|
215
|
-
const code = urlParams.get('code')
|
|
216
|
-
if (!code) {
|
|
217
|
-
return reject(new Error('Error with authorization endpoint'))
|
|
218
|
-
}
|
|
219
|
-
try {
|
|
220
|
-
const token = await self.exchangeAuthorizationForAccessToken(
|
|
221
|
-
code,
|
|
222
|
-
redirectUrl.origin + redirectUrl.pathname,
|
|
223
|
-
)
|
|
224
|
-
self.storeToken(token)
|
|
225
|
-
return resolve(token)
|
|
226
|
-
} catch (error) {
|
|
227
|
-
return error instanceof Error
|
|
228
|
-
? reject(error)
|
|
229
|
-
: reject(new Error(String(error)))
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
if (redirectUriWithInfo.includes('access_denied')) {
|
|
233
|
-
return reject(new Error('OAuth flow was cancelled'))
|
|
234
|
-
}
|
|
235
|
-
if (redirectUriWithInfo.includes('error')) {
|
|
236
|
-
return reject(new Error('Oauth flow error: ' + queryStringSearch))
|
|
237
|
-
}
|
|
238
|
-
this.deleteMessageChannel()
|
|
239
|
-
},
|
|
240
|
-
// opens external OAuth flow, popup for web and new browser window for desktop
|
|
241
|
-
async useEndpointForAuthorization(
|
|
242
|
-
resolve: (token: string) => void,
|
|
243
|
-
reject: (error: Error) => void,
|
|
244
|
-
) {
|
|
245
|
-
const redirectUri = isElectron
|
|
246
|
-
? 'http://localhost/auth'
|
|
247
|
-
: window.location.origin + window.location.pathname
|
|
248
|
-
const data: OAuthData = {
|
|
249
|
-
client_id: self.clientId,
|
|
250
|
-
redirect_uri: redirectUri,
|
|
251
|
-
response_type: self.responseType || 'code',
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (self.state()) {
|
|
255
|
-
data.state = self.state()
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
if (self.scopes) {
|
|
259
|
-
data.scope = self.scopes
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
if (self.needsPKCE) {
|
|
263
|
-
const { codeVerifierPKCE } = self
|
|
264
|
-
|
|
265
|
-
const sha256 = await import('crypto-js/sha256').then(f => f.default)
|
|
266
|
-
const Base64 = await import('crypto-js/enc-base64')
|
|
267
|
-
const codeChallenge = fixup(
|
|
268
|
-
Base64.stringify(sha256(codeVerifierPKCE)),
|
|
269
|
-
)
|
|
270
|
-
data.code_challenge = codeChallenge
|
|
271
|
-
data.code_challenge_method = 'S256'
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
if (self.hasRefreshToken) {
|
|
275
|
-
data.token_access_type = 'offline'
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
const params = new URLSearchParams(Object.entries(data))
|
|
279
|
-
|
|
280
|
-
const url = new URL(self.authEndpoint)
|
|
281
|
-
url.search = params.toString()
|
|
282
|
-
|
|
283
|
-
const eventName = `JBrowseAuthWindow-${self.internetAccountId}`
|
|
284
|
-
if (isElectron) {
|
|
285
|
-
const { ipcRenderer } = window.require('electron')
|
|
286
|
-
const redirectUri = await ipcRenderer.invoke('openAuthWindow', {
|
|
287
|
-
internetAccountId: self.internetAccountId,
|
|
288
|
-
data,
|
|
289
|
-
url: url.toString(),
|
|
290
|
-
})
|
|
291
|
-
|
|
292
|
-
const eventFromDesktop = new MessageEvent('message', {
|
|
293
|
-
data: { name: eventName, redirectUri: redirectUri },
|
|
294
|
-
})
|
|
295
|
-
// may want to improve handling
|
|
296
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
297
|
-
this.finishOAuthWindow(eventFromDesktop, resolve, reject)
|
|
298
|
-
} else {
|
|
299
|
-
const options = `width=500,height=600,left=0,top=0`
|
|
300
|
-
window.open(url, eventName, options)
|
|
301
|
-
}
|
|
302
|
-
},
|
|
303
|
-
async getTokenFromUser(
|
|
304
|
-
resolve: (token: string) => void,
|
|
305
|
-
reject: (error: Error) => void,
|
|
306
|
-
): Promise<void> {
|
|
307
|
-
const refreshToken =
|
|
308
|
-
self.hasRefreshToken && self.retrieveRefreshToken()
|
|
309
|
-
if (refreshToken) {
|
|
310
|
-
resolve(await self.exchangeRefreshForAccessToken(refreshToken))
|
|
311
|
-
}
|
|
312
|
-
this.addMessageChannel(resolve, reject)
|
|
313
|
-
// may want to improve handling
|
|
314
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
315
|
-
this.useEndpointForAuthorization(resolve, reject)
|
|
316
|
-
},
|
|
317
|
-
async validateToken(
|
|
318
|
-
token: string,
|
|
319
|
-
location: UriLocation,
|
|
320
|
-
): Promise<string> {
|
|
321
|
-
const decoded = jwtDecode<JwtPayload>(token)
|
|
322
|
-
if (decoded.exp && decoded.exp < Date.now() / 1000) {
|
|
323
|
-
const refreshToken =
|
|
324
|
-
self.hasRefreshToken && self.retrieveRefreshToken()
|
|
325
|
-
if (refreshToken) {
|
|
326
|
-
try {
|
|
327
|
-
if (!refreshTokenPromise) {
|
|
328
|
-
refreshTokenPromise =
|
|
329
|
-
self.exchangeRefreshForAccessToken(refreshToken)
|
|
330
|
-
}
|
|
331
|
-
const newToken = await refreshTokenPromise
|
|
332
|
-
return this.validateToken(newToken, location)
|
|
333
|
-
} catch (err) {
|
|
334
|
-
throw new Error(`Token could not be refreshed. ${err}`)
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
} else {
|
|
338
|
-
refreshTokenPromise = undefined
|
|
339
|
-
}
|
|
340
|
-
return token
|
|
341
|
-
},
|
|
342
|
-
}
|
|
343
|
-
})
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
export default stateModelFactory
|
|
347
|
-
export type OAuthStateModel = ReturnType<typeof stateModelFactory>
|
|
348
|
-
export type OAuthModel = Instance<OAuthStateModel>
|
package/src/index.test.js
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import Plugin from '@jbrowse/core/Plugin'
|
|
2
|
-
import PluginManager from '@jbrowse/core/PluginManager'
|
|
3
|
-
import InternetAccountType from '@jbrowse/core/pluggableElementTypes/InternetAccountType'
|
|
4
|
-
import {
|
|
5
|
-
configSchema as OAuthConfigSchema,
|
|
6
|
-
modelFactory as OAuthInternetAccountModelFactory,
|
|
7
|
-
} from './OAuthModel'
|
|
8
|
-
import {
|
|
9
|
-
configSchema as ExternalTokenConfigSchema,
|
|
10
|
-
modelFactory as ExternalTokenInternetAccountModelFactory,
|
|
11
|
-
} from './ExternalTokenModel'
|
|
12
|
-
import {
|
|
13
|
-
configSchema as HTTPBasicConfigSchema,
|
|
14
|
-
modelFactory as HTTPBasicInternetAccountModelFactory,
|
|
15
|
-
} from './HTTPBasicModel'
|
|
16
|
-
import {
|
|
17
|
-
configSchema as DropboxOAuthConfigSchema,
|
|
18
|
-
modelFactory as DropboxOAuthInternetAccountModelFactory,
|
|
19
|
-
} from './DropboxOAuthModel'
|
|
20
|
-
import {
|
|
21
|
-
configSchema as GoogleDriveOAuthConfigSchema,
|
|
22
|
-
modelFactory as GoogleDriveOAuthInternetAccountModelFactory,
|
|
23
|
-
} from './GoogleDriveOAuthModel'
|
|
24
|
-
import { getSnapshot } from 'mobx-state-tree'
|
|
25
|
-
|
|
26
|
-
// mock warnings to avoid unnecessary outputs
|
|
27
|
-
beforeEach(() => {
|
|
28
|
-
jest.spyOn(console, 'warn').mockImplementation(() => {})
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
afterEach(() => {
|
|
32
|
-
console.warn.mockRestore()
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
class AuthenticationPlugin extends Plugin {
|
|
36
|
-
install(pluginManager) {
|
|
37
|
-
pluginManager.addInternetAccountType(() => {
|
|
38
|
-
return new InternetAccountType({
|
|
39
|
-
name: 'OAuthInternetAccount',
|
|
40
|
-
configSchema: OAuthConfigSchema,
|
|
41
|
-
stateModel: OAuthInternetAccountModelFactory(OAuthConfigSchema),
|
|
42
|
-
})
|
|
43
|
-
})
|
|
44
|
-
pluginManager.addInternetAccountType(() => {
|
|
45
|
-
return new InternetAccountType({
|
|
46
|
-
name: 'ExternalTokenInternetAccount',
|
|
47
|
-
configSchema: ExternalTokenConfigSchema,
|
|
48
|
-
stateModel: ExternalTokenInternetAccountModelFactory(
|
|
49
|
-
ExternalTokenConfigSchema,
|
|
50
|
-
),
|
|
51
|
-
})
|
|
52
|
-
})
|
|
53
|
-
pluginManager.addInternetAccountType(() => {
|
|
54
|
-
return new InternetAccountType({
|
|
55
|
-
name: 'HTTPBasicInternetAccount',
|
|
56
|
-
configSchema: HTTPBasicConfigSchema,
|
|
57
|
-
stateModel: HTTPBasicInternetAccountModelFactory(HTTPBasicConfigSchema),
|
|
58
|
-
})
|
|
59
|
-
})
|
|
60
|
-
pluginManager.addInternetAccountType(() => {
|
|
61
|
-
return new InternetAccountType({
|
|
62
|
-
name: 'DropboxOAuthInternetAccount',
|
|
63
|
-
configSchema: DropboxOAuthConfigSchema,
|
|
64
|
-
stateModel: DropboxOAuthInternetAccountModelFactory(
|
|
65
|
-
DropboxOAuthConfigSchema,
|
|
66
|
-
),
|
|
67
|
-
})
|
|
68
|
-
})
|
|
69
|
-
pluginManager.addInternetAccountType(() => {
|
|
70
|
-
return new InternetAccountType({
|
|
71
|
-
name: 'GoogleDriveOAuthInternetAccount',
|
|
72
|
-
configSchema: GoogleDriveOAuthConfigSchema,
|
|
73
|
-
stateModel: GoogleDriveOAuthInternetAccountModelFactory(
|
|
74
|
-
GoogleDriveOAuthConfigSchema,
|
|
75
|
-
),
|
|
76
|
-
})
|
|
77
|
-
})
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
test('initialized correctly', () => {
|
|
82
|
-
const pm = new PluginManager([
|
|
83
|
-
new AuthenticationPlugin(),
|
|
84
|
-
]).createPluggableElements()
|
|
85
|
-
|
|
86
|
-
expect(Object.values(pm.internetAccountTypes.registeredTypes).length).toEqual(
|
|
87
|
-
5,
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
const HTTPBasic = pm.getInternetAccountType('HTTPBasicInternetAccount')
|
|
91
|
-
const config = HTTPBasic.configSchema.create({
|
|
92
|
-
type: 'HTTPBasicInternetAccount',
|
|
93
|
-
internetAccountId: 'HTTPBasicTest',
|
|
94
|
-
})
|
|
95
|
-
expect(getSnapshot(config)).toMatchSnapshot()
|
|
96
|
-
})
|
package/src/index.ts
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import Plugin from '@jbrowse/core/Plugin'
|
|
2
|
-
import PluginManager from '@jbrowse/core/PluginManager'
|
|
3
|
-
import InternetAccountType from '@jbrowse/core/pluggableElementTypes/InternetAccountType'
|
|
4
|
-
import {
|
|
5
|
-
configSchema as OAuthConfigSchema,
|
|
6
|
-
modelFactory as OAuthInternetAccountModelFactory,
|
|
7
|
-
} from './OAuthModel'
|
|
8
|
-
import {
|
|
9
|
-
configSchema as ExternalTokenConfigSchema,
|
|
10
|
-
modelFactory as ExternalTokenInternetAccountModelFactory,
|
|
11
|
-
} from './ExternalTokenModel'
|
|
12
|
-
import {
|
|
13
|
-
configSchema as HTTPBasicConfigSchema,
|
|
14
|
-
modelFactory as HTTPBasicInternetAccountModelFactory,
|
|
15
|
-
} from './HTTPBasicModel'
|
|
16
|
-
import {
|
|
17
|
-
configSchema as DropboxOAuthConfigSchema,
|
|
18
|
-
modelFactory as DropboxOAuthInternetAccountModelFactory,
|
|
19
|
-
} from './DropboxOAuthModel'
|
|
20
|
-
import {
|
|
21
|
-
configSchema as GoogleDriveOAuthConfigSchema,
|
|
22
|
-
modelFactory as GoogleDriveOAuthInternetAccountModelFactory,
|
|
23
|
-
} from './GoogleDriveOAuthModel'
|
|
24
|
-
|
|
25
|
-
export default class AuthenticationPlugin extends Plugin {
|
|
26
|
-
name = 'AuthenticationPlugin'
|
|
27
|
-
|
|
28
|
-
exports = {
|
|
29
|
-
OAuthConfigSchema,
|
|
30
|
-
OAuthInternetAccountModelFactory,
|
|
31
|
-
ExternalTokenConfigSchema,
|
|
32
|
-
ExternalTokenInternetAccountModelFactory,
|
|
33
|
-
HTTPBasicConfigSchema,
|
|
34
|
-
HTTPBasicInternetAccountModelFactory,
|
|
35
|
-
DropboxOAuthConfigSchema,
|
|
36
|
-
DropboxOAuthInternetAccountModelFactory,
|
|
37
|
-
GoogleDriveOAuthConfigSchema,
|
|
38
|
-
GoogleDriveOAuthInternetAccountModelFactory,
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
install(pluginManager: PluginManager) {
|
|
42
|
-
pluginManager.addInternetAccountType(() => {
|
|
43
|
-
return new InternetAccountType({
|
|
44
|
-
name: 'OAuthInternetAccount',
|
|
45
|
-
configSchema: OAuthConfigSchema,
|
|
46
|
-
stateModel: OAuthInternetAccountModelFactory(OAuthConfigSchema),
|
|
47
|
-
})
|
|
48
|
-
})
|
|
49
|
-
pluginManager.addInternetAccountType(() => {
|
|
50
|
-
return new InternetAccountType({
|
|
51
|
-
name: 'ExternalTokenInternetAccount',
|
|
52
|
-
configSchema: ExternalTokenConfigSchema,
|
|
53
|
-
stateModel: ExternalTokenInternetAccountModelFactory(
|
|
54
|
-
ExternalTokenConfigSchema,
|
|
55
|
-
),
|
|
56
|
-
})
|
|
57
|
-
})
|
|
58
|
-
pluginManager.addInternetAccountType(() => {
|
|
59
|
-
return new InternetAccountType({
|
|
60
|
-
name: 'HTTPBasicInternetAccount',
|
|
61
|
-
configSchema: HTTPBasicConfigSchema,
|
|
62
|
-
stateModel: HTTPBasicInternetAccountModelFactory(HTTPBasicConfigSchema),
|
|
63
|
-
})
|
|
64
|
-
})
|
|
65
|
-
pluginManager.addInternetAccountType(() => {
|
|
66
|
-
return new InternetAccountType({
|
|
67
|
-
name: 'DropboxOAuthInternetAccount',
|
|
68
|
-
configSchema: DropboxOAuthConfigSchema,
|
|
69
|
-
stateModel: DropboxOAuthInternetAccountModelFactory(
|
|
70
|
-
DropboxOAuthConfigSchema,
|
|
71
|
-
),
|
|
72
|
-
})
|
|
73
|
-
})
|
|
74
|
-
pluginManager.addInternetAccountType(() => {
|
|
75
|
-
return new InternetAccountType({
|
|
76
|
-
name: 'GoogleDriveOAuthInternetAccount',
|
|
77
|
-
configSchema: GoogleDriveOAuthConfigSchema,
|
|
78
|
-
stateModel: GoogleDriveOAuthInternetAccountModelFactory(
|
|
79
|
-
GoogleDriveOAuthConfigSchema,
|
|
80
|
-
),
|
|
81
|
-
})
|
|
82
|
-
})
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export {
|
|
87
|
-
configSchema as OAuthConfigSchema,
|
|
88
|
-
modelFactory as OAuthInternetAccountModelFactory,
|
|
89
|
-
} from './OAuthModel'
|
|
90
|
-
export {
|
|
91
|
-
configSchema as ExternalTokenConfigSchema,
|
|
92
|
-
modelFactory as ExternalTokenInternetAccountModelFactory,
|
|
93
|
-
} from './ExternalTokenModel'
|
|
94
|
-
|
|
95
|
-
export {
|
|
96
|
-
configSchema as HTTPBasicConfigSchema,
|
|
97
|
-
modelFactory as HTTPBasicInternetAccountModelFactory,
|
|
98
|
-
} from './HTTPBasicModel'
|
|
99
|
-
|
|
100
|
-
export {
|
|
101
|
-
configSchema as DropboxOAuthConfigSchema,
|
|
102
|
-
modelFactory as DropboxOAuthInternetAccountModelFactory,
|
|
103
|
-
} from './DropboxOAuthModel'
|
|
104
|
-
|
|
105
|
-
export {
|
|
106
|
-
configSchema as GoogleDriveOAuthConfigSchema,
|
|
107
|
-
modelFactory as GoogleDriveOAuthInternetAccountModelFactory,
|
|
108
|
-
} from './GoogleDriveOAuthModel'
|