@@ -11,28 +11,29 @@ type Auth = ReturnType<typeof betterAuth>;
1111let _auth : Auth | undefined ;
1212
1313/**
14- * Runtime cache of OIDC endpoint origins discovered from IdP discovery documents.
14+ * Fetch an OIDC discovery document and inject every endpoint origin into
15+ * better-auth's live trusted-origins list so the SSO plugin trusts them
16+ * during provider registration.
1517 *
16- * Populated by `prefetchOidcEndpointOrigins()` before provider registration so
17- * that better-auth's trusted-origins check passes for IdPs whose token/userinfo
18- * endpoints live on a different domain than the issuer (e.g. Google).
19- */
20- const discoveredIdpOrigins = new Set < string > ( ) ;
21-
22- /**
23- * Fetch an OIDC discovery document and cache every endpoint origin so
24- * better-auth trusts them during provider registration.
18+ * Why: better-auth resolves `trustedOrigins` once at init and caches the
19+ * result as a plain array. The SSO plugin then validates every URL in the
20+ * discovery document (discovery endpoint, token_endpoint, jwks_uri, etc.)
21+ * against that cached array. IdPs like Google use multiple domains
22+ * (accounts.google.com vs oauth2.googleapis.com), so we must discover
23+ * those origins and inject them into the live array before registration.
2524 *
26- * Must be called **before** `auth.api.registerSSOProvider()` so the
27- * origins are available when better-auth validates discovery endpoints.
25+ * Must be called **before** `auth.api.registerSSOProvider()`.
2826 */
2927export async function prefetchOidcEndpointOrigins ( issuerUrl : string ) : Promise < void > {
3028 const discoveryUrl = issuerUrl . replace ( / \/ + $ / , "" ) + "/.well-known/openid-configuration" ;
3129 const res = await $fetch < Record < string , unknown > > ( discoveryUrl , {
3230 timeout : 10_000 ,
3331 } ) ;
3432
35- // Extract origins from all *_endpoint fields in the discovery document
33+ // Collect origins from all endpoint fields + the issuer itself
34+ const newOrigins = new Set < string > ( ) ;
35+ try { newOrigins . add ( new URL ( issuerUrl ) . origin ) ; } catch { }
36+
3637 const endpointKeys = [
3738 "authorization_endpoint" ,
3839 "token_endpoint" ,
@@ -45,11 +46,17 @@ export async function prefetchOidcEndpointOrigins(issuerUrl: string): Promise<vo
4546 for ( const key of endpointKeys ) {
4647 const value = res [ key ] ;
4748 if ( typeof value === "string" ) {
48- try {
49- discoveredIdpOrigins . add ( new URL ( value ) . origin ) ;
50- } catch {
51- // Skip malformed URLs
52- }
49+ try { newOrigins . add ( new URL ( value ) . origin ) ; } catch { }
50+ }
51+ }
52+
53+ // Push directly into better-auth's live trustedOrigins array so
54+ // isTrustedOrigin() sees them immediately (it reads this.trustedOrigins).
55+ const ctx = await ( auth as any ) . $context ;
56+ const existing = new Set ( ctx . trustedOrigins as string [ ] ) ;
57+ for ( const origin of newOrigins ) {
58+ if ( ! existing . has ( origin ) ) {
59+ ( ctx . trustedOrigins as string [ ] ) . push ( origin ) ;
5360 }
5461 }
5562}
@@ -59,11 +66,11 @@ export async function prefetchOidcEndpointOrigins(issuerUrl: string): Promise<vo
5966 *
6067 * Combines:
6168 * 1. App origins (base URL, configured origins, dev defaults)
62- * 2. Origins auto-discovered from OIDC discovery documents
63- * 3. Already-registered SSO provider issuers from the database
69+ * 2. Already-registered SSO provider issuers from the database
6470 *
65- * For IdPs that cannot be auto-discovered, add their origin to the
66- * BETTER_AUTH_TRUSTED_ORIGINS environment variable.
71+ * Additional IdP endpoint origins are injected at runtime by
72+ * `prefetchOidcEndpointOrigins()` directly into the auth context.
73+ * For edge cases, add origins to the BETTER_AUTH_TRUSTED_ORIGINS env var.
6774 */
6875function resolveTrustedOrigins ( baseUrl : string ) : ( request ?: Request ) => Promise < string [ ] > {
6976 const configuredOrigins = env . BETTER_AUTH_TRUSTED_ORIGINS ;
@@ -89,7 +96,7 @@ function resolveTrustedOrigins(baseUrl: string): (request?: Request) => Promise<
8996 ) ;
9097
9198 return async ( ) => {
92- const allOrigins = [ ...staticOrigins , ... discoveredIdpOrigins ] ;
99+ const allOrigins = [ ...staticOrigins ] ;
93100
94101 // Load already-registered SSO provider issuers from the database
95102 try {
0 commit comments