@@ -4,50 +4,60 @@ import { StackAssertionError } from "@stackframe/stack-shared/dist/utils/errors"
44import { mergeScopeStrings } from "@stackframe/stack-shared/dist/utils/strings" ;
55
66export abstract class OAuthBaseProvider {
7- issuer : Issuer ;
8- scope : string ;
9- oauthClient : Client ;
10- redirectUri : string ;
7+ constructor (
8+ public readonly oauthClient : Client ,
9+ public readonly scope : string ,
10+ public readonly redirectUri : string ,
11+ ) { }
1112
12- constructor ( options : {
13- issuer : string ,
14- authorizationEndpoint : string ,
15- tokenEndpoint : string ,
16- userinfoEndpoint ?: string ,
17- clientId : string ,
18- clientSecret : string ,
19- redirectUri : string ,
20- baseScope : string ,
21- } ) {
22- this . issuer = new Issuer ( {
13+ protected static async createConstructorArgs ( options :
14+ & {
15+ clientId : string ,
16+ clientSecret : string ,
17+ redirectUri : string ,
18+ baseScope : string ,
19+ isMock ?: boolean ,
20+ }
21+ & (
22+ | {
23+ issuer : string ,
24+ authorizationEndpoint : string ,
25+ tokenEndpoint : string ,
26+ userinfoEndpoint ?: string ,
27+ }
28+ | {
29+ discoverFromUrl : string ,
30+ }
31+ )
32+ ) {
33+ const issuer = "discoverFromUrl" in options ? await Issuer . discover ( options . discoverFromUrl ) : new Issuer ( {
2334 issuer : options . issuer ,
2435 authorization_endpoint : options . authorizationEndpoint ,
2536 token_endpoint : options . tokenEndpoint ,
2637 userinfo_endpoint : options . userinfoEndpoint ,
2738 } ) ;
28- this . oauthClient = new this . issuer . Client ( {
39+ const oauthClient = new issuer . Client ( {
2940 client_id : options . clientId ,
3041 client_secret : options . clientSecret ,
3142 redirect_uri : options . redirectUri ,
3243 response_types : [ "code" ] ,
3344 } ) ;
3445
3546 // facebook always return an id_token even in the OAuth2 flow, which is not supported by openid-client
36- const oldGrant = this . oauthClient . grant ;
47+ const oldGrant = oauthClient . grant ;
3748 if ( ! ( oldGrant as any ) ) {
3849 // it seems that on Sentry, this was undefined in one scenario, so let's log some data to help debug if it happens again
3950 // not sure if that is actually what was going on? the error log has very few details
4051 // https://stackframe-pw.sentry.io/issues/5515577938
41- throw new StackAssertionError ( "oldGrant is undefined for some reason — that should never happen!" , { options, oauthClient : this . oauthClient } ) ;
52+ throw new StackAssertionError ( "oldGrant is undefined for some reason — that should never happen!" , { options, oauthClient } ) ;
4253 }
43- this . oauthClient . grant = async function ( params ) {
54+ oauthClient . grant = async function ( params ) {
4455 const grant = await oldGrant . call ( this , params ) ;
4556 delete grant . id_token ;
4657 return grant ;
4758 } ;
4859
49- this . redirectUri = options . redirectUri ;
50- this . scope = options . baseScope ;
60+ return [ oauthClient , options . baseScope , options . redirectUri ] as const ;
5161 }
5262
5363 getAuthorizationUrl ( options : {
@@ -71,14 +81,14 @@ export abstract class OAuthBaseProvider {
7181 state : string ,
7282 } ) : Promise < OAuthUserInfo > {
7383 let tokenSet ;
84+ const params = {
85+ code_verifier : options . codeVerifier ,
86+ state : options . state ,
87+ } ;
7488 try {
75- const params = {
76- code_verifier : options . codeVerifier ,
77- state : options . state ,
78- } ;
7989 tokenSet = await this . oauthClient . oauthCallback ( this . redirectUri , options . callbackParams , params ) ;
8090 } catch ( error ) {
81- throw new StackAssertionError ( " OAuth callback failed" , undefined , { cause : error } ) ;
91+ throw new StackAssertionError ( `Inner OAuth callback failed due to error: ${ error } ` , undefined , { cause : error } ) ;
8292 }
8393 if ( ! tokenSet . access_token ) {
8494 throw new StackAssertionError ( "No access token received" , { tokenSet } ) ;
0 commit comments