feat(passkeys): Add passkeys support and related UI components - #830
aXenDeveloper merged 3 commits into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c10ffb0207
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| .select({ value: count() }) | ||
| .from(core_users_sso) | ||
| .where(eq(core_users_sso.userId, userId)), |
There was a problem hiding this comment.
Count only configured SSO providers before allowing deletion
When a passwordless account retains an SSO row for a provider that has since been removed or renamed in authorization.ssoAdapters, this count still treats that unusable link as a recovery method. The user can consequently delete their last passkey and permanently lock themselves out. Filter the linked accounts against the currently configured adapter IDs before allowing deletion.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 49c87e65c0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| }); | ||
|
|
||
| // eslint-disable-next-line @typescript-eslint/only-throw-error | ||
| if (!config.passkeys) throw notFound(); |
There was a problem hiding this comment.
Distinguish unavailable config from disabled passkeys
When the middleware-config request transiently fails, fetchMiddlewareConfig() returns UNKNOWN_MIDDLEWARE_CONFIG, where isKnown and passkeys are both false. This condition therefore turns an API outage into a 404 for /settings/security; because the loader also caches that fallback with staleTime: "static", subsequent navigations can continue reporting that the page does not exist after the API recovers. Check config.isKnown separately and surface/retry the configuration failure, only throwing notFound() when a successfully loaded configuration explicitly disables passkeys.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 07f84102a7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| hasPassword: | ||
| isPasswordSignInEnabled(this.c) && userWithEmail.password !== null, |
There was a problem hiding this comment.
Avoid routing SSO collisions to disabled password reset
When authorization.password is false but an email adapter exists, an SSO callback matching an existing account now reports hasPassword: false here. However, tanstack/auth/sso-screen.tsx still sets showResetPassword from config.isEmail alone, so SSOLinkFormContent displays a “set password” link to /login/reset-password; that route now returns 404 and both password-reset endpoints return 403. This leaves the collision flow directing users to an impossible recovery action, so the reset CTA also needs to account for the password capability or offer an appropriate alternative.
Useful? React with 👍 / 👎.
Improving Documentation
pnpm lint:fixto fix formatting issues before opening the PR.Description
What?
Why?