Help us shape the future of Go! Take the 2026 Go Developer Survey

webauthn

package module
v0.0.0-...-4801d79 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 24, 2026 License: MIT Imports: 27 Imported by: 0

README

go-webauthn

Selected identified-user and discoverable none/ES256 or opt-in Ed25519 profiles; whole-unit qualification and release remain incomplete.

The root module owns WebAuthn protocol verification. The independent postgres module owns real durable ceremony and credential storage through the existing identity coordinator. Neither owns identity enrollment authorization, sessions, passkey workflows, browser UI or HTTP routes.

The candidate defaults to ES256, with explicit Ed25519 selection, none attestation, exact tenant/ RP/origin binding, mandatory UP/UV, 32-byte opaque user handles, five-minute single-use challenges, typed credProps/credProtect, backup flags and counter policy. Unsupported variants fail closed. Source identity, precise bounds and authority distinctions are in protocol sources.

The documentation map links the retained complete goal and the selected implementation's security boundaries.

Public flow

  1. An existing trusted identity workflow authorizes enrollment/use and selects tenant before looking up RP configuration. CeremonyContext is correlation, not authentication or authorization proof.
  2. Construct the concrete native store with the primary pool and public coordinator policy, then construct webauthn.New with that store, fixed tenant/RP/version/origins, explicit timeout and an opaque NewChallengeDigestKey value. The service copies mutable configuration.
  3. BeginRegistration commits a digest-only ceremony before returning browser options. TransferJSON reveals the challenge once to a synchronous delivery callback outside SQL. A retry returns original safe ceremony metadata but cannot re-reveal its challenge.
  4. VerifyRegistration accepts bounded browser JSON, verifies the selected protocol, then atomically consumes the ceremony and inserts one credential. Only successful finalization produces an opaque VerifiedRegistration.
  5. BeginAssertion selects the identified subject and nonempty credential allowlist. VerifyAssertion verifies exact client-data bytes and signature, then atomically consumes the ceremony and updates counter/backup/version before returning an opaque VerifiedAssertion.
Explicit Ed25519 selection

Config.Algorithms is an ordered allowlist: for example, []webauthn.Algorithm{webauthn.ES256, webauthn.EdDSA} enables both, while []webauthn.Algorithm{webauthn.EdDSA} selects only Ed25519. EdDSA means the exact COSE alg=-8, kty=1, crv=6, 32-byte public-key profile; Ed448, X25519, RSA, private-key members and other algorithm/key combinations deny. The service copies the list, advertises exactly that order in creation options, and binds the frozen selection into every registration/assertion ceremony. Nil retains the existing ES256-only profile and original serialized rows and challenge digests; an explicit empty, duplicate or unsupported list is invalid. Changing the policy rejects old in-flight ceremonies instead of widening them; also advance RelyingParty.Version when changing configuration.

Existing credential records and migrations are unchanged. Assertions dispatch from the stored COSE key and matching algorithm, never by signature inference. Ed25519 verifies the exact authenticator-data/client-hash message with Go's standard crypto implementation; there is no pre-hashed mode or algorithm fallback. Identified and discoverable paths retain the same current-subject, one-use, counter/backup, rollback and historical-recovery contracts. Independent Ed25519 crypto fixtures are exercised, but actual Ed25519 browser/authenticator interoperability remains unverified; retained Chromium evidence is ES256-only.

Discoverable credentials

For existing active users, set BeginRegistrationRequest.ResidentKeyRequired to request resident-required creation with UV. The default remains the existing nonresident-discouraged profile. none attestation and unsigned credProps cannot prove physical residency or device provenance.

Construct NewDiscoverable with a DiscoverableStore. Native support requires an adapter revision implementing this seam and forward migration 2; older adapter revisions remain identified-only and are rejected by NewDiscoverable. BeginDiscoverableAssertion takes a trusted CeremonyContext with empty UserID and a bounded AnonymousFlowID, never a browser-selected account. It emits no credential allowlist or user handle. Retain that original pre-auth flow, tenant, actor and ceremony for VerifyDiscoverableAssertion; supply a new completion command ID. The signed response must contain a matching 32-byte handle. Resolution binds RP, credential ID and RP-wide handle mapping to one tenant/user; the final transaction checks that user is currently active and atomically consumes the original ceremony and updates counter/backup/version. The returned VerifiedAssertion.Credential() identifies the resolved subject; its Context() retains the anonymous command, not a fabricated authenticated user.

