Skip to content

fix: key name resolution for client creation#9

Merged
tomaspozo merged 5 commits intomainfrom
fix/context-client-key-resolution
Mar 23, 2026
Merged

fix: key name resolution for client creation#9
tomaspozo merged 5 commits intomainfrom
fix/context-client-key-resolution

Conversation

@tomaspozo
Copy link
Copy Markdown
Member

@tomaspozo tomaspozo commented Mar 20, 2026

Summary

  • verifyCredentials now returns the matched keyName in AuthResult, so downstream code knows which named key was used for auth
  • createContextClient and createAdminClient use the matched key name instead of always defaulting to 'default' — with fallback to first available key when no 'default' exists
  • README samples updated to export default { fetch } format, removed repetitive imports, and documented bare array JWKS format

…lting

verifyCredentials now returns the matched keyName in AuthResult.
createContextClient and createAdminClient accept an optional keyName
parameter, falling back to 'default' when not provided.
…e key

Client creation now falls back to first available key when no 'default'
exists and keyName is null. Tests cover named keys, wildcard matching
non-first keys, and the full fallback chain.
Copilot AI review requested due to automatic review settings March 20, 2026 21:01
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves multi-key support by carrying the matched key name through authentication and using it during Supabase client creation, rather than always assuming "default".

Changes:

  • Extend AuthResult to include keyName, and have verifyCredentials populate it (including wildcard matches).
  • Update createSupabaseContext to pass the matched keyName into createContextClient / createAdminClient.
  • Enhance client creation helpers to support named keys and add fallback behavior when "default" is absent; update README examples and document bare-array JWKS parsing.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/types.ts Adds keyName to AuthResult to propagate matched key identity.
src/create-supabase-context.ts Uses auth.keyName to select named keys when creating clients.
src/core/verify-credentials.ts Returns the matched key name for public/secret modes (incl. wildcard).
src/core/verify-credentials.test.ts Adds assertions ensuring keyName is returned correctly across modes.
src/core/create-context-client.ts Adds keyName parameter and named-key resolution + fallback.
src/core/create-context-client.test.ts Adds coverage for named key selection and fallback/empty-key behavior.
src/core/create-admin-client.ts Adds keyName parameter and named-key resolution + fallback.
src/core/create-admin-client.test.ts Adds coverage for named key selection and fallback/empty-key behavior.
README.md Updates Deno examples to export default { fetch } and documents JWKS bare array format.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/core/create-context-client.ts Outdated
Comment thread src/core/create-context-client.ts Outdated
Comment thread src/core/create-admin-client.ts Outdated
const secretKey = resolved.secretKeys['default']
const name = keyName ?? 'default'
const keys = resolved.secretKeys
const secretKey = keys[name] ?? (keyName ? undefined : Object.values(keys)[0])
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as createContextClient: fallback logic uses a truthiness check on keyName (keyName ? undefined : Object.values(keys)[0]). Passing keyName='' will incorrectly allow fallback-to-first-key. Prefer checking keyName == null (or explicitly rejecting empty strings) so explicit-but-empty values don’t change behavior unexpectedly.

Suggested change
const secretKey = keys[name] ?? (keyName ? undefined : Object.values(keys)[0])
const secretKey = keys[name] ?? (keyName == null ? Object.values(keys)[0] : undefined)

Copilot uses AI. Check for mistakes.
Comment thread src/core/create-admin-client.ts Outdated
Use keyName == null instead of truthiness check so empty strings
don't incorrectly trigger fallback. Error messages now only suggest
SUPABASE_*_KEY for the default key, not for named keys.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/create-supabase-context.ts Outdated
const supabase = createContextClient(auth.token, options?.env)
const supabaseAdmin = createAdminClient(options?.env)
const supabase = createContextClient(auth.token, options?.env, auth.keyName)
const supabaseAdmin = createAdminClient(options?.env, auth.keyName)
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

createSupabaseContext passes auth.keyName to createAdminClient for all auth types. For public:* / public:<name>, auth.keyName is derived from publishableKeys, but createAdminClient looks up secretKeys[name] and will throw if secret keys aren’t named identically. This can turn a successful public auth into a 500. Consider only passing keyName to createAdminClient when auth.authType === 'secret' (or implement a fallback to default/first secret key when the named secret key is missing).

Suggested change
const supabaseAdmin = createAdminClient(options?.env, auth.keyName)
const adminKeyName = auth.authType === 'secret' ? auth.keyName : undefined
const supabaseAdmin = createAdminClient(options?.env, adminKeyName)

Copilot uses AI. Check for mistakes.
Comment thread src/types.ts Outdated
token: string | null
userClaims: UserClaims | null
claims: JWTClaims | null
keyName: string | null
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AuthResult is an exported type, and adding a new required field (keyName) is a TypeScript breaking change for consumers who construct/annotate AuthResult values. If you want this to be non-breaking, consider making it optional (keyName?: string | null) while still returning it from verifyCredentials, or ensure this change is released as a breaking/major bump.

Suggested change
keyName: string | null
keyName?: string | null

Copilot uses AI. Check for mistakes.
…optional

Admin client now only receives keyName when authType is 'secret',
preventing mismatched key lookups when auth is public. AuthResult.keyName
is now optional to avoid breaking consumers who construct the type.
Copy link
Copy Markdown
Member

@kallebysantos kallebysantos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!!
Just noticing that some docs was changed outside main PR context...

Comment thread README.md
@tomaspozo tomaspozo merged commit e17bd4e into main Mar 23, 2026
5 of 6 checks passed
@tomaspozo tomaspozo deleted the fix/context-client-key-resolution branch March 23, 2026 15:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants