You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
GET /webauthn/register/start accepts ?attachment=platform or ?attachment=cross-platform, which narrows the browser picker to one kind of
authenticator. Nothing in this SDK can ask for it.
buildRegisterStartPath in src/client/createSeamlessAuthClient.ts
builds that query string from a PRF-shaped input and sets only requestPrf and requirePrf, so the parameter is unreachable without hand building the URL. RegisterPasskeyOptions has no field for it either.
The deployment default is authenticator_policy.attachment: 'any', which offers
both kinds, so this does not block enrolment. What is missing is the deliberate
path: an organisation handing someone an issued security key wants that person
taken straight to it, not left to recognise it in a browser dialog. The bundled
enrolment view calls authClient.registerPasskey(metadata) with no branch point
where a user could choose one.
Proposed solution
Add an optional attachment to RegisterPasskeyOptions and thread it into the
register/start query. Keep it unset by default so the picker still offers both
kinds and current behaviour is unchanged.
Type it as Exclude<AuthenticatorAttachmentPolicy, 'any'> against @seamless-auth/types rather than restating the two strings. any is a
deployment default, not something a single request can ask for, so the request
type is the policy type minus that member. The API publishes no request-side
union of its own (WebAuthnAuthenticatorAttachmentSchema lives in the API
repository, not in the types package), and deriving it keeps this from drifting
the way PasskeyPolicyErrorCode did before Passkey policy refusals surface as a raw error code to the end user #132.
Handle attachment_not_allowed. The API answers 400 from register/start when
a request names an attachment the deployment has pinned against, and this is
the change that makes that code reachable: it is unreachable today precisely
because the SDK never sends the parameter. It is deliberately outside getPasskeyPolicyErrorCode, which is scoped to the 403 policy refusals from
register/finish, so it needs its own handling rather than being folded in.
Offer a visible "use a security key instead" path in the bundled enrolment UI.
Alternatives considered
Callers can bypass registerPasskey and drive startRegistration against a
hand-built register/start URL. That means reimplementing the PRF handling, the
metadata plumbing and the error mapping the SDK already does, so it is not a
real workaround.
Widening getPasskeyPolicyErrorCode to the whole WebAuthnErrorCode union would
surface attachment_not_allowed without new code, but it would also report a 400 from register/start, and a prf_output_not_allowed from login, as
registration policy refusals. That was considered and rejected in #135.
Acceptance
A caller can drive a security-key enrolment through the SDK without hand
building the URL
The default enrolment path is unchanged, and omitting attachment sends no
query parameter
A refusal from a pinned deployment policy is distinguishable from a generic
registration failure
Client half of fells-code/seamless-auth-api#183, which shipped the API side and
records that the work lands in this repository.
Problem statement
GET /webauthn/register/startaccepts?attachment=platformor?attachment=cross-platform, which narrows the browser picker to one kind ofauthenticator. Nothing in this SDK can ask for it.
buildRegisterStartPathinsrc/client/createSeamlessAuthClient.tsbuilds that query string from a PRF-shaped input and sets only
requestPrfandrequirePrf, so the parameter is unreachable without hand building the URL.RegisterPasskeyOptionshas no field for it either.The deployment default is
authenticator_policy.attachment: 'any', which offersboth kinds, so this does not block enrolment. What is missing is the deliberate
path: an organisation handing someone an issued security key wants that person
taken straight to it, not left to recognise it in a browser dialog. The bundled
enrolment view calls
authClient.registerPasskey(metadata)with no branch pointwhere a user could choose one.
Proposed solution
attachmenttoRegisterPasskeyOptionsand thread it into theregister/start query. Keep it unset by default so the picker still offers both
kinds and current behaviour is unchanged.
Exclude<AuthenticatorAttachmentPolicy, 'any'>against@seamless-auth/typesrather than restating the two strings.anyis adeployment default, not something a single request can ask for, so the request
type is the policy type minus that member. The API publishes no request-side
union of its own (
WebAuthnAuthenticatorAttachmentSchemalives in the APIrepository, not in the types package), and deriving it keeps this from drifting
the way
PasskeyPolicyErrorCodedid before Passkey policy refusals surface as a raw error code to the end user #132.attachment_not_allowed. The API answers400from register/start whena request names an attachment the deployment has pinned against, and this is
the change that makes that code reachable: it is unreachable today precisely
because the SDK never sends the parameter. It is deliberately outside
getPasskeyPolicyErrorCode, which is scoped to the403policy refusals fromregister/finish, so it needs its own handling rather than being folded in.
Alternatives considered
Callers can bypass
registerPasskeyand drivestartRegistrationagainst ahand-built register/start URL. That means reimplementing the PRF handling, the
metadata plumbing and the error mapping the SDK already does, so it is not a
real workaround.
Widening
getPasskeyPolicyErrorCodeto the wholeWebAuthnErrorCodeunion wouldsurface
attachment_not_allowedwithout new code, but it would also report a400from register/start, and aprf_output_not_allowedfrom login, asregistration policy refusals. That was considered and rejected in #135.
Acceptance
building the URL
attachmentsends noquery parameter
registration failure