Use BeginDiscoverableAssertionOperation or DiscoverableAssertionOperation for exact original-command recovery. Neither replay nor recovery issues fresh verification. The option contract tests preserve resident selection, UV and usernameless option shape. The optional store must finalize this protocol path durably before any verified result can be issued. Signup, session issuance, credential management and conditional UI are excluded.

Every operation uses its own random identity.NewCommandID. Preserve that ID and complete original input across retries. An unknown acknowledgement returns no challenge or verified evidence; Recover uses that original command and scope. A committed replay returns typed Replay, not renewed authentication. Recovery reports only historical outcome and cannot recreate challenge bytes.

The concrete public-path walkthrough is the PostgreSQL consumer test. It is not evidence of signup, sessions, HTTP integration or complete browser conformance.

Native enrollment participation

The PostgreSQL adapter additionally offers invocation-local RegistrationCreation and RegistrationFinalization for the closed native passkey enrollment profile. These reuse the real root-produced opaque inputs and protocol SQL within the parent's existing coordinator Work; they never open an independent domain transaction. The composition contract specifies original input binding, creation custody, final checks and historical recovery.

The participant does not supply the parent's fresh authentication, factor/risk admission, identity credential insertion, metadata store, or passkey workflow. Protocol-participant integration tests therefore do not establish a complete passkey consumer. Existing standalone ceremony APIs retain their behavior.

Ownership and operations

The caller owns pool lifetime, migration execution, bounded authorization policy, the challenge-digest key and any explicit copies made during delivery. The library owns no background goroutine or global user authority. Never log or snapshot challenge-bearing browser options, raw responses, handles or credentials. Challenge.Discard invalidates every unrevealed alias; ordinary diagnostics cannot inspect its closure-backed custody, including enclosing wrappers.

Install the public identity kernel, audit and outbox histories, then postgres.MigrationSource through the existing migration owner. Discoverable support requires forward migration 2 before new binaries run; identified rows remain compatible and old binaries cannot select anonymous rows. The native adapter never opens a private domain transaction. Current active-subject, expiry and optimistic checks remain under the sole coordinator transaction, including its final check after audit/lifecycle persistence. A reserved command that is denied or rolled back can retain its separate original no-change failure audit; it cannot retain a partial success mutation or lifecycle effect.

Current exclusions include shared RP tenancy, RSA, trusted attestation/metadata, credential management, key rotation, passkeys, sessions and reference/HTTP composition. They remain requirements of the complete retained goals, not silently removed obligations.

Verification and release

Consumer fixtures cover the selected real-PostgreSQL ceremony, failure, concurrency and recovery paths, including actual Chromium output checked by pinned WPT helpers and WebCrypto. This is not the full WPT suite. The candidate has independent final source review for its retained identified profile. The native adapter's selected public protocol-library pin passes real PostgreSQL/race and actual Chrome/WPT consumer checks. The native adapter is available through public module revision v0.0.0-20261019012703-3ad12d242248; its downloaded source matches the reviewed implementation. The focused account-authority consumer additionally proves that suspension after challenge issuance denies otherwise-valid registration and assertion without consuming either ceremony or changing credential/success effects. This is the selected M15 ceremony profile, not passkey/session support. Whole-unit qualification additionally retains the full original goal's coverage, mutation, security, compatibility, lifecycle and release obligations. A local test or source pin is not a release, whole-unit conformance or production claim.

Use the checksum-verified public golib release declared in .golib.yaml, with Go 1.27.2 as the verification producer. Both modules retain Go 1.27.0 as their minimum. The historical repository goal is not a runtime or release qualification claim. An ordinary standalone checkout is sufficient, without sibling repositories, goal ledgers or building Tools from source:

make check
make ci

Both routes, and the make fast-check alias, check configuration, repository structure, cohesion, offline specification decisions, local documentation links and unconditional whole-tree secrets. They run no application tests, mutation campaigns or release checks. Hosted Required applies the same structural checks and scans committed changed content against the exact validated PR base or push before commit, without a fallback base or a duplicate full-history scan. Missing or invalid change identities and failed checks remain failures.

make check-full optionally preserves the previous full manifest-selected contract, including broad spelling and external-link documentation assurance. It is not an ordinary CI prerequisite and does not establish runtime or release qualification for the experimental implementation.

