webauthn

package
v0.0.0-...-5c79d48 Latest Latest
Warning

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

Go to latest
Published: Feb 15, 2024 License: AGPL-3.0 Imports: 27 Imported by: 0

Documentation

Overview

Package webauthn implements server-side support for the Web Authentication specification.

Refer to https://www.w3.org/TR/webauthn-2/ for details.

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidCredentials = errors.New("user has only invalid WebAuthn registrations, consider a user reset")

ErrInvalidCredentials is a special kind of credential "NotFound" error, where the user has only devices registered to other RPIDs. Possible fixes include reseting the affected users (likely the entire cluster), or rolling back to a good WebAuthn configuration (if still possible).

Functions

func U2FKeyToCBOR

func U2FKeyToCBOR(pubKey *ecdsa.PublicKey) ([]byte, error)

U2FKeyToCBOR transforms a DER-encoded U2F into its CBOR counterpart.

Types

type LoginData

type LoginData struct {
	// User is the Teleport user.
	User string
	// Device is the MFA device used to authenticate the user.
	Device *types.MFADevice
	// AllowReuse is whether the webauthn challenge used for this login
	// can be reused by the user for subsequent logins, until it expires.
	AllowReuse mfav1.ChallengeAllowReuse
}

LoginData is data gathered from a successful webauthn login.

type LoginFlow

type LoginFlow struct {
	U2F      *types.U2F
	Webauthn *types.Webauthn
	// Identity is typically an implementation of the Identity service, ie, an
	// object with access to user, device and MFA storage.
	Identity LoginIdentity
}

LoginFlow represents the WebAuthn login procedure (aka authentication).

The login flow consists of:

  1. Client requests a CredentialAssertion (containing, among other info, a challenge to be signed)
  2. Server runs Begin(), generates a credential assertion.
  3. Client validates the assertion, performs a user presence test (usually by asking the user to touch a secure token), and replies with CredentialAssertionResponse (containing the signed challenge)
  4. Server runs Finish()
  5. If all server-side checks are successful, then login/authentication is complete.

LoginFlow is used in the following scenarios:

  • Password plus challenge logins
  • Presence verification checks (eg, session MFA)
  • User verification checks after the initial login (eg, password changes with only a discoverable credential).

func (*LoginFlow) Begin

func (f *LoginFlow) Begin(ctx context.Context, user string, challengeExtensions *mfav1.ChallengeExtensions) (*wantypes.CredentialAssertion, error)

Begin is the first step of the LoginFlow. The CredentialAssertion created is relayed back to the client, who in turn performs a user presence check and signs the challenge contained within the assertion. As a side effect Begin may assign (and record in storage) a WebAuthn ID for the user. Requested challenge extensions will be stored on the stored webauthn challenge record. These extensions indicate additional rules/properties of the webauthn challenge that can be validated in the final login step.

func (*LoginFlow) Finish

func (f *LoginFlow) Finish(ctx context.Context, user string, resp *wantypes.CredentialAssertionResponse, requiredExtensions *mfav1.ChallengeExtensions) (*LoginData, error)

Finish is the second and last step of the LoginFlow. Expected challenge extensions will be validated against the stored webauthn challenge record. It returns the MFADevice used to solve the challenge, the associated Teleport user name, and other login properties. If login is successful, Finish has the side effect of updating the counter and last used timestamp of the MFADevice used.

type LoginIdentity

type LoginIdentity interface {
	GetWebauthnLocalAuth(ctx context.Context, user string) (*types.WebauthnLocalAuth, error)

	GetMFADevices(ctx context.Context, user string, withSecrets bool) ([]*types.MFADevice, error)
	UpsertMFADevice(ctx context.Context, user string, d *types.MFADevice) error
	UpsertWebauthnSessionData(ctx context.Context, user, sessionID string, sd *wantypes.SessionData) error
	GetWebauthnSessionData(ctx context.Context, user, sessionID string) (*wantypes.SessionData, error)
	DeleteWebauthnSessionData(ctx context.Context, user, sessionID string) error
}

LoginIdentity represents the subset of Identity methods used by LoginFlow. It exists to better scope LoginFlow's use of Identity and to facilitate testing.

func WithDevices

func WithDevices(identity LoginIdentity, devs []*types.MFADevice) LoginIdentity

WithDevices returns a LoginIdentity backed by a fixed set of devices. The supplied devices are returned in all GetMFADevices calls.

type PasswordlessFlow

type PasswordlessFlow struct {
	Webauthn *types.Webauthn
	Identity PasswordlessIdentity
}

PasswordlessFlow provides passwordless authentication.

PasswordlessFlow is used mainly for the initial passwordless login. For UV=1 assertions after login, use LoginFlow.Begin with the desired mfav1.ChallengeExtensions.UserVerificationRequirement.

func (*PasswordlessFlow) Begin

Begin is the first step of the passwordless login flow. It works similarly to LoginFlow.Begin, but it doesn't require a Teleport username nor implies a previous password-validation step.

func (*PasswordlessFlow) Finish

Finish is the last step of the passwordless login flow. It works similarly to LoginFlow.Finish, but the user identity is established via the response UserHandle, instead of an explicit Teleport username.

type PasswordlessIdentity

type PasswordlessIdentity interface {
	GetMFADevices(ctx context.Context, user string, withSecrets bool) ([]*types.MFADevice, error)
	UpsertMFADevice(ctx context.Context, user string, d *types.MFADevice) error

	UpsertGlobalWebauthnSessionData(ctx context.Context, scope, id string, sd *wantypes.SessionData) error
	GetGlobalWebauthnSessionData(ctx context.Context, scope, id string) (*wantypes.SessionData, error)
	DeleteGlobalWebauthnSessionData(ctx context.Context, scope, id string) error
	GetTeleportUserByWebauthnID(ctx context.Context, webID []byte) (string, error)
}

PasswordlessIdentity represents the subset of Identity methods used by PasswordlessFlow.

type RegisterResponse

type RegisterResponse struct {
	// User is the device owner.
	User string
	// DeviceName is the name for the new device.
	DeviceName string
	// CreationResponse is the response from the new device.
	CreationResponse *wantypes.CredentialCreationResponse
	// Passwordless is true if this is expected to be a passwordless registration.
	// Callers may make certain concessions when processing passwordless
	// registration (such as skipping password validation), this flag reflects that.
	// The data stored in the Begin SessionData must match the passwordless flag,
	// otherwise the registration is denied.
	Passwordless bool
}

RegisterResponse represents fields needed to finish registering a new WebAuthn device.

type RegistrationFlow

type RegistrationFlow struct {
	Webauthn *types.Webauthn
	Identity RegistrationIdentity
}

RegistrationFlow represents the WebAuthn registration ceremony.

Registration consists of:

  1. Client requests a CredentialCreation (containing a challenge and various settings that may constrain allowed authenticators).
  2. Server runs Begin(), generates a credential creation.
  3. Client validates the credential creation, performs a user presence test (usually by asking the user to touch a secure token), and replies with a CredentialCreationResponse (containing the signed challenge and information about the credential and authenticator)
  4. Server runs Finish()
  5. If all server-side checks are successful, then registration is complete and the authenticator may now be used to login.

func (*RegistrationFlow) Begin

func (f *RegistrationFlow) Begin(ctx context.Context, user string, passwordless bool) (*wantypes.CredentialCreation, error)

Begin is the first step of the registration ceremony. The CredentialCreation created is relayed back to the client, who in turn performs a user presence check and signs the challenge contained within it. If passwordless is set, then registration asks the authenticator for a resident key. As a side effect Begin may assign (and record in storage) a WebAuthn ID for the user.

func (*RegistrationFlow) Finish

Finish is the second and last step of the registration ceremony. If successful, it returns the created MFADevice. Finish has the side effect or writing the device to storage (using its Identity interface).

type RegistrationIdentity

type RegistrationIdentity interface {
	UpsertWebauthnLocalAuth(ctx context.Context, user string, wla *types.WebauthnLocalAuth) error
	GetWebauthnLocalAuth(ctx context.Context, user string) (*types.WebauthnLocalAuth, error)
	GetTeleportUserByWebauthnID(ctx context.Context, webID []byte) (string, error)

	GetMFADevices(ctx context.Context, user string, withSecrets bool) ([]*types.MFADevice, error)
	UpsertMFADevice(ctx context.Context, user string, d *types.MFADevice) error
	UpsertWebauthnSessionData(ctx context.Context, user, sessionID string, sd *wantypes.SessionData) error
	GetWebauthnSessionData(ctx context.Context, user, sessionID string) (*wantypes.SessionData, error)
	DeleteWebauthnSessionData(ctx context.Context, user, sessionID string) error
}

RegistrationIdentity represents the subset of Identity methods used by RegistrationFlow.

func WithInMemorySessionData

func WithInMemorySessionData(identity RegistrationIdentity) RegistrationIdentity

WithInMemorySessionData returns a RegistrationIdentity implementation that keeps SessionData in memory.

Jump to

Keyboard shortcuts

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