Skip to content

fix: support subdomains for passkey#42

Merged
sirily11 merged 1 commit into
mainfrom
credential
May 26, 2026
Merged

fix: support subdomains for passkey#42
sirily11 merged 1 commit into
mainfrom
credential

Conversation

@sirily11

Copy link
Copy Markdown
Contributor

No description provided.

Copilot AI review requested due to automatic review settings May 26, 2026 10:31
@vercel

vercel Bot commented May 26, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
rxlab-auth Ready Ready Preview, Comment May 26, 2026 10:31am

Request Review

Copilot AI left a comment

Copy link
Copy Markdown

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 updates WebAuthn/passkey verification to support native iOS/macOS flows that report the bare RP ID origin (e.g. https://rxlab.app) rather than the server subdomain (e.g. https://auth.rxlab.app), and tightens native passkey OAuth flows by binding challenges to a validated redirect_uri.

Changes:

  • Add computeExpectedOrigins() and switch passkey verify routes to accept an array of expected origins (configured origin + https://<rpId> where applicable).
  • Require redirect_uri for native passkey OAuth options requests; persist it in the Redis challenge and re-validate it during verify.
  • Add/adjust unit tests for expected origins and native passkey options/verify behavior.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
lib/webauthn/config.ts Adds computeExpectedOrigins() and exports expectedOrigins used by verification.
lib/webauthn/expected-origins.test.ts Unit tests for expected-origins computation/deduping.
app/api/auth/passkey/register/verify/route.ts Uses expectedOrigins for session-based registration verification.
app/api/auth/passkey/authenticate/verify/route.ts Uses expectedOrigins for session-based authentication verification.
app/api/admin/passkey/register/verify/route.ts Uses expectedOrigins for admin registration verification.
app/api/admin/passkey/authenticate/verify/route.ts Uses expectedOrigins for admin authentication verification.
lib/validations/oauth.ts Makes redirect_uri required for native passkey options requests.
lib/validations/oauth.test.ts Updates schema tests for required redirect_uri.
lib/redis/index.ts Extends WebAuthnChallengeData to include optional redirectUri.
lib/oauth/native-client.ts Adds validateClientRedirect() (client existence + redirect allow-list).
app/api/oauth/passkey/authenticate/options/route.ts Validates redirect_uri and stores it on the challenge.
app/api/oauth/passkey/authenticate/options/route.test.ts New tests covering redirect URI validation + persistence.
app/api/oauth/passkey/authenticate/verify/route.ts Re-validates stored redirectUri; uses expectedOrigins.
app/api/oauth/passkey/authenticate/verify/route.test.ts Updates tests for redirect URI re-validation + expected origins array.
app/api/oauth/passkey/register/options/route.ts Validates redirect_uri and stores it on the challenge.
app/api/oauth/passkey/register/options/route.test.ts New tests covering redirect URI validation + persistence.
app/api/oauth/passkey/register/verify/route.ts Re-validates stored redirectUri; uses expectedOrigins.
app/api/oauth/passkey/register/verify/route.test.ts Updates tests for redirect URI re-validation behavior.

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

Comment on lines +50 to +61
// Validate that a client exists and that the supplied redirect_uri is one
// the client has registered. Used by passkey native routes — instead of
// requiring `signInPermission === "all"`, we trust the client's registered
// redirect-URI allow-list (same gate authorization_code already uses, see
// app/api/oauth/authorize/route.ts:78-87).
//
// On unknown client: 401 invalid_client.
// On missing or unregistered redirect_uri: 400 invalid_request.
export async function validateClientRedirect(params: {
clientId: string;
redirectUri: string | undefined;
}): Promise<NativeClientCheck> {
Comment thread lib/webauthn/config.ts
Comment on lines +10 to +24
// Origins SimpleWebAuthn's verify functions will accept.
//
// Always includes the configured web origin (e.g. https://auth.rxlab.app).
// Also includes https://<rpID> (e.g. https://rxlab.app) when the rpID is a
// real registrable domain — native iOS/macOS apps using an Associated Domain
// of webcredentials:<rpID> set the WebAuthn origin in clientDataJSON to that
// bare-rpId URL, not the server's subdomain. Dedupes; skips for localhost.
export function computeExpectedOrigins(
configuredOrigin: string,
rpId: string,
): string[] {
const set = new Set<string>([configuredOrigin]);
if (rpId && rpId !== "localhost" && rpId.includes(".")) {
set.add(`https://${rpId}`);
}
Comment thread lib/validations/oauth.ts
Comment on lines 104 to 125
@@ -118,6 +119,7 @@ export const passkeyAuthVerifyRequestSchema = z.object({
// POST /api/oauth/passkey/register/options
export const passkeyRegisterOptionsRequestSchema = z.object({
client_id: z.string().min(1, "client_id is required"),
redirect_uri: z.string().min(1, "redirect_uri is required"),
username: z.string().email("username must be a valid email address"),
name: z.string().min(1).max(64).optional(),
});
@sirily11 sirily11 merged commit 904135f into main May 26, 2026
4 checks passed
@sirily11 sirily11 deleted the credential branch May 26, 2026 10:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants