webauthn

package module
v0.0.0-...-4b45219 Latest Latest
Warning

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

Go to latest
Published: Apr 1, 2024 License: Apache-2.0 Imports: 27 Imported by: 2

README

Webauthn

Go Report Card GoDoc Coverage Status pomerium chat GitHub Actions LICENSE

This Go library implements WebAuthn/FIDO2 spec as a relying party, and includes:

Code examples

A WebAuthn relying party verifies device identity in two steps. First a device is registered using the VerifyRegistrationCeremony method:

Register
ctx := context.Background()

origin := "http://localhost:5000"
storage := webauthn.NewInMemoryCredentialStorage()
relyingParty := webauthn.NewRelyingParty(origin, storage)

var options webauthn.PublicKeyCredentialCreationOptions
_ = json.Unmarshal([]byte(`
    {
      "rp": {
        "name": "Pomerium"
      },
      "user": {
        "displayName": "Test User",
        "name": "test-user",
        "id": "dGVzdC11c2Vy"
      },
      "pubKeyCredParams": [
        {
          "type": "public-key",
          "alg": -257
        },
        {
          "type": "public-key",
          "alg": -7
        }
      ],
      "authenticatorSelection": {
        "authenticatorAttachment": "cross-platform",
        "requireResidentKey": false
      },
      "attestation": "direct",
      "challenge": "dGVzdC1jaGFsbGVuZ2U",
      "timeout": 15000
    }
`), &options)
var response webauthn.PublicKeyCreationCredential
_ = json.Unmarshal([]byte(`
    {
      "id": "BOyUQxjpKJSR2VhsJok4FR8LIoZZ53QnrXxkiw5tzrp0cJuciBsxdIjabLjB6ebQMuKPqmMIPanM28HzGB9sig",
      "rawId": "BOyUQxjpKJSR2VhsJok4FR8LIoZZ53QnrXxkiw5tzrp0cJuciBsxdIjabLjB6ebQMuKPqmMIPanM28HzGB9sig",
      "response": {
        "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiZEdWemRDMWphR0ZzYkdWdVoyVSIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6NTAwMCIsImNyb3NzT3JpZ2luIjpmYWxzZSwib3RoZXJfa2V5c19jYW5fYmVfYWRkZWRfaGVyZSI6ImRvIG5vdCBjb21wYXJlIGNsaWVudERhdGFKU09OIGFnYWluc3QgYSB0ZW1wbGF0ZS4gU2VlIGh0dHBzOi8vZ29vLmdsL3lhYlBleCJ9",
        "attestationObject": "o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2lnWEgwRgIhAIwctsPvNyXT6gEFJnqWlYqy_GBgNawLRrdZUwy8KpYqAiEAoQ6ct84cs9xyKo3v4c2HBGs1T7wg67oepLeiRa8vUG1jeDVjgVkBXTCCAVkwggEAoAMCAQICAQEwCgYIKoZIzj0EAwIwKDEVMBMGA1UEAxMMU2VjdXJpdHkgS2V5MQ8wDQYDVQQKEwZHb29nbGUwIhgPMjAwMDAxMDEwMDAwMDBaGA8yMDk5MTIzMTIzNTk1OVowKDEVMBMGA1UEAxMMU2VjdXJpdHkgS2V5MQ8wDQYDVQQKEwZHb29nbGUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ_1ZtuIheQTnPrYNbFIME1flmt6RjmX7dUQbpOUwIl4lhN_I6gOiWBaocqrYWJlGVyXN4uYV31iKY73Zw1EjhaoxcwFTATBgsrBgEEAYLlHAIBAQQEAwIEMDAKBggqhkjOPQQDAgNHADBEAiBKHLlAEJFmo0of3IiO6Afg2kn8Rmn0wa4ml4ANfsBW9AIgauaLpiP9LGBRXYS7hq1B-GSzl40V8PR_k2HkZ76RDuxoYXV0aERhdGFYxEmWDeWIDoxodDQXD2R2YFuP5K65ooYyx5lc87qDHZdjQQAAAAAAAAAAAAAAAAAAAAAAAAAAAEAE7JRDGOkolJHZWGwmiTgVHwsihlnndCetfGSLDm3OunRwm5yIGzF0iNpsuMHp5tAy4o-qYwg9qczbwfMYH2yKpQECAyYgASFYID1HLxI1bZD28OItYBsrBNkz8hr_YWX_sIht0GVmMNCcIlggze0LBzzUxMeF3sWcDzsHXr-hxGEQgwjZBjQg2dcdp7Y"
      }
    }
`), &response)

credential, err := relyingParty.VerifyRegistrationCeremony(ctx, &options, &response)
Authenticate

Once a device is registered subsequent logins can authenticate the device using VerifyAuthenticationCeremony:

ctx := context.Background()

origin := "http://localhost:5000"
storage := webauthn.NewInMemoryCredentialStorage()
relyingParty := webauthn.NewRelyingParty(origin, storage)

// authentication assumes an existing public key, so set it
_ = storage.SetCredential(context.Background(), &webauthn.Credential{
    ID: []byte{
        0xed, 0xc5, 0x97, 0xe5, 0x51, 0xb5, 0x1f, 0xb2,
        0x60, 0x04, 0x05, 0x6d, 0xc5, 0xfd, 0xef, 0x69,
        0x4d, 0xd1, 0xc6, 0xfc, 0xa4, 0xb5, 0x2c, 0x84,
        0xa4, 0xbc, 0x5c, 0x0a, 0xae, 0x8b, 0x6a, 0xa5,
        0x98, 0xdd, 0x65, 0x75, 0x61, 0x67, 0x0a, 0xbd,
        0xa8, 0xc3, 0xec, 0xa1, 0xda, 0x1d, 0xd1, 0x28,
        0xa4, 0xd4, 0x22, 0x6d, 0xb0, 0x9b, 0xbd, 0x3a,
        0x41, 0xaa, 0xd1, 0xd7, 0x49, 0x94, 0x67, 0xaa,
    },
    PublicKey: []byte{
        0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21,
        0x58, 0x20, 0x93, 0x9f, 0x98, 0xa3, 0xdd, 0x89,
        0x22, 0xfb, 0xa0, 0xa8, 0x2c, 0xbd, 0xf7, 0xf7,
        0xa3, 0x8b, 0x57, 0xd9, 0x58, 0xf8, 0xc3, 0xa4,
        0xed, 0xc6, 0x64, 0xf7, 0x46, 0x3b, 0xcf, 0xe3,
        0x45, 0x64, 0x22, 0x58, 0x20, 0x31, 0xa3, 0xaf,
        0xa1, 0xda, 0x87, 0x5a, 0x08, 0x4b, 0xd0, 0x3a,
        0xcf, 0x33, 0x3e, 0xf8, 0x40, 0x81, 0x1a, 0x2f,
        0xe4, 0xa1, 0x0b, 0x4a, 0x4b, 0x51, 0xa9, 0xc0,
        0xcb, 0xaf, 0x4b, 0x84, 0xfb,
    },
})

var options webauthn.PublicKeyCredentialRequestOptions
_ = json.Unmarshal([]byte(`
    {
      "allowCredentials": [
        {
          "type": "public-key",
          "id": "7cWX5VG1H7JgBAVtxf3vaU3RxvyktSyEpLxcCq6LaqWY3WV1YWcKvajD7KHaHdEopNQibbCbvTpBqtHXSZRnqg"
        }
      ],
      "challenge": "dGVzdC1jaGFsbGVuZ2U",
      "timeout": 15000
    }
`), &options)
var response webauthn.PublicKeyAssertionCredential
_ = json.Unmarshal([]byte(`
    {
      "id": "7cWX5VG1H7JgBAVtxf3vaU3RxvyktSyEpLxcCq6LaqWY3WV1YWcKvajD7KHaHdEopNQibbCbvTpBqtHXSZRnqg",
      "type": "public-key",
      "rawId": "7cWX5VG1H7JgBAVtxf3vaU3RxvyktSyEpLxcCq6LaqWY3WV1YWcKvajD7KHaHdEopNQibbCbvTpBqtHXSZRnqg",
      "response": {
        "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiZEdWemRDMWphR0ZzYkdWdVoyVSIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6NTAwMCIsImNyb3NzT3JpZ2luIjpmYWxzZX0",
        "authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MBAAAAAQ",
        "signature": "MEYCIQCqBbzRvp3ZmvseoMnrevFt0HNhvIh0idFdjREw7kmv_AIhAPFPTNL0lnAsgCmemU4BReqSBPYKAw5uEKfmYI4rp9Lf"
      }
    }
`), &response)

