feat: add passkey login option to the login screen#54
Merged
Conversation
New AuthorizerPasskeyLogin component offers a full passwordless, usernameless "Sign in with a passkey" button (discoverable-credential login) above the existing login methods, wired via authorizer-js's loginWithPasskey() (authorizerdev/authorizer-js#40 / backend: authorizerdev/authorizer#671). Renders nothing when isWebauthnSupported() is false - there's no server config flag for passkeys (unlike social login), it's purely a browser capability check. Passkey management (list/add/delete existing passkeys) is out of scope here: this library only ever contained login-flow components, no account/settings page exists to extend, and the raw SDK methods (webauthnCredentials, webauthnDeleteCredential, registerPasskey) are already exported for a consuming app to build that itself. Live-verified in the example app against a real backend: the button renders, click fires webauthn_login_options over GraphQL and invokes the browser's native navigator.credentials.get() correctly (confirmed via the loading state and no console errors). Completing an actual ceremony needs real biometric hardware or a manually-configured Chrome DevTools virtual authenticator, neither of which is scriptable through browser automation - the ceremony logic itself is already proven correct by a Go integration test that simulates a real authenticator via github.com/descope/virtualwebauthn through the actual server code path.
The "OR" separator after the passkey button rendered unconditionally whenever WebAuthn was supported, regardless of whether basic auth, magic link, or any social login was actually enabled. If none were, the login view showed the passkey button followed by a dangling "OR" with nothing beneath it. Gated on the same conditions AuthorizerRoot uses to decide whether AuthorizerSocialLogin, AuthorizerBasicAuthLogin, or AuthorizerMagicLinkLogin render anything.
Contributor
Author
|
Fixed the dangling separator finding: the "OR" now only renders when another login method (social, basic auth, or magic link) is actually going to show below it, mirroring AuthorizerRoot's own visibility conditions. |
Contributor
Author
|
Blocked on an authorizer-js release. This calls |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
New
AuthorizerPasskeyLogincomponent offers a full passwordless, usernameless "Sign in with a passkey" button (discoverable-credential login) above the existing login methods, wired viaauthorizer-js'sloginWithPasskey().isWebauthnSupported()is false — purely a browser capability check, no server config flag (unlike social login)AuthorizerRooton the login view onlyScope decision
Passkey management (list/add/delete existing passkeys) is intentionally out of scope here — this library has only ever contained login-flow components, there's no account/settings page to extend, and the raw SDK methods (
webauthnCredentials,webauthnDeleteCredential,registerPasskey) are already exported for a consuming app (web/app, or any other) to build that itself.Dependency (blocking merge)
Depends on
authorizerdev/authorizer-js#40(isWebauthnSupported,loginWithPasskey), which itself depends onauthorizerdev/authorizer-js#39— neither published to npm yet.package.jsonhere is intentionally untouched, verified locally vianpm link.Test plan
tsc --noEmitclean, build clean (ESM/CJS)example/app against a real local backend (branchfeat/webauthn-passkey-backend,authorizerdev/authorizer#671): button renders correctly, click fireswebauthn_login_optionsand invokes the browser's nativenavigator.credentials.get()(confirmed via loading state, no console errors)authorizerdev/authorizer#671) that simulates a real authenticator viagithub.com/descope/virtualwebauthnthrough the actual server code path.