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 ¶
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 ¶
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:
- Client requests a CredentialAssertion (containing, among other info, a challenge to be signed)
- Server runs Begin(), generates a credential assertion.
- 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)
- Server runs Finish()
- 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 ¶
func (f *PasswordlessFlow) Begin(ctx context.Context) (*wantypes.CredentialAssertion, error)
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 ¶
func (f *PasswordlessFlow) Finish(ctx context.Context, resp *wantypes.CredentialAssertionResponse) (*LoginData, error)
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:
- Client requests a CredentialCreation (containing a challenge and various settings that may constrain allowed authenticators).
- Server runs Begin(), generates a credential creation.
- 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)
- Server runs Finish()
- 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 ¶
func (f *RegistrationFlow) Finish(ctx context.Context, req RegisterResponse) (*types.MFADevice, error)
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.