make check-online explicitly adds authoritative specification refresh to the local contract. Scheduled and manual CI also refresh those authorities online and run whole-tree secrets. Passing any of these planning routes is not runtime security or release qualification.

See the versioned Golib ecosystem index and package-family guidance for the shared design language.

License

MIT. See LICENSE, SECURITY.md and the versioned threat model. The embedded unmodified PSL retains its MPL 2.0 notice.

Documentation

Overview

Package webauthn implements a bounded WebAuthn Level 3 none-attestation, ES256 or explicitly selected Ed25519 protocol profile. It does not authorize identity enrollment or issue sessions. Trusted workflows authorize context first.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Algorithm

type Algorithm int32

Algorithm identifies one supported COSE signature algorithm and exact key profile. Other COSE values, including other EdDSA curves, are unsupported.

const (
	// ES256 selects ECDSA P-256 with SHA-256 (COSE alg=-7, kty=2, crv=1).
	ES256 Algorithm = -7
	// EdDSA selects only Ed25519 (COSE alg=-8, kty=1, crv=6), not Ed448.
	EdDSA Algorithm = -8
)

type AssertionMutation

type AssertionMutation struct {
	Context        CeremonyContext
	Ceremony       CeremonyRecord
	Before         Credential
	After          Credential
	ResponseDigest [32]byte
	CounterRisk    bool
}

AssertionMutation fixes the exact verified before/after credential state. CounterRisk is bounded risk evidence for backup-eligible counter regressions; it is not an automatic clone verdict. Counter never decreases.

func (AssertionMutation) Format

func (AssertionMutation) Format(s fmt.State, _ rune)

type AssertionOptions

type AssertionOptions struct {
	// contains filtered or unexported fields
}

AssertionOptions contains identified-assertion browser options after commit.

func (AssertionOptions) Ceremony

func (o AssertionOptions) Ceremony() (CeremonyRecord, bool)

Ceremony returns safe original assertion metadata, never authentication.

func (AssertionOptions) Format

func (AssertionOptions) Format(s fmt.State, _ rune)

func (AssertionOptions) TransferJSON

func (o AssertionOptions) TransferJSON(ctx context.Context, deliver func(context.Context, []byte) error) error

TransferJSON delivers bounded browser assertion options exactly once.

type AssertionTransition

type AssertionTransition struct {
	// contains filtered or unexported fields
}

AssertionTransition is immutable verified-signature input to atomic storage. Store must compare the original versions, not rebase a stale assertion.

func (AssertionTransition) Format

func (AssertionTransition) Format(s fmt.State, _ rune)

func (AssertionTransition) Mutation

Mutation returns the original verified optimistic transition, never a rebase.

type BeginAssertionRequest

type BeginAssertionRequest struct {
	Context            CeremonyContext
	UserHandle         []byte
	Origin             string
	AllowedCredentials [][]byte
}

BeginAssertionRequest selects an existing identified subject and a nonempty allowlist of at most 100 credentials. Use DiscoverableService for usernameless.

type BeginDiscoverableAssertionRequest

type BeginDiscoverableAssertionRequest struct {
	Context CeremonyContext
	Origin  string
}

BeginDiscoverableAssertionRequest requires an empty Context.UserID and a trusted bounded Context.AnonymousFlowID. No user handle or allowlist is known.

type BeginRegistrationRequest

type BeginRegistrationRequest struct {
	Context             CeremonyContext
	UserHandle          []byte
	Origin              string
	ExcludedCredentials [][]byte
	ResidentKeyRequired bool
}

BeginRegistrationRequest fixes the opaque 32-byte RP-wide user handle and exact allowed origin. The trusted caller owns prior identity authorization. ResidentKeyRequired opts into resident-required browser creation; false keeps the existing discouraged profile. Neither none attestation nor credProps proves physical residency or authenticator provenance.

type CeremonyContext

type CeremonyContext struct {
	CommandID identity.CommandID
	TenantID  identity.TenantID
	UserID    identity.UserID
	// AnonymousFlowID selects a trusted pre-authentication transaction only for
	// discoverable assertions. It is mutually exclusive with UserID.
	AnonymousFlowID string `json:",omitempty"`
	ActorID         identity.ActorID
	CorrelationID   string
}

CeremonyContext comes from an already authorized trusted workflow, never Host, forwarded headers or a browser body. It is not proof of identity or a session. Use a fresh identity.NewCommandID for each operation and retain it on retries.

func (CeremonyContext) Format

