From e14d7e76afade841c6952db9fd2b10654a97002c Mon Sep 17 00:00:00 2001 From: Muzzaiyyan Hussain Date: Wed, 12 Nov 2025 12:57:36 +0530 Subject: [PATCH 1/2] fix(auth): skip validateExp when allowExpired=true --- packages/core/auth-js/src/GoTrueClient.ts | 162 +++++++++++----------- 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/packages/core/auth-js/src/GoTrueClient.ts b/packages/core/auth-js/src/GoTrueClient.ts index f23bc954e..bbeaa31ad 100644 --- a/packages/core/auth-js/src/GoTrueClient.ts +++ b/packages/core/auth-js/src/GoTrueClient.ts @@ -742,9 +742,9 @@ export default class GoTrueClient { */ async signInWithWeb3(credentials: Web3Credentials): Promise< | { - data: { session: Session; user: User } - error: null - } + data: { session: Session; user: User } + error: null + } | { data: { session: null; user: null }; error: AuthError } > { const { chain } = credentials @@ -1021,9 +1021,9 @@ export default class GoTrueClient { : []), ...(options?.signInWithSolana?.resources?.length ? [ - 'Resources', - ...options.signInWithSolana.resources.map((resource) => `- ${resource}`), - ] + 'Resources', + ...options.signInWithSolana.resources.map((resource) => `- ${resource}`), + ] : []), ].join('\n') @@ -1084,9 +1084,9 @@ export default class GoTrueClient { private async _exchangeCodeForSession(authCode: string): Promise< | { - data: { session: Session; user: User; redirectType: string | null } - error: null - } + data: { session: Session; user: User; redirectType: string | null } + error: null + } | { data: { session: null; user: null; redirectType: null }; error: AuthError } > { const storageItem = await getItemAsync(this.storage, `${this.storageKey}-code-verifier`) @@ -1533,23 +1533,23 @@ export default class GoTrueClient { fn: ( result: | { - data: { - session: Session - } - error: null + data: { + session: Session } + error: null + } | { - data: { - session: null - } - error: AuthError + data: { + session: null } + error: AuthError + } | { - data: { - session: null - } - error: null + data: { + session: null } + error: null + } ) => Promise ): Promise { this._debug('#_useSession', 'begin') @@ -1571,23 +1571,23 @@ export default class GoTrueClient { */ private async __loadSession(): Promise< | { - data: { - session: Session - } - error: null + data: { + session: Session } + error: null + } | { - data: { - session: null - } - error: AuthError + data: { + session: null } + error: AuthError + } | { - data: { - session: null - } - error: null + data: { + session: null } + error: null + } > { this._debug('#__loadSession()', 'begin') @@ -1943,9 +1943,9 @@ export default class GoTrueClient { callbackUrlType: string ): Promise< | { - data: { session: Session; redirectType: string | null } - error: null - } + data: { session: Session; redirectType: string | null } + error: null + } | { data: { session: null; redirectType: null }; error: AuthError } > { try { @@ -2181,13 +2181,13 @@ export default class GoTrueClient { this._debug('#onAuthStateChange()', 'registered callback with id', id) this.stateChangeEmitters.set(id, subscription) - ;(async () => { - await this.initializePromise + ; (async () => { + await this.initializePromise - await this._acquireLock(-1, async () => { - this._emitInitialSession(id) - }) - })() + await this._acquireLock(-1, async () => { + this._emitInitialSession(id) + }) + })() return { data: { subscription } } } @@ -2226,9 +2226,9 @@ export default class GoTrueClient { } = {} ): Promise< | { - data: {} - error: null - } + data: {} + error: null + } | { data: null; error: AuthError } > { let codeChallenge: string | null = null @@ -2266,11 +2266,11 @@ export default class GoTrueClient { */ async getUserIdentities(): Promise< | { - data: { - identities: UserIdentity[] - } - error: null + data: { + identities: UserIdentity[] } + error: null + } | { data: null; error: AuthError } > { try { @@ -2395,9 +2395,9 @@ export default class GoTrueClient { */ async unlinkIdentity(identity: UserIdentity): Promise< | { - data: {} - error: null - } + data: {} + error: null + } | { data: null; error: AuthError } > { try { @@ -3155,14 +3155,14 @@ export default class GoTrueClient { | Exclude /** Exclude out the webauthn params from here because we're going to need to serialize them in the response */ | Prettify< - StrictOmit & { - webauthn: Prettify< - StrictOmit & { - credential_response: PublicKeyCredentialJSON - } - > - } - >, + StrictOmit & { + webauthn: Prettify< + StrictOmit & { + credential_response: PublicKeyCredentialJSON + } + > + } + >, /* Exclude challengeId because the backend expects snake_case, and exclude factorId since it's passed in the path params */ 'challengeId' | 'factorId' > & { @@ -3171,18 +3171,18 @@ export default class GoTrueClient { challenge_id: params.challengeId, ...('webauthn' in params ? { - webauthn: { - ...params.webauthn, - credential_response: - params.webauthn.type === 'create' - ? serializeCredentialCreationResponse( - params.webauthn.credential_response as RegistrationCredential - ) - : serializeCredentialRequestResponse( - params.webauthn.credential_response as AuthenticationCredential - ), - }, - } + webauthn: { + ...params.webauthn, + credential_response: + params.webauthn.type === 'create' + ? serializeCredentialCreationResponse( + params.webauthn.credential_response as RegistrationCredential + ) + : serializeCredentialRequestResponse( + params.webauthn.credential_response as AuthenticationCredential + ), + }, + } : { code: params.code }), } @@ -3353,7 +3353,7 @@ export default class GoTrueClient { for (const factor of user?.factors ?? []) { data.all.push(factor) if (factor.status === 'verified') { - ;(data[factor.factor_type] as (typeof factor)[]).push(factor) + ; (data[factor.factor_type] as (typeof factor)[]).push(factor) } } @@ -3626,9 +3626,9 @@ export default class GoTrueClient { } = {} ): Promise< | { - data: { claims: JwtPayload; header: JwtHeader; signature: Uint8Array } - error: null - } + data: { claims: JwtPayload; header: JwtHeader; signature: Uint8Array } + error: null + } | { data: null; error: AuthError } | { data: null; error: null } > { @@ -3649,16 +3649,16 @@ export default class GoTrueClient { raw: { header: rawHeader, payload: rawPayload }, } = decodeJWT(token) - if (!options?.allowExpired) { - // Reject expired JWTs should only happen if jwt argument was passed + // Only validate expiration if allowExpired is NOT true + if (options?.allowExpired !== true) { validateExp(payload.exp) } const signingKey = !header.alg || - header.alg.startsWith('HS') || - !header.kid || - !('crypto' in globalThis && 'subtle' in globalThis.crypto) + header.alg.startsWith('HS') || + !header.kid || + !('crypto' in globalThis && 'subtle' in globalThis.crypto) ? null : await this.fetchJwk(header.kid, options?.keys ? { keys: options.keys } : options?.jwks) From 12b1094545a55bc1cd7cfcd41cbc3e7cc5f62084 Mon Sep 17 00:00:00 2001 From: Muzzaiyyan Hussain Date: Wed, 12 Nov 2025 12:59:57 +0530 Subject: [PATCH 2/2] fix(auth): skip validateExp when allowExpired=true --- packages/core/auth-js/src/GoTrueClient.ts | 158 +++++++++++----------- 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/packages/core/auth-js/src/GoTrueClient.ts b/packages/core/auth-js/src/GoTrueClient.ts index bbeaa31ad..f86ad5a00 100644 --- a/packages/core/auth-js/src/GoTrueClient.ts +++ b/packages/core/auth-js/src/GoTrueClient.ts @@ -742,9 +742,9 @@ export default class GoTrueClient { */ async signInWithWeb3(credentials: Web3Credentials): Promise< | { - data: { session: Session; user: User } - error: null - } + data: { session: Session; user: User } + error: null + } | { data: { session: null; user: null }; error: AuthError } > { const { chain } = credentials @@ -1021,9 +1021,9 @@ export default class GoTrueClient { : []), ...(options?.signInWithSolana?.resources?.length ? [ - 'Resources', - ...options.signInWithSolana.resources.map((resource) => `- ${resource}`), - ] + 'Resources', + ...options.signInWithSolana.resources.map((resource) => `- ${resource}`), + ] : []), ].join('\n') @@ -1084,9 +1084,9 @@ export default class GoTrueClient { private async _exchangeCodeForSession(authCode: string): Promise< | { - data: { session: Session; user: User; redirectType: string | null } - error: null - } + data: { session: Session; user: User; redirectType: string | null } + error: null + } | { data: { session: null; user: null; redirectType: null }; error: AuthError } > { const storageItem = await getItemAsync(this.storage, `${this.storageKey}-code-verifier`) @@ -1533,23 +1533,23 @@ export default class GoTrueClient { fn: ( result: | { - data: { - session: Session + data: { + session: Session + } + error: null } - error: null - } | { - data: { - session: null + data: { + session: null + } + error: AuthError } - error: AuthError - } | { - data: { - session: null + data: { + session: null + } + error: null } - error: null - } ) => Promise ): Promise { this._debug('#_useSession', 'begin') @@ -1571,23 +1571,23 @@ export default class GoTrueClient { */ private async __loadSession(): Promise< | { - data: { - session: Session + data: { + session: Session + } + error: null } - error: null - } | { - data: { - session: null + data: { + session: null + } + error: AuthError } - error: AuthError - } | { - data: { - session: null + data: { + session: null + } + error: null } - error: null - } > { this._debug('#__loadSession()', 'begin') @@ -1943,9 +1943,9 @@ export default class GoTrueClient { callbackUrlType: string ): Promise< | { - data: { session: Session; redirectType: string | null } - error: null - } + data: { session: Session; redirectType: string | null } + error: null + } | { data: { session: null; redirectType: null }; error: AuthError } > { try { @@ -2181,13 +2181,13 @@ export default class GoTrueClient { this._debug('#onAuthStateChange()', 'registered callback with id', id) this.stateChangeEmitters.set(id, subscription) - ; (async () => { - await this.initializePromise + ;(async () => { + await this.initializePromise - await this._acquireLock(-1, async () => { - this._emitInitialSession(id) - }) - })() + await this._acquireLock(-1, async () => { + this._emitInitialSession(id) + }) + })() return { data: { subscription } } } @@ -2226,9 +2226,9 @@ export default class GoTrueClient { } = {} ): Promise< | { - data: {} - error: null - } + data: {} + error: null + } | { data: null; error: AuthError } > { let codeChallenge: string | null = null @@ -2266,11 +2266,11 @@ export default class GoTrueClient { */ async getUserIdentities(): Promise< | { - data: { - identities: UserIdentity[] + data: { + identities: UserIdentity[] + } + error: null } - error: null - } | { data: null; error: AuthError } > { try { @@ -2395,9 +2395,9 @@ export default class GoTrueClient { */ async unlinkIdentity(identity: UserIdentity): Promise< | { - data: {} - error: null - } + data: {} + error: null + } | { data: null; error: AuthError } > { try { @@ -3155,14 +3155,14 @@ export default class GoTrueClient { | Exclude /** Exclude out the webauthn params from here because we're going to need to serialize them in the response */ | Prettify< - StrictOmit & { - webauthn: Prettify< - StrictOmit & { - credential_response: PublicKeyCredentialJSON - } - > - } - >, + StrictOmit & { + webauthn: Prettify< + StrictOmit & { + credential_response: PublicKeyCredentialJSON + } + > + } + >, /* Exclude challengeId because the backend expects snake_case, and exclude factorId since it's passed in the path params */ 'challengeId' | 'factorId' > & { @@ -3171,18 +3171,18 @@ export default class GoTrueClient { challenge_id: params.challengeId, ...('webauthn' in params ? { - webauthn: { - ...params.webauthn, - credential_response: - params.webauthn.type === 'create' - ? serializeCredentialCreationResponse( - params.webauthn.credential_response as RegistrationCredential - ) - : serializeCredentialRequestResponse( - params.webauthn.credential_response as AuthenticationCredential - ), - }, - } + webauthn: { + ...params.webauthn, + credential_response: + params.webauthn.type === 'create' + ? serializeCredentialCreationResponse( + params.webauthn.credential_response as RegistrationCredential + ) + : serializeCredentialRequestResponse( + params.webauthn.credential_response as AuthenticationCredential + ), + }, + } : { code: params.code }), } @@ -3353,7 +3353,7 @@ export default class GoTrueClient { for (const factor of user?.factors ?? []) { data.all.push(factor) if (factor.status === 'verified') { - ; (data[factor.factor_type] as (typeof factor)[]).push(factor) + ;(data[factor.factor_type] as (typeof factor)[]).push(factor) } } @@ -3626,9 +3626,9 @@ export default class GoTrueClient { } = {} ): Promise< | { - data: { claims: JwtPayload; header: JwtHeader; signature: Uint8Array } - error: null - } + data: { claims: JwtPayload; header: JwtHeader; signature: Uint8Array } + error: null + } | { data: null; error: AuthError } | { data: null; error: null } > { @@ -3656,9 +3656,9 @@ export default class GoTrueClient { const signingKey = !header.alg || - header.alg.startsWith('HS') || - !header.kid || - !('crypto' in globalThis && 'subtle' in globalThis.crypto) + header.alg.startsWith('HS') || + !header.kid || + !('crypto' in globalThis && 'subtle' in globalThis.crypto) ? null : await this.fetchJwk(header.kid, options?.keys ? { keys: options.keys } : options?.jwks)