Documentation
¶
Overview ¶
contract.go: Wires the passkey plugin into the forge-dashboard contract surface via plugin.ContractContributor.
Package passkey provides WebAuthn/passkey authentication for AuthSome.
The passkey plugin supports FIDO2 WebAuthn registration and authentication ceremonies. It owns its own credential store (like the MFA plugin) and provides HTTP routes via the RouteProvider interface.
Usage:
eng, _ := authsome.NewEngine(
authsome.WithStore(store),
authsome.WithPlugin(passkey.New(passkey.Config{
RPDisplayName: "My App",
RPID: "example.com",
RPOrigins: []string{"https://example.com"},
})),
)
Index ¶
- Variables
- type Assertion
- type AssertionResponse
- type Attestation
- type AttestationResponse
- type Config
- type Credential
- type CredentialInfo
- type DeleteRequest
- type DeleteResponse
- type ListRequest
- type ListResponse
- type LoginBeginRequest
- type LoginBeginResponse
- type LoginFinishRequest
- type LoginFinishResponse
- type MemoryStore
- func (s *MemoryStore) CreateCredential(_ context.Context, c *Credential) error
- func (s *MemoryStore) DeleteCredential(_ context.Context, credentialID []byte) error
- func (s *MemoryStore) GetCredential(_ context.Context, credentialID []byte) (*Credential, error)
- func (s *MemoryStore) ListUserCredentials(_ context.Context, userID id.UserID) ([]*Credential, error)
- func (s *MemoryStore) UpdateSignCount(_ context.Context, credentialID []byte, count uint32) error
- type MongoStore
- func (s *MongoStore) CreateCredential(ctx context.Context, c *Credential) error
- func (s *MongoStore) DeleteCredential(ctx context.Context, credentialID []byte) error
- func (s *MongoStore) GetCredential(ctx context.Context, credentialID []byte) (*Credential, error)
- func (s *MongoStore) ListUserCredentials(ctx context.Context, userID id.UserID) ([]*Credential, error)
- func (s *MongoStore) UpdateSignCount(ctx context.Context, credentialID []byte, count uint32) error
- type Plugin
- func (p *Plugin) DeclareSettings(m *settings.Manager) error
- func (p *Plugin) ListUserAuthMethods(ctx context.Context, userID id.UserID) ([]*plugin.AuthMethod, error)
- func (p *Plugin) MigrationGroups(driverName string) []*migrate.Group
- func (p *Plugin) Name() string
- func (p *Plugin) OnBeforeUserDelete(ctx context.Context, userID id.UserID) error
- func (p *Plugin) OnInit(_ context.Context, engine plugin.Engine) error
- func (p *Plugin) RegisterContract(d *dispatcher.Dispatcher, reg contract.Registry, wreg contract.WardenRegistry, ...) error
- func (p *Plugin) RegisterRoutes(router forge.Router) error
- func (p *Plugin) SetStore(s Store)
- type PostgresStore
- func (s *PostgresStore) CreateCredential(ctx context.Context, c *Credential) error
- func (s *PostgresStore) DeleteCredential(ctx context.Context, credentialID []byte) error
- func (s *PostgresStore) GetCredential(ctx context.Context, credentialID []byte) (*Credential, error)
- func (s *PostgresStore) ListUserCredentials(ctx context.Context, userID id.UserID) ([]*Credential, error)
- func (s *PostgresStore) UpdateSignCount(ctx context.Context, credentialID []byte, count uint32) error
- type RegisterBeginRequest
- type RegisterBeginResponse
- type RegisterFinishRequest
- type RegisterFinishResponse
- type SqliteStore
- func (s *SqliteStore) CreateCredential(ctx context.Context, c *Credential) error
- func (s *SqliteStore) DeleteCredential(ctx context.Context, credentialID []byte) error
- func (s *SqliteStore) GetCredential(ctx context.Context, credentialID []byte) (*Credential, error)
- func (s *SqliteStore) ListUserCredentials(ctx context.Context, userID id.UserID) ([]*Credential, error)
- func (s *SqliteStore) UpdateSignCount(ctx context.Context, credentialID []byte, count uint32) error
- type Store
Constants ¶
This section is empty.
Variables ¶
var ( // SettingRPDisplayName controls the relying party display name. SettingRPDisplayName = settings.Define("passkey.rp_display_name", "AuthSome", settings.WithDisplayName("RP Display Name"), settings.WithDescription("Relying party display name shown to users during WebAuthn ceremonies"), settings.WithCategory("Passkey / WebAuthn"), settings.WithScopes(settings.ScopeGlobal, settings.ScopeApp), settings.WithInputType(formconfig.FieldText), settings.WithPlaceholder("AuthSome"), settings.WithUIValidation(formconfig.Validation{Required: true, MaxLen: 100}), settings.WithHelpText("The name users see when registering or authenticating with passkeys"), settings.WithOrder(10), ) // SettingRPID controls the relying party identifier. SettingRPID = settings.Define("passkey.rp_id", "localhost", settings.WithDisplayName("RP ID"), settings.WithDescription("Relying party identifier (typically the domain name)"), settings.WithCategory("Passkey / WebAuthn"), settings.WithScopes(settings.ScopeGlobal, settings.ScopeApp), settings.WithInputType(formconfig.FieldText), settings.WithPlaceholder("example.com"), settings.WithUIValidation(formconfig.Validation{ Required: true, MaxLen: 253, Pattern: `^(localhost|127\.0\.0\.1|::1|([a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*)$`, }), settings.WithHelpText("Must match the effective domain users browse to. Use 'localhost' for dev."), settings.WithOrder(20), ) // SettingRPOrigins controls the allowed origins for WebAuthn ceremonies. // When empty, origins are derived from RPID (and the request origin for // localhost dev mode — see Plugin.waForRequest). SettingRPOrigins = settings.Define("passkey.rp_origins", []string{}, settings.WithDisplayName("RP Origins"), settings.WithDescription("Allowed origins for WebAuthn ceremonies (e.g. https://app.example.com)"), settings.WithCategory("Passkey / WebAuthn"), settings.WithScopes(settings.ScopeGlobal, settings.ScopeApp), settings.WithInputType(formconfig.FieldTextarea), settings.WithPlaceholder("https://app.example.com\nhttps://www.example.com"), settings.WithHelpText("One origin per line. Each must include scheme and port. Leave empty to use Config defaults; localhost dev auto-trusts the request origin regardless of port."), settings.WithOrder(25), ) // SettingSessionTimeoutSeconds controls the WebAuthn ceremony timeout. SettingSessionTimeoutSeconds = settings.Define("passkey.session_timeout_seconds", 300, settings.WithDisplayName("Ceremony Timeout (seconds)"), settings.WithDescription("How long a WebAuthn ceremony session lives in seconds"), settings.WithCategory("Passkey / WebAuthn"), settings.WithScopes(settings.ScopeGlobal, settings.ScopeApp), settings.WithInputType(formconfig.FieldNumber), settings.WithUIValidation(formconfig.Validation{Required: true, Min: intPtr(30), Max: intPtr(600)}), settings.WithHelpText("Time allowed to complete a passkey ceremony. Default: 300 (5 minutes)"), settings.WithOrder(30), ) )
var ErrCredentialNotFound = errors.New("passkey: credential not found")
ErrCredentialNotFound is returned when a credential is not found.
var PostgresMigrations = migrate.NewGroup("authsome-passkey", migrate.DependsOn("authsome"))
PostgresMigrations is the postgres migration group for the passkey plugin.
var SqliteMigrations = migrate.NewGroup("authsome-passkey", migrate.DependsOn("authsome"))
SqliteMigrations is the SQLite migration group for the passkey plugin.
Functions ¶
This section is empty.
Types ¶
type Assertion ¶ added in v1.9.0
type Assertion struct {
ID string `json:"id"`
RawID string `json:"rawId"`
Type string `json:"type"`
Response AssertionResponse `json:"response"`
}
Assertion is the credential navigator.credentials.get() returns, posted to /v1/passkeys/login/finish.
type AssertionResponse ¶ added in v1.9.0
type AssertionResponse struct {
ClientDataJSON string `json:"clientDataJSON"`
AuthenticatorData string `json:"authenticatorData"`
Signature string `json:"signature"`
UserHandle string `json:"userHandle,omitempty"`
}
AssertionResponse is the assertion half of a login credential. UserHandle is present only for discoverable (passwordless) login.
type Attestation ¶ added in v1.9.0
type Attestation struct {
ID string `json:"id"`
RawID string `json:"rawId"`
Type string `json:"type"`
Response AttestationResponse `json:"response"`
}
Attestation is the credential navigator.credentials.create() returns, posted to /v1/passkeys/register/finish.
type AttestationResponse ¶ added in v1.9.0
type AttestationResponse struct {
ClientDataJSON string `json:"clientDataJSON"`
AttestationObject string `json:"attestationObject"`
}
AttestationResponse is the attestation half of a registration credential.
type Config ¶
type Config struct {
// RPDisplayName is the relying party display name shown to users.
RPDisplayName string
// RPID is the relying party identifier (typically the domain name).
RPID string
// RPOrigins are the allowed origins for WebAuthn ceremonies.
RPOrigins []string
// SessionTimeout is how long a WebAuthn ceremony session lives (default: 5 minutes).
SessionTimeout time.Duration
// StepUpWindow is how recently the caller must have signed in to
// register a passkey (default: 5 minutes). A passkey is a sign-in
// credential, so adding one on a possibly stolen session is refused.
StepUpWindow time.Duration
}
Config configures the passkey/WebAuthn plugin.
type Credential ¶ added in v1.9.0
type Credential struct {
ID id.PasskeyID `json:"id"`
UserID id.UserID `json:"user_id"`
AppID id.AppID `json:"app_id"`
CredentialID []byte `json:"credential_id"` // Raw credential ID from WebAuthn
PublicKey []byte `json:"public_key"` // COSE-encoded public key
AttestationType string `json:"attestation_type"` // "none", "packed", etc.
Transport []string `json:"transport"` // "usb", "ble", "nfc", "internal"
SignCount uint32 `json:"sign_count"`
AAGUID []byte `json:"aaguid"`
DisplayName string `json:"display_name"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Credential represents a WebAuthn/passkey credential stored for a user.
type CredentialInfo ¶ added in v1.9.0
type CredentialInfo struct {
ID string `json:"id"`
DisplayName string `json:"display_name"`
Transport []string `json:"transport"`
CreatedAt string `json:"created_at"`
}
CredentialInfo is a serializable credential summary.
type DeleteRequest ¶ added in v1.9.0
type DeleteRequest struct {
CredentialID string `path:"credentialId"`
}
DeleteRequest is the request for deleting a passkey.
type DeleteResponse ¶ added in v1.9.0
type DeleteResponse struct {
Status string `json:"status"`
}
DeleteResponse confirms passkey deletion.
type ListRequest ¶ added in v1.9.0
type ListRequest struct{}
ListRequest is an empty request for listing passkeys.
type ListResponse ¶ added in v1.9.0
type ListResponse struct {
Credentials []*CredentialInfo `json:"credentials"`
}
ListResponse contains the user's registered passkeys.
type LoginBeginRequest ¶ added in v1.9.0
type LoginBeginRequest struct{}
LoginBeginRequest initiates a WebAuthn authentication ceremony. LoginBeginRequest has no fields: which ceremony to start is decided by whether the caller is already authenticated, not by anything they send.
It previously carried an Email, but nothing ever read it — resolveUser resolves from the auth context — so supplying one selected the step-up branch while the value itself was discarded. Email-identified passkey login is not implemented; it would also disclose whether an address has passkeys registered, which the discoverable flow avoids by design.
type LoginBeginResponse ¶ added in v1.9.0
type LoginBeginResponse struct {
Options any `json:"options"`
}
LoginBeginResponse contains the WebAuthn assertion options.
type LoginFinishRequest ¶ added in v1.9.0
type LoginFinishRequest struct{}
LoginFinishRequest is the raw assertion response from the browser.
type LoginFinishResponse ¶ added in v1.9.0
type LoginFinishResponse struct {
UserID string `json:"user_id"`
Status string `json:"status"`
SessionToken string `json:"session_token,omitempty"`
RefreshToken string `json:"refresh_token,omitempty"`
}
LoginFinishResponse confirms successful authentication. For passwordless (discoverable) login it also carries the freshly-issued session tokens.
type MemoryStore ¶ added in v1.9.0
type MemoryStore struct {
// contains filtered or unexported fields
}
MemoryStore is an in-memory Store for testing.
func NewMemoryStore ¶ added in v1.9.0
func NewMemoryStore() *MemoryStore
NewMemoryStore creates a new in-memory passkey credential store.
func (*MemoryStore) CreateCredential ¶ added in v1.9.0
func (s *MemoryStore) CreateCredential(_ context.Context, c *Credential) error
CreateCredential stores a new passkey credential.
func (*MemoryStore) DeleteCredential ¶ added in v1.9.0
func (s *MemoryStore) DeleteCredential(_ context.Context, credentialID []byte) error
DeleteCredential removes a credential by its WebAuthn credential ID.
func (*MemoryStore) GetCredential ¶ added in v1.9.0
func (s *MemoryStore) GetCredential(_ context.Context, credentialID []byte) (*Credential, error)
GetCredential finds a credential by its WebAuthn credential ID.
func (*MemoryStore) ListUserCredentials ¶ added in v1.9.0
func (s *MemoryStore) ListUserCredentials(_ context.Context, userID id.UserID) ([]*Credential, error)
ListUserCredentials returns all credentials for a user.
func (*MemoryStore) UpdateSignCount ¶ added in v1.9.0
UpdateSignCount updates the sign counter for a credential.
type MongoStore ¶ added in v1.9.0
type MongoStore struct {
// contains filtered or unexported fields
}
MongoStore implements passkey.Store using the Grove MongoDB driver.
func NewMongoStore ¶ added in v1.9.0
func NewMongoStore(db *grove.DB) *MongoStore
NewMongoStore creates a new MongoDB-backed passkey store.
func (*MongoStore) CreateCredential ¶ added in v1.9.0
func (s *MongoStore) CreateCredential(ctx context.Context, c *Credential) error
func (*MongoStore) DeleteCredential ¶ added in v1.9.0
func (s *MongoStore) DeleteCredential(ctx context.Context, credentialID []byte) error
func (*MongoStore) GetCredential ¶ added in v1.9.0
func (s *MongoStore) GetCredential(ctx context.Context, credentialID []byte) (*Credential, error)
func (*MongoStore) ListUserCredentials ¶ added in v1.9.0
func (s *MongoStore) ListUserCredentials(ctx context.Context, userID id.UserID) ([]*Credential, error)
func (*MongoStore) UpdateSignCount ¶ added in v1.9.0
type Plugin ¶
type Plugin struct {
// contains filtered or unexported fields
}
Plugin is the passkey/WebAuthn plugin.
func (*Plugin) DeclareSettings ¶ added in v1.9.0
DeclareSettings implements plugin.SettingsProvider.
func (*Plugin) ListUserAuthMethods ¶ added in v1.9.0
func (p *Plugin) ListUserAuthMethods(ctx context.Context, userID id.UserID) ([]*plugin.AuthMethod, error)
ListUserAuthMethods implements plugin.AuthMethodContributor. It returns one entry per registered passkey credential for the user.
func (*Plugin) MigrationGroups ¶ added in v1.9.0
MigrationGroups implements plugin.MigrationProvider.
func (*Plugin) OnBeforeUserDelete ¶ added in v1.9.0
OnBeforeUserDelete removes a deleted user's passkeys. A credential that outlives its account is a way back in that nobody owns.
func (*Plugin) OnInit ¶ added in v1.9.0
OnInit initializes the WebAuthn library and optionally extracts bridges and the ceremony store from the engine.
func (*Plugin) RegisterContract ¶ added in v1.9.0
func (p *Plugin) RegisterContract( d *dispatcher.Dispatcher, reg contract.Registry, wreg contract.WardenRegistry, engine plugin.Engine, ) error
func (*Plugin) RegisterRoutes ¶
RegisterRoutes registers passkey/WebAuthn HTTP endpoints on a forge.Router.
type PostgresStore ¶ added in v1.9.0
type PostgresStore struct {
// contains filtered or unexported fields
}
PostgresStore implements passkey.Store using the Grove ORM with PostgreSQL.
func NewPostgresStore ¶ added in v1.9.0
func NewPostgresStore(db *grove.DB) *PostgresStore
NewPostgresStore creates a new PostgreSQL-backed passkey store.
func (*PostgresStore) CreateCredential ¶ added in v1.9.0
func (s *PostgresStore) CreateCredential(ctx context.Context, c *Credential) error
func (*PostgresStore) DeleteCredential ¶ added in v1.9.0
func (s *PostgresStore) DeleteCredential(ctx context.Context, credentialID []byte) error
func (*PostgresStore) GetCredential ¶ added in v1.9.0
func (s *PostgresStore) GetCredential(ctx context.Context, credentialID []byte) (*Credential, error)
func (*PostgresStore) ListUserCredentials ¶ added in v1.9.0
func (s *PostgresStore) ListUserCredentials(ctx context.Context, userID id.UserID) ([]*Credential, error)
func (*PostgresStore) UpdateSignCount ¶ added in v1.9.0
type RegisterBeginRequest ¶ added in v1.9.0
type RegisterBeginRequest struct {
DisplayName string `json:"display_name,omitempty"`
}
RegisterBeginRequest is the request body for beginning passkey registration.
type RegisterBeginResponse ¶ added in v1.9.0
type RegisterBeginResponse struct {
Options any `json:"options"`
}
RegisterBeginResponse contains the WebAuthn registration options.
type RegisterFinishRequest ¶ added in v1.9.0
type RegisterFinishRequest struct{}
RegisterFinishRequest is the raw attestation response from the browser.
type RegisterFinishResponse ¶ added in v1.9.0
type RegisterFinishResponse struct {
ID string `json:"id"`
DisplayName string `json:"display_name"`
Status string `json:"status"`
}
RegisterFinishResponse confirms credential registration.
type SqliteStore ¶ added in v1.9.0
type SqliteStore struct {
// contains filtered or unexported fields
}
SqliteStore implements passkey.Store using the Grove ORM with SQLite.
func NewSqliteStore ¶ added in v1.9.0
func NewSqliteStore(db *grove.DB) *SqliteStore
NewSqliteStore creates a new SQLite-backed passkey store.
func (*SqliteStore) CreateCredential ¶ added in v1.9.0
func (s *SqliteStore) CreateCredential(ctx context.Context, c *Credential) error
func (*SqliteStore) DeleteCredential ¶ added in v1.9.0
func (s *SqliteStore) DeleteCredential(ctx context.Context, credentialID []byte) error
func (*SqliteStore) GetCredential ¶ added in v1.9.0
func (s *SqliteStore) GetCredential(ctx context.Context, credentialID []byte) (*Credential, error)
func (*SqliteStore) ListUserCredentials ¶ added in v1.9.0
func (s *SqliteStore) ListUserCredentials(ctx context.Context, userID id.UserID) ([]*Credential, error)
func (*SqliteStore) UpdateSignCount ¶ added in v1.9.0
type Store ¶ added in v1.9.0
type Store interface {
CreateCredential(ctx context.Context, c *Credential) error
GetCredential(ctx context.Context, credentialID []byte) (*Credential, error)
ListUserCredentials(ctx context.Context, userID id.UserID) ([]*Credential, error)
DeleteCredential(ctx context.Context, credentialID []byte) error
UpdateSignCount(ctx context.Context, credentialID []byte, count uint32) error
}
Store persists passkey/WebAuthn credential data.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package contract wires the passkey plugin's deep-link settings page into the forge-dashboard contract registry.
|
Package contract wires the passkey plugin's deep-link settings page into the forge-dashboard contract registry. |
|
Package passkeytest provides a backend-agnostic conformance suite for the passkey.Store interface.
|
Package passkeytest provides a backend-agnostic conformance suite for the passkey.Store interface. |