func (CeremonyContext) Format(s fmt.State, _ rune)

type CeremonyCreation

type CeremonyCreation struct {
	// contains filtered or unexported fields
}

CeremonyCreation is issued only by Service. Its immutable intent can be read by a durable adapter; Generate runs only after acknowledged command ownership, outside SQL. Generated challenge is an output, not a caller-supplied input. Raw challenge custody must never enter retained preparation or journal data.

func (CeremonyCreation) Format

func (CeremonyCreation) Format(s fmt.State, _ rune)

func (CeremonyCreation) Generate

Generate creates original challenge output with crypto/rand outside SQL. Adapters call this only after acknowledged command reservation. now is a primary-authority clock sample. The digest binds complete ceremony scope.

func (CeremonyCreation) Intent

func (c CeremonyCreation) Intent() (CeremonyIntent, error)

Intent returns an owned copy of every original caller-controlled input.

type CeremonyIntent

type CeremonyIntent struct {
	Context            CeremonyContext
	Kind               string
	RPID               string
	RPVersion          uint64
	Origin             string
	UserHandle         []byte
	AllowedCredentials [][]byte
	Extensions         ExtensionRequestSet
	// ResidentKeyRequired selects resident-required creation, never a claim
	// that an unsigned browser extension proves authenticator residency.
	ResidentKeyRequired bool `json:",omitempty"`
	// Algorithms freezes the exact explicit profile. Absent means legacy ES256,
	// never the current service's expanded policy. Omission preserves old rows.
	Algorithms []Algorithm `json:",omitempty"`
}

CeremonyIntent is the complete safe generated-state request. Challenge bytes are deliberately absent. Consumers must not log opaque handles or user data. Policy fields are frozen by the service, not recovered from browser input.

func (CeremonyIntent) Format

func (CeremonyIntent) Format(s fmt.State, _ rune)

type CeremonyRecord

type CeremonyRecord struct {
	Intent          CeremonyIntent
	ID              string
	ChallengeDigest [32]byte
	ExpiresAt       time.Time
	Version         uint64
}

CeremonyRecord contains only a scoped keyed challenge digest at rest. Versions start at 1. Store queries bind tenant/RP/ceremony and subject or pre-auth flow.

func (CeremonyRecord) Format

func (CeremonyRecord) Format(s fmt.State, _ rune)

type Challenge

type Challenge struct {
	// contains filtered or unexported fields
}

Challenge is opaque reveal-once custody. Only Transfer exposes bytes to a synchronous browser-delivery callback outside database work. Copies share lifetime; diagnostics and serialization never expose bytes. Zero is invalid.

func (Challenge) Discard

func (c Challenge) Discard()

Discard invalidates every alias and clears unrevealed bytes, including on unknown commit paths. It performs no IO and is safe beside Transfer.

func (Challenge) Format

func (Challenge) Format(s fmt.State, _ rune)

func (Challenge) MarshalJSON

func (Challenge) MarshalJSON() ([]byte, error)

func (Challenge) Transfer

func (c Challenge) Transfer(ctx context.Context, deliver func(context.Context, []byte) error) (err error)

Transfer invalidates every challenge alias before calling deliver. Borrowed bytes are cleared afterward, including errors and panics. Delivery failure does not undo a committed ceremony and never permits re-reveal on retry.

type ChallengeDigestKey

type ChallengeDigestKey struct {
	// contains filtered or unexported fields
}

ChallengeDigestKey is immutable opaque deployment-key custody. Its closure representation also protects keys inside unexported enclosing fmt wrappers. The caller retains responsibility for its original input copy. Zero is invalid.

func NewChallengeDigestKey

func NewChallengeDigestKey(input []byte) (ChallengeDigestKey, error)

NewChallengeDigestKey copies a nonzero exact 32-byte key without IO.

func (ChallengeDigestKey) Format

func (ChallengeDigestKey) Format(s fmt.State, _ rune)

func (ChallengeDigestKey) MarshalJSON

func (ChallengeDigestKey) MarshalJSON() ([]byte, error)

type Config

type Config struct {
	TenantID     identity.TenantID
	RelyingParty RelyingParty
	Extensions   ExtensionRequestSet
	// Algorithms is an ordered, copied allowlist used for both ceremonies.
	// Nil preserves the legacy ES256-only profile and stored ceremony bytes.
	// An explicit list must be nonempty, unique and limited to ES256/EdDSA.
	// Changing it invalidates in-flight ceremonies; also advance RP.Version.
	Algorithms               []Algorithm
	ChallengeKey             ChallengeDigestKey
	DevelopmentLocalhostHTTP bool
	MaximumDuration          time.Duration
}

