virtualwebauthn

package module
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Dec 18, 2022 License: MIT Imports: 10 Imported by: 2

README

Virtual WebAuthn

The Go package virtualwebauthn provides a set of helper tools for testing full WebAuthn authentication flows in a relying party WebAuthn server implementation without requiring a browser or an actual authenticator.

Check the test for a working example on how to use this library.

Features

  • Test both register/attestation and login/assertion flows
  • Validate credential creation and request options
  • Generate attestation and assertion responses
  • Supports EC2 and RSA keys with SHA256
  • Supports packed attestation format

Usage

Setup

First we create mock entities to work with for running tests.

// The relying party settings should mirror those on the actual WebAuthn server
rp := virtualwebauthn.RelyingParty{Name: "Example Corp", ID: "example.com", Origin: "https://example.com"}

// A mock authenticator that represents a security key or biometrics module
authenticator := virtualwebauthn.NewAuthenticator()

// Create a new credential that we'll try to register with the relying party
credential := virtualwebauthn.NewCredential(virtualwebauthn.KeyTypeEC2)
Register

Start a register flow with the relying party and get an attestationOptions JSON string that contains the serialized credential creation options:

// Ask the server to start a register flow for a user. The server and user here
// are placeholders for whatever the system being tested uses.
attestationOptions := server.registerStart(user)

Use the ParseAttestationOptions and CreateAttestationResponse functions to parse the attestationOptions string, ensure that it's valid, and generate an appropriate attestationResponse that should appear to have come from a browser's navigator.credentials.create call:

// Parses the attestation options we got from the relying party to ensure they're valid
parsedAttestationOptions, err := virtualwebauthn.ParseAttestationOptions(attestationOptions)
if err != nil {
    ...
}

// Creates an attestation response that we can send to the relying party as if it came from
// an actual browser and authenticator.
attestationResponse := virtualwebauthn.CreateAttestationResponse(rp, authenticator, credential, *parsedAttestationOptions)

We can now go back to the relying party with the attestationResponse and finish the register flow:

// Finish the register flow by sending the attestation response. Again the server and
// user here are placeholders for whatever the system being tested uses.
err := server.registerFinish(user, attestationResponse)
if err != nil {
    ...
}

// Add the EC2 credential to the mock authenticator
authenticator.AddCredential(credential)

Documentation

Overview

Package virtualwebauthn provides a set of helper tools for testing Webauthn authentication flows.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CreateAssertionResponse

func CreateAssertionResponse(rp RelyingParty, auth Authenticator, cred Credential, options AssertionOptions) string

func CreateAttestationResponse

func CreateAttestationResponse(rp RelyingParty, auth Authenticator, cred Credential, options AttestationOptions) string

Types

type AssertionOptions

type AssertionOptions struct {
	Challenge        []byte   `json:"challenge,omitempty"`
	AllowCredentials []string `json:"allowCredentials,omitempty"`
	RelyingPartyID   string   `json:"rpId,omitempty"`
}

func ParseAssertionOptions

func ParseAssertionOptions(str string) (assertionOptions *AssertionOptions, err error)

type AttestationOptions

type AttestationOptions struct {
	Challenge          []byte   `json:"challenge,omitempty"`
	ExcludeCredentials []string `json:"excludeCredentials,omitempty"`
	RelyingPartyID     string   `json:"rpId,omitempty"`
	RelyingPartyName   string   `json:"rpName,omitempty"`
	UserID             string   `json:"user,omitempty"`
	UserName           string   `json:"userName,omitempty"`
	UserDisplayName    string   `json:"userDisplayName,omitempty"`
}

func ParseAttestationOptions

func ParseAttestationOptions(str string) (attestationOptions *AttestationOptions, err error)

type Authenticator

type Authenticator struct {
	Options     AuthenticatorOptions `json:"options"`
	Aaguid      [16]byte             `json:"aaguid"`
	Credentials []Credential         `json:"credentials,omitempty"`
}

func NewAuthenticator

func NewAuthenticator() Authenticator

func NewAuthenticatorWithOptions

func NewAuthenticatorWithOptions(options AuthenticatorOptions) Authenticator

func (*Authenticator) AddCredential

func (a *Authenticator) AddCredential(cred Credential)

func (*Authenticator) FindAllowedCredential

func (a *Authenticator) FindAllowedCredential(options AssertionOptions) *Credential

type AuthenticatorOptions

type AuthenticatorOptions struct {
	UserHandle      []byte
	UserNotPresent  bool
	UserNotVerified bool
}

type Credential

type Credential struct {
	ID      []byte `json:"id"`
	Key     Key    `json:"key"`
	Counter uint32 `json:"counter,omitempty"`
}

func NewCredential

func NewCredential(keyType KeyType) Credential

func (*Credential) IsAllowedForAssertion

func (c *Credential) IsAllowedForAssertion(options AssertionOptions) bool

func (*Credential) IsExcludedForAttestation

func (c *Credential) IsExcludedForAttestation(options AttestationOptions) bool

type Key

type Key struct {
	Type       KeyType    `json:"type"`
	SigningKey SigningKey `json:"signingKey"`
}

type KeyType

type KeyType int
const (
	KeyTypeEC2 KeyType = iota
	KeyTypeRSA
)

type RelyingParty

type RelyingParty struct {
	ID     string `json:"id"`
	Name   string `json:"name"`
	Origin string `json:"origin"`
}

type SigningKey

type SigningKey interface {
	KeyData() []byte
	Sign(digest []byte) (signature []byte, err error)
}

Jump to

Keyboard shortcuts

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