@@ -18,12 +18,11 @@ import fetch from "node-fetch";
18
18
import UriEventHandler from "./utils/UriEventHandler" ;
19
19
import {
20
20
AuthSession ,
21
- ExchangePromise ,
21
+ WebCallback ,
22
22
User ,
23
23
Auth0LoginType ,
24
- OnReturn ,
25
24
ResponseAuth0 ,
26
- UserInfoAuth0
25
+ WebCallbackHandler
27
26
} from "./types" ;
28
27
import {
29
28
fetchPlatformData ,
@@ -44,7 +43,7 @@ class AuthProvider implements AuthenticationProvider, Disposable {
44
43
private eventEmitter = new EventEmitter < ChangeEvent > ( ) ;
45
44
private currentInstance : Disposable ;
46
45
private pendingIDs : string [ ] = [ ] ;
47
- private promises = new Map < string , ExchangePromise > ( ) ;
46
+ private callbackEvents = new Map < string , WebCallback > ( ) ;
48
47
private uriHandler = new UriEventHandler ( ) ;
49
48
private webviewView ! : WebviewView [ "webview" ] ;
50
49
@@ -153,21 +152,11 @@ class AuthProvider implements AuthenticationProvider, Disposable {
153
152
}
154
153
}
155
154
156
- public async dispose ( ) {
157
- this . currentInstance . dispose ( ) ;
158
- }
159
-
160
- get browserCallbackUri ( ) {
161
- const publisher = this . context . extension . packageJSON . publisher ;
162
- const name = this . context . extension . packageJSON . name ;
163
- return `vscode://${ publisher } .${ name } ` ;
164
- }
165
-
166
155
private async openBrowser ( type : Auth0LoginType , stateId : string ) {
167
156
const searchParams = new URLSearchParams ( [
168
157
[ "response_type" , type ] ,
169
158
[ "client_id" , AUTH0_CLIENT_ID ] ,
170
- [ "redirect_uri" , this . browserCallbackUri ] ,
159
+ [ "redirect_uri" , this . webCallbackURI ] ,
171
160
[ "state" , stateId ] ,
172
161
[ "scope" , AUTH0_SCOPES ] ,
173
162
[ "audience" , "platform" ] ,
@@ -186,45 +175,59 @@ class AuthProvider implements AuthenticationProvider, Disposable {
186
175
title : "Signing in to Seqera Cloud" ,
187
176
cancellable : true
188
177
} ,
189
- async ( _ , token ) => {
178
+ async ( _ , cancellationToken ) => {
190
179
// Add pending login ID to client
191
180
const stateId = uuid ( ) ;
192
181
this . pendingIDs . push ( stateId ) ;
193
182
194
183
await this . openBrowser ( type , stateId ) ;
195
184
196
- let codeExchangePromise = this . promises . get ( AUTH0_SCOPES ) ;
197
- if ( ! codeExchangePromise ) {
198
- codeExchangePromise = promiseFromEvent (
185
+ let callback : WebCallback | undefined ;
186
+
187
+ try {
188
+ const pendingCallback = this . callbackEvents . get ( AUTH0_SCOPES ) ;
189
+ callback = pendingCallback ;
190
+ callback ??= promiseFromEvent (
199
191
this . uriHandler . event ,
200
- this . onReturnFromWeb
192
+ this . webCallbackHandler
193
+ ) ;
194
+ this . callbackEvents . set ( AUTH0_SCOPES , callback ) ;
195
+
196
+ const userCancel = promiseFromEvent < any , any > (
197
+ cancellationToken . onCancellationRequested ,
198
+ ( _ , __ , reject ) => {
199
+ reject ( "User Cancelled" ) ;
200
+ }
201
+ ) ;
202
+ const timeoutPromise = new Promise < string > ( ( _ , reject ) =>
203
+ setTimeout ( ( ) => reject ( "Timed out" ) , 60000 )
201
204
) ;
202
- this . promises . set ( AUTH0_SCOPES , codeExchangePromise ) ;
203
- }
204
205
205
- try {
206
206
return await Promise . race ( [
207
- codeExchangePromise . promise ,
208
- new Promise < string > ( ( _ , reject ) =>
209
- setTimeout ( ( ) => reject ( "Cancelled" ) , 60000 )
210
- ) ,
211
- promiseFromEvent < any , any > (
212
- token . onCancellationRequested ,
213
- ( _ , __ , reject ) => {
214
- reject ( "User Cancelled" ) ;
215
- }
216
- ) . promise
207
+ callback . promise ,
208
+ userCancel . promise ,
209
+ timeoutPromise
217
210
] ) ;
218
211
} finally {
219
212
this . pendingIDs = this . pendingIDs . filter ( ( n ) => n !== stateId ) ;
220
- codeExchangePromise ?. cancel . fire ( ) ;
221
- this . promises . delete ( AUTH0_SCOPES ) ;
213
+ callback ?. cancel . fire ( ) ;
214
+ this . callbackEvents . delete ( AUTH0_SCOPES ) ;
222
215
}
223
216
}
224
217
) ;
225
218
}
226
219
227
- private onReturnFromWeb : OnReturn = async ( uri , resolve , reject ) => {
220
+ get webCallbackURI ( ) {
221
+ const publisher = this . context . extension . packageJSON . publisher ;
222
+ const name = this . context . extension . packageJSON . name ;
223
+ return `vscode://${ publisher } .${ name } ` ;
224
+ }
225
+
226
+ private webCallbackHandler : WebCallbackHandler = async (
227
+ uri ,
228
+ resolve ,
229
+ reject
230
+ ) => {
228
231
const queryString = uri . query || uri . fragment ;
229
232
const query = new URLSearchParams ( queryString ) ;
230
233
const accessToken = query . get ( "code" ) || query . get ( "access_token" ) ;
@@ -253,7 +256,7 @@ class AuthProvider implements AuthenticationProvider, Disposable {
253
256
[ "client_id" , AUTH0_CLIENT_ID ] ,
254
257
[ "client_secret" , AUTH0_CLIENT_SECRET ] ,
255
258
[ "code" , code ] ,
256
- [ "redirect_uri" , this . browserCallbackUri ]
259
+ [ "redirect_uri" , this . webCallbackURI ]
257
260
] ) ;
258
261
const auth = await fetch ( `https://${ AUTH0_DOMAIN } /oauth/token` , {
259
262
method : `POST` ,
@@ -267,6 +270,10 @@ class AuthProvider implements AuthenticationProvider, Disposable {
267
270
public setWebview ( webview : any ) {
268
271
this . webviewView = webview ;
269
272
}
273
+
274
+ public async dispose ( ) {
275
+ this . currentInstance . dispose ( ) ;
276
+ }
270
277
}
271
278
272
279
export default AuthProvider ;
0 commit comments