Config selects one trusted tenant and one RP. This finite profile always requires UP and UV, none attestation, and a five-minute 32-byte challenge. ChallengeKey is a nonzero deployment-owned HMAC key; keep it stable while ceremonies exist. The service copies it and never serializes it.

func (Config) Format

func (Config) Format(s fmt.State, _ rune)

func (Config) MarshalJSON

func (Config) MarshalJSON() ([]byte, error)

type Conflict

type Conflict struct{}

Conflict identifies optimistic, idempotency or RP-wide uniqueness conflicts.

func (Conflict) Error

func (Conflict) Error() string

type Credential

type Credential struct {
	TenantID       identity.TenantID
	UserID         identity.UserID
	RPID           string
	ID             []byte
	UserHandle     []byte
	PublicKey      []byte
	Algorithm      int32
	AAGUID         [16]byte
	Counter        uint32
	BackupEligible bool
	BackupState    bool
	Extensions     ExtensionOutputSet
	Version        uint64
}

Credential is public verification metadata, never authentication evidence. Byte slices are owned snapshots. Version is positive and monotonically grows. Credential IDs/user-handle mappings are unique across the whole RP, not tenant.

func (Credential) Format

func (Credential) Format(s fmt.State, _ rune)

type CredentialPropertiesOutput

type CredentialPropertiesOutput struct {
	ResidentKey bool
	Authority   ExtensionAuthority
}

CredentialPropertiesOutput is an untrusted browser claim, never signed authenticator authority and never sufficient to authorize a policy decision.

type CredentialProtectionOutput

type CredentialProtectionOutput struct {
	Policy    uint8
	Authority ExtensionAuthority
}

CredentialProtectionOutput records creation authenticator data. Registration with none attestation provides no device provenance. Assertions preserve this metadata, never promoting unsolicited output into fresh enrollment authority.

type Denied

type Denied struct{}

Denied intentionally does not distinguish missing, expired or wrong-scope state.

func (Denied) Error

func (Denied) Error() string

type Dependencies

type Dependencies struct{ Store Store }

Dependencies are borrowed, concurrent-safe dependencies; the service never closes them. Store must be a durable participant, not an application map.

type DiscoverableService

type DiscoverableService interface {
	Service
	BeginDiscoverableAssertion(context.Context, BeginDiscoverableAssertionRequest) (AssertionOptions, error)
	VerifyDiscoverableAssertion(context.Context, VerifyDiscoverableAssertionRequest) (VerifiedAssertion, error)
}

DiscoverableService adds resident-required registration/usernameless assertion without changing the identified Service or Store contracts. Results remain protocol facts, not identity enrollment grants, sessions or authorization.

func NewDiscoverable

func NewDiscoverable(c Config, d Dependencies) (DiscoverableService, error)

NewDiscoverable selects usernameless assertions only with the explicit durable resolution contract. It otherwise has the same bounded configuration as New.

type DiscoverableStore

type DiscoverableStore interface {
	Store
	LoadDiscoverableCredential(context.Context, Lookup, []byte, []byte) (Credential, error)
}

DiscoverableStore is the optional durable resolution seam. Lookup must carry an anonymous context and the original ceremony. Resolve exactly RP, credential ID and mandatory handle, scope tenant without disambiguating RP uniqueness, and preserve original pre-transition state for exact retries. FinalizeAssertion must check the resolved active subject inside its atomic commit, consume the anonymous ceremony and CAS-update that same credential and handle mapping.

type ExtensionAuthority

type ExtensionAuthority uint8

ExtensionAuthority prevents retained browser/none-attestation claims from being promoted to fresh signed authenticator evidence by downstream callers.

const (
	// BrowserReported is unsigned client-extension output, never authorization.
	BrowserReported ExtensionAuthority = iota + 1
	// UnattestedAuthenticator is structurally accepted registration authData
	// under none attestation, without authenticator provenance/signature trust.
	UnattestedAuthenticator
)

type ExtensionOutputSet

type ExtensionOutputSet struct {
	CredentialProperties *CredentialPropertiesOutput
	CredentialProtection *CredentialProtectionOutput
}