credential, err := relyingParty.VerifyAuthenticationCeremony(ctx, &options, &response)

Demo apps

Documentation

Overview

Package webauthn contains types and functions for implementing the server-side component of a Web Authentication Relying Party.

Index

Examples

Constants

View Source
const (
	// AttestationTypeBasic indicates the authenticator’s attestation key pair is specific to an authenticator "model",
	// i.e., a "batch" of authenticators. Thus, authenticators of the same, or similar, model often share the same
	// attestation key pair.
	AttestationTypeBasic = "Basic"
	// AttestationTypeSelf (also known as surrogate basic attestation) indicates the Authenticator does not have any
	// specific attestation key pair. Instead it uses the credential private key to create the attestation signature.
	// Authenticators without meaningful protection measures for an attestation private key typically use this
	// attestation type.
	AttestationTypeSelf = "Self"
	// AttestationTypeAttestationCA indicates an authenticator is based on a Trusted Platform Module (TPM) and holds an
	// authenticator-specific "endorsement key" (EK). This key is used to securely communicate with a trusted third
	// party, the Attestation CA (formerly known as a "Privacy CA"). The authenticator can generate multiple
	// attestation identity key pairs (AIK) and requests an Attestation CA to issue an AIK certificate for each. Using
	// this approach, such an authenticator can limit the exposure of the EK (which is a global correlation handle) to
	// Attestation CA(s). AIKs can be requested for each authenticator-generated public key credential individually,
	// and conveyed to Relying Parties as attestation certificates.
	AttestationTypeAttestationCA = "AttCA"
	// AttestationTypeAnonymizationCA indicates the authenticator uses an Anonymization CA which dynamically generates
	// per-credential attestation certificates such that the attestation statements presented to Relying Parties do
	// not provide uniquely identifiable information, e.g., that might be used for tracking purposes.
	AttestationTypeAnonymizationCA = "AnonCA"
	// AttestationTypeNone indicates no attestation information is available.
	AttestationTypeNone = "None"
	// AttestationTypeUnknown indicates the attestation type is not known.
	AttestationTypeUnknown = "Unknown"
)

Attestation types from https://www.w3.org/TR/webauthn-2/#sctn-attestation-types

View Source
const AAGUIDSize = fido.AAGUIDSize

AAGUIDSize is the number of bytes of an AAGUID in the AttestedCredentialData.

View Source
const AuthenticatorFlagsSize = 1

AuthenticatorFlagsSize is the number of bytes in the AuthenticatorFlags.

View Source
const RPIDHashSize = sha256.Size

RPIDHashSize is the number of bytes in a SHA256 Hash of the RP ID.

Variables

View Source
var (
	// ErrInvalidAttestationStatement indicates that an attestation statement is invalid.
	ErrInvalidAttestationStatement = errors.New("invalid attestation statement")
	// ErrInvalidCertificate indicates that an attestation statement has an invalid x5c certificate.
	ErrInvalidCertificate = errors.New("invalid certificate")
	// ErrInvalidCertInfo indicates that an attestation statement has an invalid certInfo field.
	ErrInvalidCertInfo = errors.New("invalid certInfo")
	// ErrInvalidPubArea indicates that an attestation statement has an invalid pubArea field.
	ErrInvalidPubArea = errors.New("invalid pubArea")
	// ErrMissingCertificate indicates that an attestation statement is missing an x5c certificate.
	ErrMissingCertificate = errors.New("missing certificate")
	// ErrMissingCertInfo indicates that an attestation statement is missing the certInfo field.
	ErrMissingCertInfo = errors.New("missing certInfo")
	// ErrMissingPubArea indicates that an attestation statement is missing a pubArea field.
	ErrMissingPubArea = errors.New("missing pubArea")
)
View Source
var (
	// ErrCredentialNotFound is the error used to indicate a credential wasn't found.
	ErrCredentialNotFound = errors.New("credential not found")
	// ErrCredentialRegisteredToDifferentUser is the error used to indicate a credential is being used by another user.
	ErrCredentialRegisteredToDifferentUser = errors.New("credential registered to another user")
	// ErrInvalidRPIDHash is the error used to indicate an rp id hash is invalid.
	ErrInvalidRPIDHash = errors.New("invalid rp id hash")
)

AllAttestationFormats are all the attestation formats.

AllAttestationTypes are all the known attestation types.

View Source
var AppleCertPool = x509.NewCertPool()

AppleCertPool is the x509 certificate pool used to verify apple attestation.

View Source
var AppleWebAuthnRootCAPEM []byte

AppleWebAuthnRootCAPEM is the Apple WebAuthn Root CA taken from: https://www.apple.com/certificateauthority/Apple_WebAuthn_Root_CA.pem

View Source
var ErrInvalidAttestationObject = errors.New("invalid attestation object")

ErrInvalidAttestationObject indicates an invalid attestation object.

View Source
var ErrInvalidAttestedCredentialData = errors.New("invalid attested credential data")

ErrInvalidAttestedCredentialData indicates the attested credential data is invalid.

View Source
var ErrInvalidAuthenticatorData = errors.New("invalid authenticator data")

ErrInvalidAuthenticatorData indicates the authenticator data is invalid.

Functions

This section is empty.

Types

type AAGUID

type AAGUID = fido.AAGUID

AAGUID is the Authenticator Attestation GUID.

type AttestationConveyancePreference

type AttestationConveyancePreference string

AttestationConveyancePreference indicates what the authenticator should provide for attestation.

const (
	// AttestationConveyanceNone indicates that the Relying Party is not interested in authenticator attestation. For
	// example, in order to potentially avoid having to obtain user consent to relay identifying information to the
	// Relying Party, or to save a roundtrip to an Attestation CA or Anonymization CA. This is the default value.
	AttestationConveyanceNone AttestationConveyancePreference = "none"
	// AttestationConveyanceIndirect indicates that the Relying Party prefers an attestation conveyance yielding
	// verifiable attestation statements, but allows the client to decide how to obtain such attestation statements.
	// The client MAY replace the authenticator-generated attestation statements with attestation statements generated
	// by an Anonymization CA, in order to protect the user’s privacy, or to assist Relying Parties with attestation
	// verification in a heterogeneous ecosystem.
	AttestationConveyanceIndirect AttestationConveyancePreference = "indirect"
	// AttestationConveyanceDirect indicates that the Relying Party wants to receive the attestation statement as
	// generated by the authenticator.
	AttestationConveyanceDirect AttestationConveyancePreference = "direct"
	// AttestationConveyanceEnterprise indicates that the Relying Party wants to receive an attestation statement that
	// may include uniquely identifying information. This is intended for controlled deployments within an enterprise
	// where the organization wishes to tie registrations to specific authenticators. User agents MUST NOT provide such
	// an attestation unless the user agent or authenticator configuration permits it for the requested RP ID.
	//
	// If permitted, the user agent SHOULD signal to the authenticator (at invocation time) that enterprise attestation
	// is requested, and convey the resulting AAGUID and attestation statement, unaltered, to the Relying Party.
	AttestationConveyanceEnterprise AttestationConveyancePreference = "enterprise"
)

type AttestationFormat

type AttestationFormat string

AttestationFormat is the attestation format.

const (
	AttestationFormatAndroidKey       AttestationFormat = "android-key"
	AttestationFormatAndroidSafetyNet AttestationFormat = "android-safetynet"
	AttestationFormatApple            AttestationFormat = "apple"
	AttestationFormatFIDOU2F          AttestationFormat = "fido-u2f"
	AttestationFormatNone             AttestationFormat = "none"
	AttestationFormatPacked           AttestationFormat = "packed"
	AttestationFormatTPM              AttestationFormat = "tpm"
)

