@@ -18,12 +18,11 @@ import fetch from "node-fetch";
1818import UriEventHandler from "./utils/UriEventHandler" ;
1919import {
2020 AuthSession ,
21- ExchangePromise ,
21+ WebCallback ,
2222 User ,
2323 Auth0LoginType ,
24- OnReturn ,
2524 ResponseAuth0 ,
26- UserInfoAuth0
25+ WebCallbackHandler
2726} from "./types" ;
2827import {
2928 fetchPlatformData ,
@@ -44,7 +43,7 @@ class AuthProvider implements AuthenticationProvider, Disposable {
4443 private eventEmitter = new EventEmitter < ChangeEvent > ( ) ;
4544 private currentInstance : Disposable ;
4645 private pendingIDs : string [ ] = [ ] ;
47- private promises = new Map < string , ExchangePromise > ( ) ;
46+ private callbackEvents = new Map < string , WebCallback > ( ) ;
4847 private uriHandler = new UriEventHandler ( ) ;
4948 private webviewView ! : WebviewView [ "webview" ] ;
5049
@@ -153,21 +152,11 @@ class AuthProvider implements AuthenticationProvider, Disposable {
153152 }
154153 }
155154
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-
166155 private async openBrowser ( type : Auth0LoginType , stateId : string ) {
167156 const searchParams = new URLSearchParams ( [
168157 [ "response_type" , type ] ,
169158 [ "client_id" , AUTH0_CLIENT_ID ] ,
170- [ "redirect_uri" , this . browserCallbackUri ] ,
159+ [ "redirect_uri" , this . webCallbackURI ] ,
171160 [ "state" , stateId ] ,
172161 [ "scope" , AUTH0_SCOPES ] ,
173162 [ "audience" , "platform" ] ,
@@ -186,45 +175,59 @@ class AuthProvider implements AuthenticationProvider, Disposable {
186175 title : "Signing in to Seqera Cloud" ,
187176 cancellable : true
188177 } ,
189- async ( _ , token ) => {
178+ async ( _ , cancellationToken ) => {
190179 // Add pending login ID to client
191180 const stateId = uuid ( ) ;
192181 this . pendingIDs . push ( stateId ) ;
193182
194183 await this . openBrowser ( type , stateId ) ;
195184
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 (
199191 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 )
201204 ) ;
202- this . promises . set ( AUTH0_SCOPES , codeExchangePromise ) ;
203- }
204205
205- try {
206206 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
217210 ] ) ;
218211 } finally {
219212 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 ) ;
222215 }
223216 }
224217 ) ;
225218 }
226219
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+ ) => {
228231 const queryString = uri . query || uri . fragment ;
229232 const query = new URLSearchParams ( queryString ) ;
230233 const accessToken = query . get ( "code" ) || query . get ( "access_token" ) ;
@@ -253,7 +256,7 @@ class AuthProvider implements AuthenticationProvider, Disposable {
253256 [ "client_id" , AUTH0_CLIENT_ID ] ,
254257 [ "client_secret" , AUTH0_CLIENT_SECRET ] ,
255258 [ "code" , code ] ,
256- [ "redirect_uri" , this . browserCallbackUri ]
259+ [ "redirect_uri" , this . webCallbackURI ]
257260 ] ) ;
258261 const auth = await fetch ( `https://${ AUTH0_DOMAIN } /oauth/token` , {
259262 method : `POST` ,
@@ -267,6 +270,10 @@ class AuthProvider implements AuthenticationProvider, Disposable {
267270 public setWebview ( webview : any ) {
268271 this . webviewView = webview ;
269272 }
273+
274+ public async dispose ( ) {
275+ this . currentInstance . dispose ( ) ;
276+ }
270277}
271278
272279export default AuthProvider ;
0 commit comments