ExtensionOutputSet retains only explicitly requested typed outputs. Unknown and unselected extensions are discarded without persistence or advertisement.

type ExtensionRequestSet

type ExtensionRequestSet struct {
	CredentialProperties        bool
	CredentialProtection        uint8
	EnforceCredentialProtection bool
}

ExtensionRequestSet selects creation-only credProps and credProtect. Zero requests neither. CredentialProtection is 0 (absent) or FIDO values 1, 2 or 3. Assertions retain this frozen policy but emit no creation-only inputs.

type Invalid

type Invalid struct{ Field string }

Invalid is a redacted structural/configuration error. Field is a static name.

func (Invalid) Error

func (Invalid) Error() string

type Lookup

type Lookup struct {
	Context    CeremonyContext
	RPID       string
	CeremonyID string
}

Lookup carries exact trusted tenant/RP/ceremony and subject or pre-auth flow.

func (Lookup) Format

func (Lookup) Format(s fmt.State, _ rune)

type Operation

type Operation uint8

Operation is the closed recoverable native operation. Zero is invalid.

const (
	// BeginRegistrationOperation recovers original challenge creation metadata.
	BeginRegistrationOperation Operation = iota + 1
	// BeginAssertionOperation recovers original assertion creation metadata.
	BeginAssertionOperation
	// RegistrationOperation recovers original credential creation.
	RegistrationOperation
	// AssertionOperation recovers original counter/backup update.
	AssertionOperation
	// BeginDiscoverableAssertionOperation recovers anonymous ceremony creation.
	BeginDiscoverableAssertionOperation
	// DiscoverableAssertionOperation recovers anonymous credential finalization.
	DiscoverableAssertionOperation
)

type RecoveryRequest

type RecoveryRequest struct {
	Context      CeremonyContext
	Operation    Operation
	CredentialID []byte
}

RecoveryRequest retains exact original command scope, including anonymous flow for discoverable operations. CredentialID is required only for completion. Recovery returns safe historical outcome, never a challenge, Verified result or renewed authentication proof.

func (RecoveryRequest) Format

func (RecoveryRequest) Format(s fmt.State, _ rune)

type RegistrationMutation

type RegistrationMutation struct {
	Context        CeremonyContext
	Ceremony       CeremonyRecord
	Credential     Credential
	ResponseDigest [32]byte
}

RegistrationMutation is a copied native-adapter projection, not authority to construct a RegistrationTransition or bypass the public verifier.

func (RegistrationMutation) Format

func (RegistrationMutation) Format(s fmt.State, _ rune)

type RegistrationOptions

type RegistrationOptions struct {
	// contains filtered or unexported fields
}

RegistrationOptions contains JSON browser options plus opaque challenge custody. TransferJSON emits a fresh challenge only once after durable creation.

func (RegistrationOptions) Ceremony

func (o RegistrationOptions) Ceremony() (CeremonyRecord, bool)

Ceremony returns safe original metadata, including for a committed retry whose reveal-once challenge is unavailable. It does not expose challenge data.

func (RegistrationOptions) Format

func (RegistrationOptions) Format(s fmt.State, _ rune)

func (RegistrationOptions) TransferJSON

func (o RegistrationOptions) TransferJSON(ctx context.Context, deliver func(context.Context, []byte) error) error

TransferJSON delivers bounded browser creation options exactly once. The callback owns any explicit copy and must not log its challenge-bearing input.

type RegistrationTransition

type RegistrationTransition struct {
	// contains filtered or unexported fields
}

RegistrationTransition is immutable protocol-verifier output. Only Service can create it. It is provisional and not an authenticated result; native adapters consume the ceremony and create Credential in one coordinated commit.

func (RegistrationTransition) Format

func (RegistrationTransition) Format(s fmt.State, _ rune)

func (RegistrationTransition) Mutation

Mutation returns an owned provisional native projection. Zero transitions cannot be reconstructed from public fields; only the verifier issues them.

type RelyingParty

type RelyingParty struct {
	ID      string
	Name    string
	Origins []string
	Version uint64
}

RelyingParty is fixed before processing browser input. Version changes when any RP/origin/extension policy changes; old ceremonies cannot be reinterpreted. TenantID is selected before RP lookup. Shared-RP mappings are not yet selected.

type Replay

type Replay struct{ CommandID identity.CommandID }

Replay reports historical commitment without issuing fresh verification or challenge custody. Recover returns the original safe command outcome.

func (Replay) Error

func (Replay) Error() string

type Service

Service owns the selected complete protocol path, never session or passkey UX.

func New

func New(c Config, d Dependencies) (Service, error)

New validates and snapshots explicit configuration without IO or callbacks. No protocol capability is available without a nonnil durable Store. The caller owns store lifetime, identity authorization and tenant-to-RP selection.

type Store

Store is the storage-neutral complete ceremony/credential participant seam. No method exposes a concrete coordinator, transaction, or identity.UnitOfWork. Create may call Generate only after reservation is acknowledged and outside SQL. It reveals challenge custody only for acknowledged first commit; retries return original safe record and zero challenge. Finalize methods atomically consume the exact ceremony/version and insert or update credential, together with mandatory audit/lifecycle and the original command receipt. Unknown outcomes return no credential, no challenge and no verified result. All methods must support concurrent bounded calls and preserve tenant scope.

type Unavailable

type Unavailable struct{}

Unavailable is a redacted dependency failure, never evidence of rollback.

func (Unavailable) Error

func (Unavailable) Error() string

type UnknownCommit

type UnknownCommit struct{ CommandID identity.CommandID }

UnknownCommit requires recovery of this exact original command, not a new ID.

func (UnknownCommit) Error

func (UnknownCommit) Error() string

type VerificationContext

type VerificationContext struct {
	Command      CeremonyContext
	CeremonyID   string
	Operation    Operation
	RPID         string
	RPVersion    uint64
	Origin       string
	ExpiresAt    time.Time
	UserPresent  bool
	UserVerified bool
}

VerificationContext preserves the exact original finalized ceremony and completion command. ExpiresAt is the original absolute ceremony ceiling, never a new validity lease. These are historical protocol facts; consumers still require their owning identity/current-authority and factor policy.

func (VerificationContext) Format

func (VerificationContext) Format(s fmt.State, _ rune)

type VerifiedAssertion

type VerifiedAssertion struct {
	// contains filtered or unexported fields
}

VerifiedAssertion can only be issued after signature checks and durable challenge consumption/counter/backup update. Copies cannot renew authority.

func (VerifiedAssertion) Context

Context returns original immutable ceremony/command facts, not fresh authority.

func (VerifiedAssertion) CounterRisk

func (v VerifiedAssertion) CounterRisk() bool

CounterRisk reports a selected backup-credential counter warning only after successful finalization. False also represents an invalid zero result.

func (VerifiedAssertion) Credential

func (v VerifiedAssertion) Credential() (Credential, bool)

Credential returns owned finalized metadata and false for the invalid zero.

func (VerifiedAssertion) Format

func (VerifiedAssertion) Format(s fmt.State, _ rune)

type VerifiedRegistration

type VerifiedRegistration struct {
	// contains filtered or unexported fields
}

VerifiedRegistration can only be issued after successful durable finalization. It is WebAuthn protocol evidence, not a principal, session or enrollment grant.

func (VerifiedRegistration) Context

Context returns original immutable ceremony/command facts, not fresh authority.

func (VerifiedRegistration) Credential

func (v VerifiedRegistration) Credential() (Credential, bool)

Credential returns owned finalized metadata and false for the invalid zero.

func (VerifiedRegistration) Format

func (VerifiedRegistration) Format(s fmt.State, _ rune)

type VerifyAssertionRequest

type VerifyAssertionRequest struct {
	Context                   CeremonyContext
	CeremonyID                string
	Origin                    string
	Response                  []byte
	ExpectedVersion           uint64
	ExpectedCredentialVersion uint64
}

VerifyAssertionRequest additionally pins the observed credential version.

type VerifyDiscoverableAssertionRequest

type VerifyDiscoverableAssertionRequest struct {
	Context         CeremonyContext
	CeremonyID      string
	Origin          string
	Response        []byte
	ExpectedVersion uint64
}

VerifyDiscoverableAssertionRequest retains the exact original pre-auth flow. Credential version is read from primary storage and atomically compared; the browser cannot choose a subject, handle mapping or expected credential version.

type VerifyRegistrationRequest

type VerifyRegistrationRequest struct {
	Context         CeremonyContext
	CeremonyID      string
	Origin          string
	Response        []byte
	ExpectedVersion uint64
}

VerifyRegistrationRequest is bounded raw browser JSON, not verified evidence. Context.CommandID is distinct from the creation command and stable on retry.

Directories

Path Synopsis
postgres module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL