44} from "#src/credentials_provider/index.js" ;
55import type { OAuth2Credentials } from "#src/credentials_provider/oauth2.js" ;
66import { StatusMessage } from "#src/status.js" ;
7- import { uncancelableToken } from "#src/util/cancellation.js" ;
87import { HttpError } from "#src/util/http_request.js" ;
98import {
109 generateCodeChallenge ,
@@ -17,17 +16,13 @@ const GLOBUS_AUTH_HOST = "https://auth.globus.org";
1716const REDIRECT_URI = new URL ( "./globus_oauth2_redirect.html" , import . meta. url )
1817 . href ;
1918
20- function getRequiredScopes ( endpoint : string ) {
21- return `https://auth.globus.org/scopes/${ endpoint } /https` ;
22- }
23-
2419function getGlobusAuthorizeURL ( {
25- endpoint ,
20+ scope ,
2621 clientId,
2722 code_challenge,
2823 state,
2924} : {
30- endpoint : string ;
25+ scope : string [ ] ;
3126 clientId : string ;
3227 code_challenge : string ;
3328 state : string ;
@@ -39,7 +34,7 @@ function getGlobusAuthorizeURL({
3934 url . searchParams . set ( "code_challenge" , code_challenge ) ;
4035 url . searchParams . set ( "code_challenge_method" , "S256" ) ;
4136 url . searchParams . set ( "state" , state ) ;
42- url . searchParams . set ( "scope" , getRequiredScopes ( endpoint ) ) ;
37+ url . searchParams . set ( "scope" , scope . join ( " " ) ) ;
4338 return url . toString ( ) ;
4439}
4540
@@ -84,7 +79,7 @@ function getStorage() {
8479
8580async function waitForAuth (
8681 clientId : string ,
87- gcsHttpsHost : string ,
82+ globusConnectServerDomain : string ,
8883) : Promise < OAuth2Credentials > {
8984 const status = new StatusMessage ( /*delay=*/ false , /*modal=*/ true ) ;
9085
@@ -97,44 +92,35 @@ async function waitForAuth(
9792
9893 frag . appendChild ( title ) ;
9994
100- let identifier = getStorage ( ) . domainMappings ?. [ gcsHttpsHost ] ;
101-
10295 const link = document . createElement ( "button" ) ;
10396 link . textContent = "Log in to Globus" ;
104- link . disabled = true ;
105-
106- if ( ! identifier ) {
107- const label = document . createElement ( "label" ) ;
108- label . textContent = "Globus Collection UUID" ;
109- label . style . display = "block" ;
110- label . style . margin = ".5em 0" ;
111- frag . appendChild ( label ) ;
112- const endpoint = document . createElement ( "input" ) ;
113- endpoint . style . width = "100%" ;
114- endpoint . style . margin = ".5em 0" ;
115- endpoint . type = "text" ;
116- endpoint . placeholder = "a17d7fac-ce06-4ede-8318-ad8dc98edd69" ;
117- endpoint . addEventListener ( "input" , async ( e ) => {
118- identifier = ( e . target as HTMLInputElement ) . value ;
119- link . disabled = ! identifier ;
120- } ) ;
121- frag . appendChild ( endpoint ) ;
122- } else {
123- link . disabled = false ;
124- }
12597
12698 link . addEventListener ( "click" , async ( event ) => {
12799 event . preventDefault ( ) ;
128- if ( ! identifier ) {
129- status . setText ( "You must provide a Globus Collection UUID." ) ;
130- return ;
131- }
100+ /**
101+ * We make a request to the Globus Connect Server domain **even though we _know_ we're
102+ * unauthorized** to get the required consents for the resource.
103+ */
104+ console . log ( globusConnectServerDomain ) ;
105+ const authorizationIntrospectionRequest = await fetch (
106+ globusConnectServerDomain ,
107+ {
108+ method : "GET" ,
109+ headers : {
110+ "X-Requested-With" : "XMLHttpRequest" ,
111+ } ,
112+ } ,
113+ ) ;
114+
115+ const { authorization_parameters } =
116+ await authorizationIntrospectionRequest . json ( ) ;
117+
132118 const verifier = generateCodeVerifier ( ) ;
133119 const state = getRandomHexString ( ) ;
134120 const challenge = await generateCodeChallenge ( verifier ) ;
135121 const url = getGlobusAuthorizeURL ( {
136122 clientId,
137- endpoint : identifier ,
123+ scope : authorization_parameters . required_scopes ,
138124 code_challenge : challenge ,
139125 state,
140126 } ) ;
@@ -154,7 +140,6 @@ async function waitForAuth(
154140 const token = await waitForPKCEResponseMessage ( {
155141 source,
156142 state,
157- cancellationToken : uncancelableToken ,
158143 tokenExchangeCallback : async ( code ) => {
159144 const response = await fetch (
160145 getGlobusTokenURL ( { clientId, code, code_verifier : verifier } ) ,
@@ -195,7 +180,7 @@ async function waitForAuth(
195180 } ;
196181 storage . domainMappings = {
197182 ...storage . domainMappings ,
198- [ gcsHttpsHost ] : rawToken . resource_server ,
183+ [ globusConnectServerDomain ] : rawToken . resource_server ,
199184 } ;
200185
201186 localStorage . setItem ( "globus" , JSON . stringify ( storage ) ) ;
@@ -215,30 +200,35 @@ async function waitForAuth(
215200export class GlobusCredentialsProvider extends CredentialsProvider < OAuth2Credentials > {
216201 constructor (
217202 public clientId : string ,
218- public gcsHttpsHost : string ,
203+ public assetUrl : URL ,
219204 ) {
220205 super ( ) ;
221206 }
222207 get = makeCredentialsGetter ( async ( ) => {
223- const resourceServer = getStorage ( ) . domainMappings ?. [ this . gcsHttpsHost ] ;
208+ const globusConnectServerDomain = this . assetUrl . origin ;
209+
210+ const resourceServer =
211+ getStorage ( ) . domainMappings ?. [ globusConnectServerDomain ] ;
224212 const token = resourceServer
225213 ? getStorage ( ) . authorizations ?. [ resourceServer ]
226214 : undefined ;
215+
227216 if ( ! token ) {
228- return await waitForAuth ( this . clientId , this . gcsHttpsHost ) ;
217+ return await waitForAuth ( this . clientId , globusConnectServerDomain ) ;
229218 }
230- const response = await fetch ( ` ${ this . gcsHttpsHost } ` , {
219+ const response = await fetch ( this . assetUrl , {
231220 method : "HEAD" ,
232221 headers : {
233222 "X-Requested-With" : "XMLHttpRequest" ,
234223 Authorization : `${ token ?. tokenType } ${ token ?. accessToken } ` ,
235224 } ,
236225 } ) ;
226+
237227 switch ( response . status ) {
238228 case 200 :
239229 return token ;
240230 case 401 :
241- return await waitForAuth ( this . clientId , this . gcsHttpsHost ) ;
231+ return await waitForAuth ( this . clientId , globusConnectServerDomain ) ;
242232 default :
243233 throw HttpError . fromResponse ( response ) ;
244234 }
0 commit comments