Attestation formats from https://www.w3.org/TR/webauthn-2/#sctn-defined-attestation-formats

type AttestationObject

type AttestationObject struct {
	// The AuthData encodes contextual bindings made by the authenticator. These bindings are
	// controlled by the authenticator itself, and derive their trust from the WebAuthn Relying Party's assessment
	// of the security properties of the authenticator.
	AuthData []byte `json:"authData"`
	// The Format is the manner in which the signature is represented and the various contextual bindings are
	// incorporated into the attestation statement by the authenticator.
	Format AttestationFormat `json:"fmt"`
	// The Statement is a signed data object, containing statements about a public key credential itself and
	// the authenticator that created it.
	Statement AttestationStatement `json:"attStmt,omitempty"`
}

An AttestationObject conveys authenticator data and an attestation statement.

func UnmarshalAttestationObject

func UnmarshalAttestationObject(raw []byte) (attestationObject *AttestationObject, remaining []byte, err error)

UnmarshalAttestationObject unmarshals an attestation object from a slice of bytes. It expects a CBOR-encoded map.

func (*AttestationObject) UnmarshalAuthenticatorData

func (attestationObject *AttestationObject) UnmarshalAuthenticatorData() (*AuthenticatorData, error)

UnmarshalAuthenticatorData unmarshals the authenticator data.

type AttestationStatement

type AttestationStatement map[string]interface{}

AttestationStatement is a map of data stored in an AttestationObject according to one of the pre-defined attestation statement formats.

func (AttestationStatement) GetAlgorithm

func (attestationStatement AttestationStatement) GetAlgorithm() cose.Algorithm

GetAlgorithm gets the "alg" field of the attestation statement. If no field is found, or the field contains invalid data, 0 will be returned.

func (AttestationStatement) GetSignature

func (attestationStatement AttestationStatement) GetSignature() []byte

GetSignature gets the "sig" field of the attestation statement. It returns nil if no field is found, or the field does not contain a byte slice.

func (AttestationStatement) UnmarshalCertInfo

func (attestationStatement AttestationStatement) UnmarshalCertInfo() (*tpm.AttestationData, error)

UnmarshalCertInfo unmarshals the TPM certInfo from an attestation statement.

func (AttestationStatement) UnmarshalCertificates

func (attestationStatement AttestationStatement) UnmarshalCertificates() ([]*x509.Certificate, error)

UnmarshalCertificates unmarshals X.509 certificates stored in an x5c key.

func (AttestationStatement) UnmarshalPubArea

func (attestationStatement AttestationStatement) UnmarshalPubArea() (*tpm.Public, error)

UnmarshalPubArea unmarshals the pubArea field from the attestation statement.

type AttestationType

type AttestationType string

AttestationType is the attestation type.

type AttestedCredentialData

type AttestedCredentialData struct {
	// AAGUID is the AAGUID of the authenticator.
	AAGUID AAGUID
	// The CredentialID is a probabilistically-unique byte sequence identifying a public key credential source and
	// its authentication assertions.
	CredentialID []byte
	// CredentialPublicKey is the credential public key encoded in COSE_Key format.
	CredentialPublicKey []byte
}

AttestedCredentialData is added to the authenticator data when generating an attestation object for a given credential.

func UnmarshalAttestedCredentialData

func UnmarshalAttestedCredentialData(raw []byte) (data *AttestedCredentialData, remaining []byte, err error)

UnmarshalAttestedCredentialData unmarshals an AttestedCredentialData according to the data layout described in https://www.w3.org/TR/webauthn-2/#sctn-attested-credential-data:

aaguid: 16 bytes
credentialIdLength: 2 bytes, 16-bit unsigned big-endian = L
credentialId: L bytes
credentialPublicKey: variable, CTAP2 canonical CBOR encoding form

func (*AttestedCredentialData) Marshal

func (attestedCredentialData *AttestedCredentialData) Marshal() ([]byte, error)

Marshal marshals the attested credential data in the format described in Unmarshal.

type AuthenticatorAssertionResponse

type AuthenticatorAssertionResponse struct {
	// ClientDataJSON contains the JSON-compatible serialization of client data passed to the authenticator by the
	// client in order to generate this assertion. The exact JSON serialization MUST be preserved, as the hash of
	// the serialized client data has been computed over it.
	ClientDataJSON []byte `json:"clientDataJSON"`
	// AuthenticatorData contains the authenticator data returned by the authenticator.
	AuthenticatorData []byte `json:"authenticatorData"`
	// Signature contains the raw signature returned from the authenticator.
	Signature []byte `json:"signature"`
	// UserHandle contains the user handle returned from the authenticator, or nil if the authenticator did not
	// return a user handle.
	UserHandle []byte `json:"userHandle"`
}

The AuthenticatorAssertionResponse represents an authenticator's response to a client’s request for generation of a new authentication assertion given the WebAuthn Relying Party's challenge and OPTIONAL list of credentials it is aware of. This response contains a cryptographic signature proving possession of the credential private key, and optionally evidence of user consent to a specific transaction.

func (*AuthenticatorAssertionResponse) GetClientDataJSONHash

func (response *AuthenticatorAssertionResponse) GetClientDataJSONHash() ClientDataJSONHash

GetClientDataJSONHash returns the SHA-256 hash of the clientDataJSON data.

func (AuthenticatorAssertionResponse) MarshalJSON

func (response AuthenticatorAssertionResponse) MarshalJSON() ([]byte, error)

MarshalJSON marshals the AuthenticatorAssertionResponse as JSON.

func (*AuthenticatorAssertionResponse) UnmarshalAuthenticatorData

func (response *AuthenticatorAssertionResponse) UnmarshalAuthenticatorData() (*AuthenticatorData, error)

UnmarshalAuthenticatorData unmarshals the authenticator data.

func (*AuthenticatorAssertionResponse) UnmarshalClientData

func (response *AuthenticatorAssertionResponse) UnmarshalClientData() (*CollectedClientData, error)

UnmarshalClientData unmarshals the client data.

func (*AuthenticatorAssertionResponse) UnmarshalJSON

func (response *AuthenticatorAssertionResponse) UnmarshalJSON(raw []byte) error

UnmarshalJSON unmarshals the AuthenticatorAssertionResponse from JSON.

type AuthenticatorAttachment

type AuthenticatorAttachment string

AuthenticatorAttachment indicates what kind of authenticator should be used.

const (
	// AuthenticatorAttachmentPlatform indicates platform attachment.
	AuthenticatorAttachmentPlatform AuthenticatorAttachment = "platform"
	// AuthenticatorAttachmentCrossPlatform indicates cross-platform attachment.
	AuthenticatorAttachmentCrossPlatform AuthenticatorAttachment = "cross-platform"
)

type AuthenticatorAttestationResponse

type AuthenticatorAttestationResponse struct {
	// ClientDataJSON contains the JSON-compatible serialization of client data passed to the authenticator by the
	// client in order to generate this credential. The exact JSON serialization MUST be preserved, as the hash of
	// the serialized client data has been computed over it.
	ClientDataJSON []byte `json:"clientDataJSON"`
	// AttestationObject contains an attestation object, which is opaque to, and cryptographically protected
	// against tampering by, the client. The attestation object contains both authenticator data and an attestation
	// statement. The former contains the AAGUID, a unique credential ID, and the credential public key. The
	// contents of the attestation statement are determined by the attestation statement format used by the
	// authenticator. It also contains any additional information that the Relying Party's server requires to
	// validate the attestation statement, as well as to decode and validate the authenticator data along with the
	// JSON-compatible serialization of client data.
	AttestationObject []byte `json:"attestationObject"`
}

The AuthenticatorAttestationResponse interface represents the authenticator's response to a client's request for the creation of a new public key credential. It contains information about the new credential that can be used to identify it for later use, and metadata that can be used by the WebAuthn Relying Party to assess the characteristics of the credential during registration.

func (*AuthenticatorAttestationResponse) GetClientDataJSONHash

func (response *AuthenticatorAttestationResponse) GetClientDataJSONHash() ClientDataJSONHash

GetClientDataJSONHash returns the SHA-256 hash of the clientDataJSON data.

func (AuthenticatorAttestationResponse) MarshalJSON

func (response AuthenticatorAttestationResponse) MarshalJSON() ([]byte, error)

MarshalJSON marshals the AuthenticatorAttestationResponse as JSON.

func (*AuthenticatorAttestationResponse) UnmarshalAttestationObject

func (response *AuthenticatorAttestationResponse) UnmarshalAttestationObject() (*AttestationObject, error)

UnmarshalAttestationObject unmarshals the attestation object.

func (*AuthenticatorAttestationResponse) UnmarshalClientData

func (response *AuthenticatorAttestationResponse) UnmarshalClientData() (*CollectedClientData, error)

UnmarshalClientData unmarshals the client data.

func (*AuthenticatorAttestationResponse) UnmarshalJSON

func (response *AuthenticatorAttestationResponse) UnmarshalJSON(raw []byte) error

UnmarshalJSON unmarshals the AuthenticatorAttestationResponse as JSON.

type AuthenticatorData

type AuthenticatorData struct {
	// RPIDHash is the SHA-256 hash of the RP ID the credential is scoped to.
	RPIDHash RPIDHash
	// Flags are the authenticator flags.
	Flags AuthenticatorFlags
	// SignCount is the signature counter, 32-bit unsigned big-endian integer.
	SignCount uint32
	// AttestedCredentialData is the attested credential data (if present).
	AttestedCredentialData *AttestedCredentialData
	// Extensions are extension-defined authenticator data. This is a CBOR map with extension identifiers as keys,
	// and authenticator extension outputs as values.
	Extensions []byte
}

The AuthenticatorData encodes contextual bindings made by the authenticator. These bindings are controlled by the authenticator itself, and derive their trust from the WebAuthn Relying Party's assessment of the security properties of the authenticator.

func UnmarshalAuthenticatorData

func UnmarshalAuthenticatorData(raw []byte) (data *AuthenticatorData, remaining []byte, err error)

UnmarshalAuthenticatorData unmarshals AuthenticatorData according to the data layout described in: https://www.w3.org/TR/webauthn-2/#authenticator-data.

rpIdHash: 32 bytes
flags: 1 byte, bitmask
signCount: 4 bytes, 32-bit unsigned big-endian integer
attestedCredentialData: variable
extensions: variable, cbor map

func (*AuthenticatorData) Marshal

func (authenticatorData *AuthenticatorData) Marshal() ([]byte, error)

Marshal marshals authenticator data according to the format defined in Unmarshal.

type AuthenticatorFlags

type AuthenticatorFlags byte

AuthenticatorFlags are flags that indicate information about AuthenticatorData.

func (AuthenticatorFlags) AttestedCredentialDataIncluded

func (flags AuthenticatorFlags) AttestedCredentialDataIncluded() bool

AttestedCredentialDataIncluded returns true if the AuthenticatorData has attested credential data.

func (AuthenticatorFlags) ExtensionDataIncluded

func (flags AuthenticatorFlags) ExtensionDataIncluded() bool

ExtensionDataIncluded returns true if the AuthenticatorData has extension data.

func (AuthenticatorFlags) UserPresent

func (flags AuthenticatorFlags) UserPresent() bool

UserPresent returns true if the user is "present".

func (AuthenticatorFlags) UserVerified

func (flags AuthenticatorFlags) UserVerified() bool

UserVerified returns true if the user is "verified".

type AuthenticatorSelectionCriteria

type AuthenticatorSelectionCriteria struct {
	// AuthenticatorAttachment, if present, filters eligible authenticators. The value SHOULD be a member of
	// AuthenticatorAttachment but client platforms MUST ignore unknown values, treating an unknown value as if the
	// member does not exist.
	AuthenticatorAttachment AuthenticatorAttachment `json:"authenticatorAttachment,omitempty"`
	// ResidentKey specifies the extent to which the Relying Party desires to create a client-side discoverable
	// credential. For historical reasons the naming retains the deprecated “resident” terminology. The value
	// SHOULD be a member of ResidentKeyRequirement but client platforms MUST ignore unknown values, treating an
	// unknown value as if the member does not exist. If no value is given then the effective value is required if
	// requireResidentKey is true or discouraged if it is false or absent.
	ResidentKey ResidentKeyType `json:"residentKey,omitempty"`
	// RequireResidentKey is retained for backwards compatibility with WebAuthn Level 1 and, for historical reasons,
	// its naming retains the deprecated “resident” terminology for discoverable credentials. Relying Parties SHOULD
	// set it to true if, and only if, residentKey is set to required.
	RequireResidentKey bool `json:"requireResidentKey"`
	// UserVerification describes the Relying Party's requirements regarding user verification for the create()
	// operation. Eligible authenticators are filtered to only those capable of satisfying this requirement. The
	// value SHOULD be a member of UserVerificationRequirement but client platforms MUST ignore unknown values,
	// treating an unknown value as if the member does not exist.
	UserVerification UserVerificationRequirement `json:"userVerification,omitempty"`
}

AuthenticatorSelectionCriteria specifies requirements regarding authenticator attributes.

type AuthenticatorTransport

type AuthenticatorTransport string

AuthenticatorTransport indicates how the authenticator is contacted.

const (
	// AuthenticatorTransportUSB indicates the respective authenticator can be contacted over removable USB.
	AuthenticatorTransportUSB AuthenticatorTransport = "usb"
	// AuthenticatorTransportNFC indicates the respective authenticator can be contacted over Near Field Communication
	// (NFC).
	AuthenticatorTransportNFC AuthenticatorTransport = "nfc"
	// AuthenticatorTransportBLE indicates the respective authenticator can be contacted over Bluetooth Smart
	// (Bluetooth Low Energy / BLE).
	AuthenticatorTransportBLE AuthenticatorTransport = "ble"
	// AuthenticatorTransportInternal indicates the respective authenticator is contacted using a client
	// device-specific transport, i.e., it is a platform authenticator. These authenticators are not removable from the
	// client device.
	AuthenticatorTransportInternal AuthenticatorTransport = "internal"
)

type ClientDataJSONHash

type ClientDataJSONHash = [sha256.Size]byte

ClientDataJSONHash represents the SHA-256 hash of the clientDataJSON data.

type ClientDataType

type ClientDataType string

ClientDataType distinguishes between creating new credentials and using an existing credential.

const (
	// ClientDataTypeCreate is used when creating new credentials.
	ClientDataTypeCreate ClientDataType = "webauthn.create"
	// ClientDataTypeGet is used when getting an assertion on an existing credential.
	ClientDataTypeGet ClientDataType = "webauthn.get"
)

type CollectedClientData

type CollectedClientData struct {
	// Type contains the string "webauthn.create" when creating new credentials, and "webauthn.get" when
	// getting an assertion from an existing credential. The purpose of this member is to prevent certain types of
	// signature confusion attacks (where an attacker substitutes one legitimate signature for another).
	Type ClientDataType `json:"type"`
	// Challenge contains the base64url encoding of the challenge provided by the Relying Party.
	Challenge string `json:"challenge"`
	// Origin contains the fully qualified origin of the requester, as provided to the authenticator by the
	// client.
	Origin string `json:"origin"`
	// CrossOrigin contains the inverse of the sameOriginWithAncestors argument value that was passed into the
	// internal method.
	CrossOrigin bool `json:"crossOrigin"`
	// TokenBinding contains information about the state of the Token Binding protocol used when communicating with
	// the Relying Party. Its absence indicates that the client doesn’t support token binding.
	TokenBinding *TokenBinding `json:"tokenBinding"`
}

CollectedClientData represents the contextual bindings of both the WebAuthn Relying Party and the client.

type Credential

type Credential struct {
	ID        []byte `json:"id"`
	OwnerID   []byte `json:"ownerId"`
	PublicKey []byte `json:"publicKey"`
}

A Credential is the public key and user id stored by the relying party to identify a private key bound to an authenticator.

type CredentialStorage

type CredentialStorage interface {
	// GetCredential retrieves a credential from storage. If no credential is found for the
	// given ID return ErrCredentialNotFound.
	GetCredential(ctx context.Context, credentialID []byte) (*Credential, error)
	// SetCredential saves a credential to storage.
	SetCredential(ctx context.Context, credential *Credential) error
}

CredentialStorage retrieves and saves credentials.

type InMemoryCredentialStorage

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

An InMemoryCredentialStorage stores credential in an in-memory map.

func NewInMemoryCredentialStorage

func NewInMemoryCredentialStorage() *InMemoryCredentialStorage

NewInMemoryCredentialStorage creates a new InMemoryCredentialStorage.

func (*InMemoryCredentialStorage) GetCredential

func (storage *InMemoryCredentialStorage) GetCredential(_ context.Context, credentialID []byte) (*Credential, error)

GetCredential gets the credential from the map.

func (*InMemoryCredentialStorage) SetCredential

func (storage *InMemoryCredentialStorage) SetCredential(_ context.Context, credential *Credential) error

SetCredential sets the credential in the map.

type PublicKeyAssertionCredential

type PublicKeyAssertionCredential struct {
	// ID is the base64url encoding of the RawID.
	ID string `json:"id"`
	// Type is "public-key".
	Type PublicKeyCredentialType `json:"type"`
	// RawID is the credential ID, chosen by the authenticator. The credential ID is used to look up credentials for
	// use, and is therefore expected to be globally unique with high probability across all credentials of the same
	// type, across all authenticators.
	RawID []byte `json:"rawId"`
	// Response contains the authenticator's response to the client's request to generate an authentication
	// assertion.
	Response AuthenticatorAssertionResponse `json:"response"`
	// ClientExtensionResults is a map containing extension identifier → client extension output entries produced by
	// the extension’s client extension processing.
	ClientExtensionResults map[string]interface{} `json:"clientExtensionResults,omitempty"`
}

PublicKeyAssertionCredential contains the attributes when a new assertion is requested.

func (PublicKeyAssertionCredential) MarshalJSON

func (credential PublicKeyAssertionCredential) MarshalJSON() ([]byte, error)

MarshalJSON marshals the PublicKeyAssertionCredential as JSON.

func (*PublicKeyAssertionCredential) UnmarshalJSON

func (credential *PublicKeyAssertionCredential) UnmarshalJSON(raw []byte) error

UnmarshalJSON unmarshals the PublicKeyAssertionCredential from JSON.

type PublicKeyCreationCredential

type PublicKeyCreationCredential struct {
	// ID is the base64url encoding of the RawID.
	ID string `json:"id"`
	// Type is "public-key".
	Type PublicKeyCredentialType `json:"type"`
	// RawID is the credential ID, chosen by the authenticator. The credential ID is used to look up credentials for
	// use, and is therefore expected to be globally unique with high probability across all credentials of the same
	// type, across all authenticators.
	RawID []byte `json:"rawId"`
	// Response contains the authenticator's response to the client's request to create a public key credential.
	Response AuthenticatorAttestationResponse `json:"response"`
	// ClientExtensionResults is a map containing extension identifier → client extension output entries produced by
	// the extension’s client extension processing.
	ClientExtensionResults map[string]interface{} `json:"clientExtensionResults,omitempty"`
}

PublicKeyCreationCredential contains the attributes when a new credential is created.

func (PublicKeyCreationCredential) MarshalJSON

func (credential PublicKeyCreationCredential) MarshalJSON() ([]byte, error)

MarshalJSON marshals the PublicKeyCreationCredential as JSON.

func (*PublicKeyCreationCredential) UnmarshalJSON

func (credential *PublicKeyCreationCredential) UnmarshalJSON(raw []byte) error

UnmarshalJSON unmarshals the PublicKeyCreationCredential as JSON.

type PublicKeyCredentialCreationOptions

type PublicKeyCredentialCreationOptions struct {
	// This member contains data about the Relying Party responsible for the request.
	//
	// Its value’s name member is REQUIRED.
	//
	// Its value’s id member specifies the RP ID the credential should be scoped to. If omitted, its value will be
	// the CredentialsContainer object’s relevant settings object's origin's effective domain.
	RP PublicKeyCredentialRPEntity `json:"rp"`
	// This member contains data about the user account for which the Relying Party is requesting attestation.
	//
	// Its value’s name, displayName and id members are REQUIRED.
	User PublicKeyCredentialUserEntity `json:"user"`
	// This member contains a challenge intended to be used for generating the newly created credential’s
	// attestation object.
	Challenge []byte `json:"challenge"`
	// This member contains information about the desired properties of the credential to be created. The sequence
	// is ordered from most preferred to least preferred. The client makes a best-effort to create the most
	// preferred credential that it can.
	PubKeyCredParams []PublicKeyCredentialParameters `json:"pubKeyCredParams"`
	// This member specifies a time, in milliseconds, that the caller is willing to wait for the call to complete.
	// This is treated as a hint, and MAY be overridden by the client.
	Timeout time.Duration `json:"timeout,omitempty"`
	// This member is intended for use by Relying Parties that wish to limit the creation of multiple credentials
	// for the same account on a single authenticator. The client is requested to return an error if the new
	// credential would be created on an authenticator that also contains one of the credentials enumerated in this
	// parameter.
	ExcludeCredentials []PublicKeyCredentialDescriptor `json:"excludeCredentials,omitempty"`
	// This member is intended for use by Relying Parties that wish to select the appropriate authenticators to
	// participate in the create() operation.
	AuthenticatorSelection *AuthenticatorSelectionCriteria `json:"authenticatorSelection,omitempty"`
	// This member is intended for use by Relying Parties that wish to express their preference for attestation
	// conveyance. Its values SHOULD be members of AttestationConveyancePreference. Client platforms MUST ignore
	// unknown values, treating an unknown value as if the member does not exist. Its default value is "none".
	Attestation AttestationConveyancePreference `json:"attestation,omitempty"`
	// This member contains additional parameters requesting additional processing by the client and authenticator.
	// For example, the caller may request that only authenticators with certain capabilities be used to create the
	// credential, or that particular information be returned in the attestation object.
	Extensions map[string]interface{} `json:"extensions,omitempty"`
}

The PublicKeyCredentialCreationOptions supplies create() with the data it needs to generate a new credential.

func (*PublicKeyCredentialCreationOptions) AllowsAlgorithm

func (creationOptions *PublicKeyCredentialCreationOptions) AllowsAlgorithm(algorithm cose.Algorithm) bool

AllowsAlgorithm returns true if the creation options allow the given algorithm.

func (PublicKeyCredentialCreationOptions) MarshalJSON

func (creationOptions PublicKeyCredentialCreationOptions) MarshalJSON() ([]byte, error)

MarshalJSON marshals the PublicKeyCredentialCreationOptions as JSON.

func (*PublicKeyCredentialCreationOptions) UnmarshalJSON

func (creationOptions *PublicKeyCredentialCreationOptions) UnmarshalJSON(raw []byte) error

UnmarshalJSON unmarshals the PublicKeyCredentialCreationOptions as JSON.

type PublicKeyCredentialDescriptor

type PublicKeyCredentialDescriptor struct {
	// This member contains the type of the public key credential the caller is referring to. The value SHOULD be a
	// member of PublicKeyCredentialType but client platforms MUST ignore any PublicKeyCredentialDescriptor with an
	// unknown type.
	Type PublicKeyCredentialType `json:"type"`
	// This member contains the credential ID of the public key credential the caller is referring to.
	ID []byte `json:"id"`
	// This OPTIONAL member contains a hint as to how the client might communicate with the managing authenticator
	// of the public key credential the caller is referring to. The values SHOULD be members of
	// AuthenticatorTransport but client platforms MUST ignore unknown values.
	Transports []AuthenticatorTransport `json:"transports,omitempty"`
}

The PublicKeyCredentialDescriptor contains the attributes that are specified by a caller when referring to a public key credential as an input parameter to the create() or get() methods.

func (PublicKeyCredentialDescriptor) MarshalJSON

func (descriptor PublicKeyCredentialDescriptor) MarshalJSON() ([]byte, error)

MarshalJSON marshals the PublicKeyCredentialDescriptor as JSON.

func (*PublicKeyCredentialDescriptor) UnmarshalJSON

func (descriptor *PublicKeyCredentialDescriptor) UnmarshalJSON(raw []byte) error

UnmarshalJSON unmarshals the PublicKeyCredentialDescriptor as JSON.

type PublicKeyCredentialParameters

type PublicKeyCredentialParameters struct {
	// This member specifies the type of credential to be created.
	Type PublicKeyCredentialType `json:"type"`
	// This member specifies the cryptographic signature algorithm with which the newly generated credential will
	// be used, and thus also the type of asymmetric key pair to be generated, e.g., RSA or Elliptic Curve.
	COSEAlgorithmIdentifier cose.Algorithm `json:"alg"`
}

PublicKeyCredentialParameters is used to supply additional parameters when creating a new credential.

type PublicKeyCredentialRPEntity

type PublicKeyCredentialRPEntity struct {
	// A unique identifier for the Relying Party entity, which sets the RP ID.
	ID string `json:"id,omitempty"`
	// A human-palatable identifier for the Relying Party, intended only for display.
	Name string `json:"name"`
}

The PublicKeyCredentialRPEntity is used to supply additional Relying Party attributes when creating a new credential.

type PublicKeyCredentialRequestOptions

type PublicKeyCredentialRequestOptions struct {
	// This member represents a challenge that the selected authenticator signs, along with other data, when
	// producing an authentication assertion.
	Challenge []byte `json:"challenge"`
	// This OPTIONAL member specifies a time, in milliseconds, that the caller is willing to wait for the call to
	// complete. The value is treated as a hint, and MAY be overridden by the client.
	Timeout time.Duration `json:"timeout,omitempty"`
	// This OPTIONAL member specifies the relying party identifier claimed by the caller. If omitted, its
	// value will be the CredentialsContainer object’s relevant settings object's origin's effective domain.
	RPID string `json:"rpId,omitempty"`
	// This OPTIONAL member contains a list of PublicKeyCredentialDescriptor objects representing public key
	// credentials acceptable to the caller, in descending order of the caller’s preference (the first item in the
	// list is the most preferred credential, and so on down the list).
	AllowCredentials []PublicKeyCredentialDescriptor `json:"allowCredentials,omitempty"`
	// This OPTIONAL member describes the Relying Party's requirements regarding user verification for the get()
	// operation. The value SHOULD be a member of UserVerificationRequirement but client platforms MUST ignore
	// unknown values, treating an unknown value as if the member does not exist. Eligible authenticators are
	// filtered to only those capable of satisfying this requirement.
	UserVerification UserVerificationRequirement `json:"userVerification,omitempty"`
	// This OPTIONAL member contains additional parameters requesting additional processing by the client and
	// authenticator. For example, if transaction confirmation is sought from the user, then the prompt string
	// might be included as an extension.
	Extensions map[string]interface{} `json:"extensions,omitempty"`
}

The PublicKeyCredentialRequestOptions supplies get() with the data it needs to generate an assertion. Its challenge member MUST be present, while its other members are OPTIONAL.

func (PublicKeyCredentialRequestOptions) MarshalJSON

func (requestOptions PublicKeyCredentialRequestOptions) MarshalJSON() ([]byte, error)

MarshalJSON marshals the PublicKeyCredentialRequestOptions as JSON.

func (*PublicKeyCredentialRequestOptions) UnmarshalJSON

func (requestOptions *PublicKeyCredentialRequestOptions) UnmarshalJSON(raw []byte) error

UnmarshalJSON unmarshals the PublicKeyCredentialRequestOptions as JSON.

type PublicKeyCredentialType

type PublicKeyCredentialType string

PublicKeyCredentialType indicates the type of credential. (only public-key is currently supported)

const (
	// PublicKeyCredentialTypePublicKey represents a public key credential.
	PublicKeyCredentialTypePublicKey PublicKeyCredentialType = "public-key"
)

type PublicKeyCredentialUserEntity

type PublicKeyCredentialUserEntity struct {
	// The user handle of the user account entity. A user handle is an opaque byte sequence with a maximum size of
	// 64 bytes, and is not meant to be displayed to the user.
	//
	// To ensure secure operation, authentication and authorization decisions MUST be made on the basis of this id
	// member, not the displayName nor name members.
	//
	// The user handle MUST NOT contain personally identifying information about the user, such as a username or
	// e-mail address.
	ID []byte `json:"id"`
	// A human-palatable name for the user account, intended only for display. For example, "Alex Müller" or
	// "田中倫". The Relying Party SHOULD let the user choose this, and SHOULD NOT restrict the choice more than
	// necessary.
	//
	// Authenticators MUST accept and store a 64-byte minimum length for a displayName member’s value.
	// Authenticators MAY truncate a displayName member’s value so that it fits within 64 bytes.
	DisplayName string `json:"displayName"`
	// A human-palatable identifier for a user account.
	Name string `json:"name"`
}

The PublicKeyCredentialUserEntity is used to supply additional user account attributes when creating a new credential.

func (PublicKeyCredentialUserEntity) MarshalJSON

func (user PublicKeyCredentialUserEntity) MarshalJSON() ([]byte, error)

MarshalJSON marshals the PublicKeyCredentialUserEntity as JSON.

func (*PublicKeyCredentialUserEntity) UnmarshalJSON

func (user *PublicKeyCredentialUserEntity) UnmarshalJSON(raw []byte) error

UnmarshalJSON unmarshals the PublicKeyCredentialUserEntity from JSON.

type RPIDHash

type RPIDHash [RPIDHashSize]byte

RPIDHash is the SHA-256 hash of the RP ID.

func (RPIDHash) MarshalJSON

func (rpidhash RPIDHash) MarshalJSON() ([]byte, error)

MarshalJSON marshals the RPIDHash for JSON.

type RelyingParty

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

A RelyingParty is the entity that utilizes the Web Authentication API to register and authenticate users.

func NewRelyingParty

func NewRelyingParty(originURL string, credentialStorage CredentialStorage) *RelyingParty

NewRelyingParty creates a new RelyingParty.

func (*RelyingParty) VerifyAuthenticationCeremony

func (rp *RelyingParty) VerifyAuthenticationCeremony(
	ctx context.Context,
	options *PublicKeyCredentialRequestOptions,
	credential *PublicKeyAssertionCredential,
	_ ...VerifyOption,
) (*Credential, error)

VerifyAuthenticationCeremony verifies an authentication ceremony by performing steps 4-22 of https://www.w3.org/TR/webauthn-2/#sctn-verifying-assertion.

Example
package main

import (
	"context"
	"encoding/json"
	"fmt"

	"github.com/pomerium/webauthn"
)

func main() {
	ctx := context.Background()

	origin := "http://localhost:5000"
	storage := webauthn.NewInMemoryCredentialStorage()
	relyingParty := webauthn.NewRelyingParty(origin, storage)

	// authentication assumes an existing public key, so set it
	_ = storage.SetCredential(context.Background(), &webauthn.Credential{
		ID: []byte{
			0xed, 0xc5, 0x97, 0xe5, 0x51, 0xb5, 0x1f, 0xb2,
			0x60, 0x04, 0x05, 0x6d, 0xc5, 0xfd, 0xef, 0x69,
			0x4d, 0xd1, 0xc6, 0xfc, 0xa4, 0xb5, 0x2c, 0x84,
			0xa4, 0xbc, 0x5c, 0x0a, 0xae, 0x8b, 0x6a, 0xa5,
			0x98, 0xdd, 0x65, 0x75, 0x61, 0x67, 0x0a, 0xbd,
			0xa8, 0xc3, 0xec, 0xa1, 0xda, 0x1d, 0xd1, 0x28,
			0xa4, 0xd4, 0x22, 0x6d, 0xb0, 0x9b, 0xbd, 0x3a,
			0x41, 0xaa, 0xd1, 0xd7, 0x49, 0x94, 0x67, 0xaa,
		},
		PublicKey: []byte{
			0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21,
			0x58, 0x20, 0x93, 0x9f, 0x98, 0xa3, 0xdd, 0x89,
			0x22, 0xfb, 0xa0, 0xa8, 0x2c, 0xbd, 0xf7, 0xf7,
			0xa3, 0x8b, 0x57, 0xd9, 0x58, 0xf8, 0xc3, 0xa4,
			0xed, 0xc6, 0x64, 0xf7, 0x46, 0x3b, 0xcf, 0xe3,
			0x45, 0x64, 0x22, 0x58, 0x20, 0x31, 0xa3, 0xaf,
			0xa1, 0xda, 0x87, 0x5a, 0x08, 0x4b, 0xd0, 0x3a,
			0xcf, 0x33, 0x3e, 0xf8, 0x40, 0x81, 0x1a, 0x2f,
			0xe4, 0xa1, 0x0b, 0x4a, 0x4b, 0x51, 0xa9, 0xc0,
			0xcb, 0xaf, 0x4b, 0x84, 0xfb,
		},
	})

	var options webauthn.PublicKeyCredentialRequestOptions
	_ = json.Unmarshal([]byte(`
		{
		  "allowCredentials": [
			{
			  "type": "public-key",
			  "id": "7cWX5VG1H7JgBAVtxf3vaU3RxvyktSyEpLxcCq6LaqWY3WV1YWcKvajD7KHaHdEopNQibbCbvTpBqtHXSZRnqg"
			}
		  ],
		  "challenge": "dGVzdC1jaGFsbGVuZ2U",
		  "timeout": 15000
		}
	`), &options)
	var response webauthn.PublicKeyAssertionCredential
	_ = json.Unmarshal([]byte(`
		{
		  "id": "7cWX5VG1H7JgBAVtxf3vaU3RxvyktSyEpLxcCq6LaqWY3WV1YWcKvajD7KHaHdEopNQibbCbvTpBqtHXSZRnqg",
		  "type": "public-key",
		  "rawId": "7cWX5VG1H7JgBAVtxf3vaU3RxvyktSyEpLxcCq6LaqWY3WV1YWcKvajD7KHaHdEopNQibbCbvTpBqtHXSZRnqg",
		  "response": {
			"clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiZEdWemRDMWphR0ZzYkdWdVoyVSIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6NTAwMCIsImNyb3NzT3JpZ2luIjpmYWxzZX0",
			"authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MBAAAAAQ",
			"signature": "MEYCIQCqBbzRvp3ZmvseoMnrevFt0HNhvIh0idFdjREw7kmv_AIhAPFPTNL0lnAsgCmemU4BReqSBPYKAw5uEKfmYI4rp9Lf"
		  }
		}
	`), &response)

	credential, err := relyingParty.VerifyAuthenticationCeremony(ctx, &options, &response)
	if err != nil {
		panic(err)
	}

	bs, _ := json.Marshal(credential)
	fmt.Println(string(bs))
}
Output:

{"id":"7cWX5VG1H7JgBAVtxf3vaU3RxvyktSyEpLxcCq6LaqWY3WV1YWcKvajD7KHaHdEopNQibbCbvTpBqtHXSZRnqg==","ownerId":null,"publicKey":"pQECAyYgASFYIJOfmKPdiSL7oKgsvff3o4tX2Vj4w6TtxmT3RjvP40VkIlggMaOvodqHWghL0DrPMz74QIEaL+ShC0pLUanAy69LhPs="}

func (*RelyingParty) VerifyRegistrationCeremony

func (rp *RelyingParty) VerifyRegistrationCeremony(
	ctx context.Context,
	creationOptions *PublicKeyCredentialCreationOptions,
	credential *PublicKeyCreationCredential,
	verifyOptions ...VerifyOption,
) (*Credential, error)

VerifyRegistrationCeremony verifies a registration ceremony by performing steps 4-24 of https://www.w3.org/TR/webauthn-2/#sctn-registering-a-new-credential.

Example
package main

import (
	"context"
	"encoding/json"
	"fmt"

	"github.com/pomerium/webauthn"
)

func main() {
	ctx := context.Background()

	origin := "http://localhost:5000"
	storage := webauthn.NewInMemoryCredentialStorage()
	relyingParty := webauthn.NewRelyingParty(origin, storage)

	var options webauthn.PublicKeyCredentialCreationOptions
	_ = json.Unmarshal([]byte(`
		{
		  "rp": {
			"name": "Pomerium"
		  },
		  "user": {
			"displayName": "Test User",
			"name": "test-user",
			"id": "dGVzdC11c2Vy"
		  },
		  "pubKeyCredParams": [
			{
			  "type": "public-key",
			  "alg": -257
			},
			{
			  "type": "public-key",
			  "alg": -7
			}
		  ],
		  "authenticatorSelection": {
			"authenticatorAttachment": "cross-platform",
			"requireResidentKey": false
		  },
		  "attestation": "direct",
		  "challenge": "dGVzdC1jaGFsbGVuZ2U",
		  "timeout": 15000
		}
	`), &options)
	var response webauthn.PublicKeyCreationCredential
	_ = json.Unmarshal([]byte(`
		{
		  "id": "BOyUQxjpKJSR2VhsJok4FR8LIoZZ53QnrXxkiw5tzrp0cJuciBsxdIjabLjB6ebQMuKPqmMIPanM28HzGB9sig",
		  "rawId": "BOyUQxjpKJSR2VhsJok4FR8LIoZZ53QnrXxkiw5tzrp0cJuciBsxdIjabLjB6ebQMuKPqmMIPanM28HzGB9sig",
		  "response": {
		    "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiZEdWemRDMWphR0ZzYkdWdVoyVSIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6NTAwMCIsImNyb3NzT3JpZ2luIjpmYWxzZSwib3RoZXJfa2V5c19jYW5fYmVfYWRkZWRfaGVyZSI6ImRvIG5vdCBjb21wYXJlIGNsaWVudERhdGFKU09OIGFnYWluc3QgYSB0ZW1wbGF0ZS4gU2VlIGh0dHBzOi8vZ29vLmdsL3lhYlBleCJ9",
		    "attestationObject": "o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2lnWEgwRgIhAIwctsPvNyXT6gEFJnqWlYqy_GBgNawLRrdZUwy8KpYqAiEAoQ6ct84cs9xyKo3v4c2HBGs1T7wg67oepLeiRa8vUG1jeDVjgVkBXTCCAVkwggEAoAMCAQICAQEwCgYIKoZIzj0EAwIwKDEVMBMGA1UEAxMMU2VjdXJpdHkgS2V5MQ8wDQYDVQQKEwZHb29nbGUwIhgPMjAwMDAxMDEwMDAwMDBaGA8yMDk5MTIzMTIzNTk1OVowKDEVMBMGA1UEAxMMU2VjdXJpdHkgS2V5MQ8wDQYDVQQKEwZHb29nbGUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ_1ZtuIheQTnPrYNbFIME1flmt6RjmX7dUQbpOUwIl4lhN_I6gOiWBaocqrYWJlGVyXN4uYV31iKY73Zw1EjhaoxcwFTATBgsrBgEEAYLlHAIBAQQEAwIEMDAKBggqhkjOPQQDAgNHADBEAiBKHLlAEJFmo0of3IiO6Afg2kn8Rmn0wa4ml4ANfsBW9AIgauaLpiP9LGBRXYS7hq1B-GSzl40V8PR_k2HkZ76RDuxoYXV0aERhdGFYxEmWDeWIDoxodDQXD2R2YFuP5K65ooYyx5lc87qDHZdjQQAAAAAAAAAAAAAAAAAAAAAAAAAAAEAE7JRDGOkolJHZWGwmiTgVHwsihlnndCetfGSLDm3OunRwm5yIGzF0iNpsuMHp5tAy4o-qYwg9qczbwfMYH2yKpQECAyYgASFYID1HLxI1bZD28OItYBsrBNkz8hr_YWX_sIht0GVmMNCcIlggze0LBzzUxMeF3sWcDzsHXr-hxGEQgwjZBjQg2dcdp7Y"
		  }
		}
	`), &response)

	credential, err := relyingParty.VerifyRegistrationCeremony(ctx, &options, &response)
	if err != nil {
		panic(err)
	}

	bs, _ := json.Marshal(credential)
	fmt.Println(string(bs))
}
Output:

{"id":"BOyUQxjpKJSR2VhsJok4FR8LIoZZ53QnrXxkiw5tzrp0cJuciBsxdIjabLjB6ebQMuKPqmMIPanM28HzGB9sig==","ownerId":"dGVzdC11c2Vy","publicKey":"pQECAyYgASFYID1HLxI1bZD28OItYBsrBNkz8hr/YWX/sIht0GVmMNCcIlggze0LBzzUxMeF3sWcDzsHXr+hxGEQgwjZBjQg2dcdp7Y="}

type ResidentKeyType

type ResidentKeyType string

ResidentKeyType is used to indicate various resident key options.

const (
	// ResidentKeyDiscouraged indicates the Relying Party prefers creating a server-side credential, but will accept a
	// client-side discoverable credential.
	ResidentKeyDiscouraged ResidentKeyType = "discouraged"
	// ResidentKeyPreferred indicates the Relying Party strongly prefers creating a client-side discoverable
	// credential, but will accept a server-side credential. For example, user agents SHOULD guide the user through
	// setting up user verification if needed to create a client-side discoverable credential in this case. This takes
	// precedence over the setting of userVerification.
	ResidentKeyPreferred ResidentKeyType = "preferred"
	// ResidentKeyRequired indicates the Relying Party requires a client-side discoverable credential, and is prepared
	// to receive an error if a client-side discoverable credential cannot be created.
	ResidentKeyRequired ResidentKeyType = "required"
)

type TokenBinding

type TokenBinding struct {
	// This member SHOULD be a member of TokenBindingStatus but client platforms MUST ignore unknown values,
	// treating an unknown value as if the tokenBinding member does not exist.
	Status TokenBindingStatus `json:"status"`
	// This member MUST be present if status is present, and MUST be a base64url encoding of the Token Binding ID
	// that was used when communicating with the Relying Party.
	ID string `json:"id"`
}

A TokenBinding is established by a User Agent generating a private-public key pair (possibly within a secure hardware module, such as a Trusted Platform Module) per target server, providing the public key to the server, and proving possession of the corresponding private key.

type TokenBindingStatus

type TokenBindingStatus string

TokenBindingStatus indicates different token binding options.

const (
	// TokenBindingPresent indicates token binding was used when communicating with the Relying Party. In this case,
	// the id member MUST be present.
	TokenBindingPresent TokenBindingStatus = "present"
	// TokenBindingSupported indicates the client supports token binding, but it was not negotiated when
	// communicating with the Relying Party.
	TokenBindingSupported TokenBindingStatus = "supported"
)

type UserVerificationRequirement

type UserVerificationRequirement string

UserVerificationRequirement indicates which type of user verification to use.

const (
	// UserVerificationRequired indicates that the Relying Party requires user verification for the operation and will
	// fail the operation if the response does not have the UV flag set.
	UserVerificationRequired UserVerificationRequirement = "required"
	// UserVerificationPreferred indicates that the Relying Party prefers user verification for the operation if
	// possible, but will not fail the operation if the response does not have the UV flag set.
	UserVerificationPreferred UserVerificationRequirement = "preferred"
	// UserVerificationDiscouraged indicates that the Relying Party does not want user verification employed during the
	// operation (e.g., in the interest of minimizing disruption to the user interaction flow).
	UserVerificationDiscouraged UserVerificationRequirement = "discouraged"
)

type VerifyAttestationStatementResult

type VerifyAttestationStatementResult struct {
	Type       AttestationType
	TrustPaths [][]*x509.Certificate
}

VerifyAttestationStatementResult is the result of running VerifyAttestationStatement.

func VerifyAndroidKeyAttestationStatement

func VerifyAndroidKeyAttestationStatement(
	attestationObject *AttestationObject,
	clientDataJSONHash ClientDataJSONHash,
) (*VerifyAttestationStatementResult, error)

VerifyAndroidKeyAttestationStatement verifies that an AttestationObject's attestation statement is valid according to the android key verification procedure.

func VerifyAndroidSafetyNetAttestationStatement

func VerifyAndroidSafetyNetAttestationStatement(
	attestationObject *AttestationObject,
	clientDataJSONHash ClientDataJSONHash,
) (*VerifyAttestationStatementResult, error)

VerifyAndroidSafetyNetAttestationStatement verifies that an AttestationObject's attestation statement is valid according to the android safetynet verification procedure.

func VerifyAppleAttestationStatement

func VerifyAppleAttestationStatement(
	attestationObject *AttestationObject,
	clientDataJSONHash ClientDataJSONHash,
) (*VerifyAttestationStatementResult, error)

VerifyAppleAttestationStatement verifies that an AttestationObject's attestation statement is valid according to the packed verification procedure.

func VerifyAttestationStatement

func VerifyAttestationStatement(
	attestationObject *AttestationObject,
	clientDataJSONHash ClientDataJSONHash,
) (*VerifyAttestationStatementResult, error)

VerifyAttestationStatement verifies that an AttestationObject's attestation statement is valid according to the verification procedures defined for know attestation statement formats.

func VerifyFIDOU2FAttestationStatement

func VerifyFIDOU2FAttestationStatement(
	attestationObject *AttestationObject,
	clientDataJSONHash ClientDataJSONHash,
) (*VerifyAttestationStatementResult, error)

VerifyFIDOU2FAttestationStatement verifies a fido-u2f formatted attestation statement according to procedure documented here: https://www.w3.org/TR/webauthn-2/#sctn-fido-u2f-attestation.

func VerifyNoneAttestationStatement

func VerifyNoneAttestationStatement(
	_ *AttestationObject,
	_ ClientDataJSONHash,
) (*VerifyAttestationStatementResult, error)

VerifyNoneAttestationStatement verifies that an AttestationObject's attestation statement is valid according to the "none" verification procedure.

func VerifyPackedAttestationStatement

func VerifyPackedAttestationStatement(
	attestationObject *AttestationObject,
	clientDataJSONHash ClientDataJSONHash,
) (*VerifyAttestationStatementResult, error)

VerifyPackedAttestationStatement verifies that an AttestationObject's attestation statement is valid according to the packed verification procedure.

func VerifyTPMAttestationStatement

func VerifyTPMAttestationStatement(
	attestationObject *AttestationObject,
	clientDataJSONHash ClientDataJSONHash,
) (*VerifyAttestationStatementResult, error)

VerifyTPMAttestationStatement verifies a TPM attestation statement for correctness.

type VerifyOption

type VerifyOption func(*verifyConfig)

A VerifyOption customizes how verification is performed.

func WithVerifyAllowedFormats

func WithVerifyAllowedFormats(allowedFormats ...AttestationFormat) VerifyOption

WithVerifyAllowedFormats sets the allowedFormats in the verify config.

func WithVerifyAllowedTypes

func WithVerifyAllowedTypes(allowedTypes ...AttestationType) VerifyOption

WithVerifyAllowedTypes sets the allowedTypes in the verify config.

Directories

Path Synopsis
Package android contains helper functions and types for Android.
Package android contains helper functions and types for Android.
Package cose contains the subset of the CBOR Object Signing and Encryption (COSE) standard needed for webauthn.
Package cose contains the subset of the CBOR Object Signing and Encryption (COSE) standard needed for webauthn.
Package fido contains functionality related to FIDO devices.
Package fido contains functionality related to FIDO devices.
Package tpm contains types and functions for interacting with TPM structures.
Package tpm contains types and functions for interacting with TPM structures.

Jump to

Keyboard shortcuts

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