Skip to content

[Feature]: SDK cannot request a security key at enrollment #136

Description

@Bccorb

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/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
  • Covered by tests

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions