webauthn

package module
v0.6.1 Latest Latest
Warning

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

Go to latest
Published: Mar 8, 2020 License: Apache-2.0 Imports: 23 Imported by: 4

README

Build Status Go Report Card GoDoc GitHub

WebAuthn server library (Go/Golang)

This WebAuthn server library provides registration and authentication for clients using FIDO2 keys, FIDO U2F keys, TPM, and etc.

  • It's decoupled from net/http and doesn't force you to use a framework. So it's easy to use in existing projects.

  • It's modular so you only import the attestation formats you need. This helps your software avoid bloat.

  • Six attestation formats are provided: fidou2f, androidkeystore, androidsafetynet, packed, tpm, and none.

  • It doesn't import unreliable packages. It imports fxamacker/cbor because it doesn't crash and it's the most well-tested CBOR library available (v1.5 has 375+ tests and passed 3+ billion execs in coverage-guided fuzzing).

A demo webapp (webauthn-demo) shows how to use this library with a security token like the YubiKey pictured here.

Picture of FIDO U2F key

What's WebAuthn?

WebAuthn (Web Authentication) is a W3C web standard for authenticating users to web-based apps and services. It's a core component of FIDO2, the successor of FIDO U2F legacy protocol.

Design Goals

fxamacker/webauthn is designed to be:

  • small and no unreliable imports -- only 1 external dependency fxamacker/cbor
  • simple and lightweight -- decoupled from net/http and is not a framework
  • modular -- 5 separate attestation packages (packed, tpm, androidkeystore, androidsafetynet, and fidou2f), so you only import what you need.

Status

It's functional enough to demo but unit tests need work. Expired certs embedded in test data can make unit tests to fail. A temporary workaround is to fake datetime when running unit tests locally until expired test data are replaced.

  • replace expired certs in unit tests -- automate replacement of test certs and/or make expiration dates longer
  • more tests and fuzzing -- add more extensive tests and fuzzing like fxamacker/cbor and fxamacker/cbor-fuzz
  • standards compliance -- publish results of standards conformance tests when ready to announce

Features

  • Easy server-side authentication for clients using FIDO2 keys, legacy FIDO U2F keys, and etc.
  • Register credential algorithm for use
  • Register attestation format for use
  • Create new attestation format by implementing AttestationStatement interface
  • Credential algorithms: RS1, RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, and ES512
  • Credential public key types: RSA, RSA-PSS, and ECDSA
  • Credential public key curves: P-256, P-384, and P-521
  • Attestation formats: fido-u2f, android-key, android-safetynet, packed, tpm, and none
  • Attestation types: Basic, Self, and None

System Requirements

  • Go 1.12 (or newer)
  • Tested on x86_64 but it should work on other little-endian systems supported by Go.

Installation

go get github.com/fxamacker/webauthn

High-level API

See API docs.

Create assertion or attestation options:

NewAssertionOptions creates PublicKeyCredentialRequestOptions. NewAttestationOptions creates PublicKeyCredentialCreationOptions. Config represents Relying Party settings used to create those options. Config is initialized at startup and used throughout the program. User contains user data for which the Relying Party requests attestation or assertion.

func NewAssertionOptions(config *Config, user *User) (*PublicKeyCredentialRequestOptions, error)
func NewAttestationOptions(config *Config, user *User) (*PublicKeyCredentialCreationOptions, error)

Parse assertion or attestation:

ParseAssertion returns parsed PublicKeyCredentialAssertion. ParseAttestation returns parsed PublicKeyCredentialAttestation.

func ParseAssertion(r io.Reader) (*PublicKeyCredentialAssertion, error)
func ParseAttestation(r io.Reader) (*PublicKeyCredentialAttestation, error)

Verify assertion or attestation:

VerifyAssertion verifies PublicKeyCredentialAssertion, returned by ParseAssertion. AssertionExpectedData contains data needed to verify an assertion.

VerifyAttestation verifies PublicKeyCredentialAttestation, returned by ParseAttestation. AttestationExpectedData contains data needed to verify an attestation before registering a new credential. VerifyAttestation returns attestation type and attestation trust path. Library users need to assess the attestation trustworthiness by verifying that attestation type is acceptable and trust path can be trusted.

func VerifyAssertion(credentialAssertion *PublicKeyCredentialAssertion, expected *AssertionExpectedData) error
func VerifyAttestation(credentialAttestation *PublicKeyCredentialAttestation, expected *AttestationExpectedData) (attType AttestationType, trustPath interface{}, err error)

Examples

See examples.

Initialize Relying Party config:

// cfg is initialized at startup and used throughout the program to create attestation and assertion options.  
cfg := &webauthn.Config{
    RPID:                    "localhost",
    RPName:                  "WebAuthn local host",
    Timeout:                 uint64(30000),
    ChallengeLength:         64,
    AuthenticatorAttachment: webauthn.AuthenticatorPlatform,
    ResidentKey:             webauthn.ResidentKeyPreferred,
    UserVerification:        webauthn.UserVerificationPreferred,
    Attestation:             webauthn.AttestationDirect,
    CredentialAlgs:          []int{webauthn.COSEAlgES256, webauthn.COSEAlgES384, webauthn.COSEAlgES512},
}
err := cfg.Valid()
if err != nil {
    return err
}

Create attestation options:

// user contains user data for which the Relying Party requests attestation or assertion.
user := &webauthn.User{
    ID:          []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 
    Name:        "Jane Doe",
    DisplayName: "Jane",
}
creationOptions, err := webauthn.NewAttestationOptions(cfg, user)
if err != nil {
    return err
}
creationOptionsJSON, err := json.Marshal(creationOptions)
if err != nil {
    return err
}
// Save user and creationOptions in session to verify attestation later.
// Send creationOptionsJSON to web client, which passes it to navigator.credentials.create().

Parse and verify attestation:

// Parse PublicKeyCredentialAttestation returned by navigator.credentials.create().
credentialAttestation, err := webauthn.ParseAttestation(r)
if err != nil {
    return err
}
// Create AttestationExpectedData object from session's user and creationOptions.
expected := &webauthn.AttestationExpectedData{
    Origin:           "https://localhost:8443",
    RPID:             "localhost",
    CredentialAlgs:   []int{webauthn.COSEAlgES256, webauthn.COSEAlgES384, webauthn.COSEAlgES512},
    Challenge:        "33EHav-jZ1v9qwH783aU-j0ARx6r5o-YHh-wd7C6jPbd7Wh6ytbIZosIIACehwf9-s6hXhySHO-HHUjEwZS29w",
    UserVerification: webauthn.UserVerificationPreferred,
}
attType, trustPath, err := webauthn.VerifyAttestation(credentialAttestation, expected)
if err != nil {
    return err
}
// Verify that attType is acceptable and trustPath can be trusted.
// Save user info, credential id, algorithm, public key, and counter to persistent store.
// User is registered.

Create assertion options:

// user contains user data for which the Relying Party requests attestation or assertion.
user := &webauthn.User{
    ID:          []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 
    Name:        "Jane Doe",
    DisplayName: "Jane",
    CredentialIDs: [][]byte{
        []byte{11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}, 
    },
}
requestOptions, err := webauthn.NewAssertionOptions(cfg, user)
if err != nil {
    return err
}
requestOptionsJSON, err := json.Marshal(requestOptions)
if err != nil {
    return err
}
// Save user and requestOptions in session to verify assertion later.
// Send requestOptionsJSON to web client, which passes it to navigator.credentials.get().

Parse and verify assertion:

// Parse PublicKeyCredentialAssertion returned by navigator.credentials.get().
credentialAssertion, err := webauthn.ParseAssertion(r)
if err != nil {
    return err
}
// Create AssertionExpectedData object from session's user and requestOptions.
expected := &webauthn.AssertionExpectedData{
    Origin:            "https://localhost:8443",
    RPID:              "localhost",
    Challenge:         "eaTyUNnyPDDdK8SNEgTEUvz1Q8dylkjjTimYd5X7QAo-F8_Z1lsJi3BilUpFZHkICNDWY8r9ivnTgW7-XZC3qQ",
    UserVerification:  webauthn.UserVerificationPreferred,
    UserID:            []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 
    UserCredentialIDs: [][]byte{
        []byte{11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}, 
    },
    PrevCounter:       uint32(362),
    Credential:        credential,
}
err = webauthn.VerifyAssertion(credentialAssertion, expected)
if err != nil {
    return err
}
// Update counter in persistent store.
// User is authenticated.

Limitations

This library doesn't support:

  • Attestation validation through FIDO Metadata Service
  • Extensions
  • Token Binding
  • CA attestation
  • Elliptic Curve Direct Anonymous Attestation (ECDAA)

Security Policy

Security fixes are provided for the latest released version.

To report security vulnerabilities, please email faye.github@gmail.com and allow time for the problem to be resolved before reporting it to the public.

Special Thanks

  • Montgomery Edwards⁴⁴⁸ (x448) for updating README.md and filing helpful issues.

  • Ackermann Yuriy (herrjemand) for his extensive tutorials on WebAuthn/FIDO2.

  • Adam Powers (apowers313) for fido2-lib because that pointed me in the direction of separating WebAuthn functionality from any networking protocol.

This library uses attestation and assertion test data from both herrjemand and apowers313.

License

Copyright 2019-present Faye Amacker

fxamacker/webauthn is licensed under the Apache License, Version 2.0. See LICENSE for the full license text.

Documentation

Overview

Package webauthn provides server-side registration and authentication for clients using FIDO2 keys, FIDO U2F keys, tpm, etc. and is decoupled from `net/http` for easy integration with existing projects.

It's modular so projects only import what is needed. Five attestation packages are available: fidou2f, androidkeystore, androidsafetynet, packed, and tpm.

It doesn't import unreliable packages. It uses fxamacker/cbor because it doesn't crash and it's the most well-tested CBOR library available (v1.5 has 375+ tests and passed 3+ billion execs in coverage-guided fuzzing).

A demo webapp (https://www.github.com/fxamacker/webauthn-demo) shows how to use this package with a security token like the YubiKey.

Example (ParseAndVerifyAssertion)
package main

import (
	"fmt"
	"strings"

	"github.com/fxamacker/webauthn"
)

func main() {
	// assertion represents assertion data returned by navigator.credentials.get().
	assertion := `{
	"id":"AAii3V6sGoaozW7TbNaYlJaJ5br8TrBfRXnofZO6l2suc3a5tt_XFuFkFA_5eabU80S1PW0m4IZ79BS2kQO7Zcuy2vf0ESg18GTLG1mo5YSkIdqL2J44egt-6rcj7NedSEwxa_uuxUYBtHNnSQqDmtoUAfM9LSWLl65BjKVZNGUp9ao33mMSdVfQQ0bHze69JVQvLBf8OTiZUqJsOuKmpqUc",
	"rawId":"AAii3V6sGoaozW7TbNaYlJaJ5br8TrBfRXnofZO6l2suc3a5tt_XFuFkFA_5eabU80S1PW0m4IZ79BS2kQO7Zcuy2vf0ESg18GTLG1mo5YSkIdqL2J44egt-6rcj7NedSEwxa_uuxUYBtHNnSQqDmtoUAfM9LSWLl65BjKVZNGUp9ao33mMSdVfQQ0bHze69JVQvLBf8OTiZUqJsOuKmpqUc",
	"response":{
			"clientDataJSON":    "eyJjaGFsbGVuZ2UiOiJlYVR5VU5ueVBERGRLOFNORWdURVV2ejFROGR5bGtqalRpbVlkNVg3UUFvLUY4X1oxbHNKaTNCaWxVcEZaSGtJQ05EV1k4cjlpdm5UZ1c3LVhaQzNxUSIsImNsaWVudEV4dGVuc2lvbnMiOnt9LCJoYXNoQWxnb3JpdGhtIjoiU0hBLTI1NiIsIm9yaWdpbiI6Imh0dHBzOi8vbG9jYWxob3N0Ojg0NDMiLCJ0eXBlIjoid2ViYXV0aG4uZ2V0In0",
			"authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MBAAABaw",
			"signature":         "MEYCIQD6dF3B0ZoaLA0r78oyRdoMNR0bN93Zi4cF_75hFAH6pQIhALY0UIsrh03u_f4yKOwzwD6Cj3_GWLJiioTT9580s1a7",
			"userHandle":        "AQIDBAUGBwgJCg"
	},
	"type":"public-key"
}`
	r := strings.NewReader(assertion)

	// Parse PublicKeyCredentialAssertion returned by navigator.credentials.get().
	credentialAssertion, err := webauthn.ParseAssertion(r)
	if err != nil {
		fmt.Println("error:", err)
		return
	}

	// Create credential from user's registered credential.
	credentialCoseKey := []byte{
		165, 1, 2, 3, 38, 32, 1, 33, 88, 32, 69, 236, 253, 104, 237, 176, 4, 5, 142, 231, 131, 46, 25, 177, 42, 73, 213, 154, 133, 41, 198, 48, 8, 55, 228, 16, 141, 145, 161, 55, 143, 196, 34, 88, 32, 62, 59, 246, 97, 132, 170, 147, 120, 130, 166, 236, 73, 123, 208, 65, 186, 122, 59, 120, 178, 13, 89, 106, 132, 57, 16, 184, 60, 147, 124, 176, 78,
	}
	c, _, err := webauthn.ParseCredential(credentialCoseKey)
	if err != nil {
		fmt.Println("error:", err)
		return
	}

	// Create AssertionExpectedData object from saved user info, user's registered credential, and requestOptions.
	expected := &webauthn.AssertionExpectedData{
		Origin:           "https://localhost:8443",
		RPID:             "localhost",
		Challenge:        "eaTyUNnyPDDdK8SNEgTEUvz1Q8dylkjjTimYd5X7QAo-F8_Z1lsJi3BilUpFZHkICNDWY8r9ivnTgW7-XZC3qQ",
		UserVerification: webauthn.UserVerificationPreferred,
		UserID:           []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
		UserCredentialIDs: [][]byte{
			{0, 8, 162, 221, 94, 172, 26, 134, 168, 205, 110, 211, 108, 214, 152, 148, 150, 137, 229, 186, 252, 78, 176, 95, 69, 121, 232, 125, 147, 186, 151, 107, 46, 115, 118, 185, 182, 223, 215, 22, 225, 100, 20, 15, 249, 121, 166, 212, 243, 68, 181, 61, 109, 38, 224, 134, 123, 244, 20, 182, 145, 3, 187, 101, 203, 178, 218, 247, 244, 17, 40, 53, 240, 100, 203, 27, 89, 168, 229, 132, 164, 33, 218, 139, 216, 158, 56, 122, 11, 126, 234, 183, 35, 236, 215, 157, 72, 76, 49, 107, 251, 174, 197, 70, 1, 180, 115, 103, 73, 10, 131, 154, 218, 20, 1, 243, 61, 45, 37, 139, 151, 174, 65, 140, 165, 89, 52, 101, 41, 245, 170, 55, 222, 99, 18, 117, 87, 208, 67, 70, 199, 205, 238, 189, 37, 84, 47, 44, 23, 252, 57, 56, 153, 82, 162, 108, 58, 226, 166, 166, 165, 28},
		},
		PrevCounter: uint32(0),
		Credential:  c,
	}

	err = webauthn.VerifyAssertion(credentialAssertion, expected)
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	// Update counter in persistent store.
	// User is authenticated.

	fmt.Printf("Credential ID: %s\n", credentialAssertion.ID)
	fmt.Printf("Authenticator counter: %d\n", credentialAssertion.AuthnData.Counter)
	fmt.Printf("User present: %t\n", credentialAssertion.AuthnData.UserPresent)
	fmt.Printf("User verified: %t\n", credentialAssertion.AuthnData.UserVerified)

}
Output:

Credential ID: AAii3V6sGoaozW7TbNaYlJaJ5br8TrBfRXnofZO6l2suc3a5tt_XFuFkFA_5eabU80S1PW0m4IZ79BS2kQO7Zcuy2vf0ESg18GTLG1mo5YSkIdqL2J44egt-6rcj7NedSEwxa_uuxUYBtHNnSQqDmtoUAfM9LSWLl65BjKVZNGUp9ao33mMSdVfQQ0bHze69JVQvLBf8OTiZUqJsOuKmpqUc
Authenticator counter: 363
User present: true
User verified: false
Example (ParseAndVerifyAttestation)
package main

import (
	"fmt"
	"strings"

	"github.com/fxamacker/webauthn"
)

func main() {
	// attestation represents attestation data returned by navigator.credentials.create().
	attestation := `{
	"id"   :"AAii3V6sGoaozW7TbNaYlJaJ5br8TrBfRXnofZO6l2suc3a5tt_XFuFkFA_5eabU80S1PW0m4IZ79BS2kQO7Zcuy2vf0ESg18GTLG1mo5YSkIdqL2J44egt-6rcj7NedSEwxa_uuxUYBtHNnSQqDmtoUAfM9LSWLl65BjKVZNGUp9ao33mMSdVfQQ0bHze69JVQvLBf8OTiZUqJsOuKmpqUc",
	"rawId":"AAii3V6sGoaozW7TbNaYlJaJ5br8TrBfRXnofZO6l2suc3a5tt_XFuFkFA_5eabU80S1PW0m4IZ79BS2kQO7Zcuy2vf0ESg18GTLG1mo5YSkIdqL2J44egt-6rcj7NedSEwxa_uuxUYBtHNnSQqDmtoUAfM9LSWLl65BjKVZNGUp9ao33mMSdVfQQ0bHze69JVQvLBf8OTiZUqJsOuKmpqUc",
	"response":{
		"attestationObject":"o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVkBJkmWDeWIDoxodDQXD2R2YFuP5K65ooYyx5lc87qDHZdjQQAAAAAAAAAAAAAAAAAAAAAAAAAAAKIACKLdXqwahqjNbtNs1piUlonluvxOsF9Feeh9k7qXay5zdrm239cW4WQUD_l5ptTzRLU9bSbghnv0FLaRA7tly7La9_QRKDXwZMsbWajlhKQh2ovYnjh6C37qtyPs151ITDFr-67FRgG0c2dJCoOa2hQB8z0tJYuXrkGMpVk0ZSn1qjfeYxJ1V9BDRsfN7r0lVC8sF_w5OJlSomw64qampRylAQIDJiABIVgguxHN3W6ehp0VWXKaMNie1J82MVJCFZYScau74o17cx8iWCDb1jkTLi7lYZZbgwUwpqAk8QmIiPMTVQUVkhGEyGrKww==",
		"clientDataJSON":"eyJjaGFsbGVuZ2UiOiIzM0VIYXYtaloxdjlxd0g3ODNhVS1qMEFSeDZyNW8tWUhoLXdkN0M2alBiZDdXaDZ5dGJJWm9zSUlBQ2Vod2Y5LXM2aFhoeVNITy1ISFVqRXdaUzI5dyIsImNsaWVudEV4dGVuc2lvbnMiOnt9LCJoYXNoQWxnb3JpdGhtIjoiU0hBLTI1NiIsIm9yaWdpbiI6Imh0dHBzOi8vbG9jYWxob3N0Ojg0NDMiLCJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIn0="
	},
	"type":"public-key"
}`
	r := strings.NewReader(attestation)

	// Parse attestation returned by navigator.credentials.create().
	credentialAttestation, err := webauthn.ParseAttestation(r)
	if err != nil {
		fmt.Println("error:", err)
		return
	}

	// Create AttestationExpectedData object from saved user and creationOptions.
	expected := &webauthn.AttestationExpectedData{
		Origin:           "https://localhost:8443",
		RPID:             "localhost",
		CredentialAlgs:   []int{webauthn.COSEAlgES256, webauthn.COSEAlgES384, webauthn.COSEAlgES512},
		Challenge:        "33EHav-jZ1v9qwH783aU-j0ARx6r5o-YHh-wd7C6jPbd7Wh6ytbIZosIIACehwf9-s6hXhySHO-HHUjEwZS29w",
		UserVerification: webauthn.UserVerificationPreferred,
	}

	attType, trustPath, err := webauthn.VerifyAttestation(credentialAttestation, expected)
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	// Verify that attType is acceptable and trustPath can be trusted.
	// Save user info, credential id, algorithm, public key, and counter to persistent store.
	// User is registered.

	pk, _ := credentialAttestation.AuthnData.Credential.MarshalPKIXPublicKeyPEM()
	fmt.Printf("Credential ID: %s\n", credentialAttestation.ID)
	fmt.Printf("Credential algorithm: %s\n", credentialAttestation.AuthnData.Credential.Algorithm)
	fmt.Printf("Credential public key: %s", pk)
	fmt.Printf("Authenticator counter: %d\n", credentialAttestation.AuthnData.Counter)
	fmt.Printf("User present: %t\n", credentialAttestation.AuthnData.UserPresent)
	fmt.Printf("User verified: %t\n", credentialAttestation.AuthnData.UserVerified)
	fmt.Printf("Attestation type: %s\n", attType)
	fmt.Printf("Trust path: %v\n", trustPath)

}
Output:

Credential ID: AAii3V6sGoaozW7TbNaYlJaJ5br8TrBfRXnofZO6l2suc3a5tt_XFuFkFA_5eabU80S1PW0m4IZ79BS2kQO7Zcuy2vf0ESg18GTLG1mo5YSkIdqL2J44egt-6rcj7NedSEwxa_uuxUYBtHNnSQqDmtoUAfM9LSWLl65BjKVZNGUp9ao33mMSdVfQQ0bHze69JVQvLBf8OTiZUqJsOuKmpqUc
Credential algorithm: ECDSA-SHA256
Credential public key: -----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuxHN3W6ehp0VWXKaMNie1J82MVJC
FZYScau74o17cx/b1jkTLi7lYZZbgwUwpqAk8QmIiPMTVQUVkhGEyGrKww==
-----END PUBLIC KEY-----
Authenticator counter: 0
User present: true
User verified: false
Attestation type: None
Trust path: <nil>

Index

Examples

Constants

View Source
const (
	COSEAlgES256 = -7     // ECDSA with SHA-256
	COSEAlgES384 = -35    // ECDSA with SHA-384
	COSEAlgES512 = -36    // ECDSA with SHA-512
	COSEAlgPS256 = -37    // RSASSA-PSS with SHA-256
	COSEAlgPS384 = -38    // RSASSA-PSS with SHA-384
	COSEAlgPS512 = -39    // RSASSA-PSS with SHA-512
	COSEAlgRS1   = -65535 // RSASSA-PKCS1-v1_5 with SHA-1
	COSEAlgRS256 = -257   // RSASSA-PKCS1-v1_5 with SHA-256
	COSEAlgRS384 = -258   // RSASSA-PKCS1-v1_5 with SHA-384
	COSEAlgRS512 = -259   // RSASSA-PKCS1-v1_5 with SHA-512
)

Supported COSE algorithm identifier registered in the IANA COSE Algorithm registry.

Variables

This section is empty.

Functions

func RegisterAttestationFormat

func RegisterAttestationFormat(name string, parse func([]byte) (AttestationStatement, error))

RegisterAttestationFormat registers attestation statement format with a function that parses attestation statement of given format.

func RegisterSignatureAlgorithm

func RegisterSignatureAlgorithm(coseAlg int, sigAlg x509.SignatureAlgorithm, pkAlg x509.PublicKeyAlgorithm, hash crypto.Hash)

RegisterSignatureAlgorithm registers the given COSE algorithm identifier with corresponding signature algorithm, public key algorithm, and hash function.

func UnregisterAttestationFormat

func UnregisterAttestationFormat(name string)

UnregisterAttestationFormat unregisters given attestation statement format.

func UnregisterSignatureAlgorithm

func UnregisterSignatureAlgorithm(coseAlg int)

UnregisterSignatureAlgorithm unregisters the given COSE algorithm.

func VerifyAssertion

func VerifyAssertion(credentialAssertion *PublicKeyCredentialAssertion, expected *AssertionExpectedData) error

VerifyAssertion verifies assertion and returns error, as defined in http://w3c.github.io/webauthn/#sctn-verifying-assertion

Types

type AssertionExpectedData

type AssertionExpectedData struct {
	Origin            string
	RPID              string
	Challenge         string
	UserVerification  UserVerificationRequirement
	UserID            []byte
	UserCredentialIDs [][]byte
	PrevCounter       uint32
	Credential        *Credential
}

AssertionExpectedData represents data needed to verify assertions.

type AttestationConveyancePreference

type AttestationConveyancePreference string

AttestationConveyancePreference represents the Web Authentication enumeration of the same name, as defined in http://w3c.github.io/webauthn/#enum-attestation-convey

const (
	AttestationNone     AttestationConveyancePreference = "none"     // Relying Party is not interested in authenticator attestation.
	AttestationIndirect AttestationConveyancePreference = "indirect" // Relying Party prefers a verifiable attestation statements, but allows the client to decide how to obtain such attestation statements.
	AttestationDirect   AttestationConveyancePreference = "direct"   // Relying Party wants to receive the attestation statement.
)

AttestationConveyancePreference enumeration.

type AttestationExpectedData

type AttestationExpectedData struct {
	Origin           string
	RPID             string
	CredentialAlgs   []int
	Challenge        string
	UserVerification UserVerificationRequirement
}

AttestationExpectedData represents data needed to verify attestations.

type AttestationStatement

type AttestationStatement interface {
	// Verify verifies an attestation statement and returns attestation type and trust path, or an error.
	Verify(clientDataHash []byte, authnData *AuthenticatorData) (attType AttestationType, trustPath interface{}, err error)
}

AttestationStatement is the common interface implemented by all attestation statements.

type AttestationType

type AttestationType int

AttestationType identifies an attestation trust model.

const (
	AttestationTypeBasic AttestationType = iota + 1
	AttestationTypeSelf
	AttestationTypeCA
	AttestationTypeECDAA
	AttestationTypeNone
)

Attestation types are defined in http://w3c.github.io/webauthn/#sctn-attestation-types

func VerifyAttestation

func VerifyAttestation(credentialAttestation *PublicKeyCredentialAttestation, expected *AttestationExpectedData) (attType AttestationType, trustPath interface{}, err error)

VerifyAttestation verifies attestation and returns attestation type, trust path, or error, as defined in http://w3c.github.io/webauthn/#sctn-registering-a-new-credential

func (AttestationType) String

func (attType AttestationType) String() string

type AuthenticatorAttachment

type AuthenticatorAttachment string

AuthenticatorAttachment represents the Web Authentication enumeration of the same name, as defined in http://w3c.github.io/webauthn/#enum-attachment

const (
	AuthenticatorPlatform      AuthenticatorAttachment = "platform"
	AuthenticatorCrossPlatform AuthenticatorAttachment = "cross-platform"
)

AuthenticatorAttachment enumeration.

type AuthenticatorData

type AuthenticatorData struct {
	Raw          []byte                 // Complete raw authenticator data content.
	RPIDHash     []byte                 // SHA-256 hash of the RP ID the credential is scoped to.
	UserPresent  bool                   // User is present.
	UserVerified bool                   // User is verified.
	Counter      uint32                 // Signature Counter.
	AAGUID       []byte                 // AAGUID of the authenticator (optional).
	CredentialID []byte                 // Identifier of a public key credential source (optional).
	Credential   *Credential            // Algorithm and public key portion of a Relying Party-specific credential key pair (optional).
	Extensions   map[string]interface{} // Extension-defined authenticator data (optional).
}

AuthenticatorData represents the Web Authentication structure of the same name, as defined in http://w3c.github.io/webauthn/#sctn-authenticator-data

type AuthenticatorSelectionCriteria

type AuthenticatorSelectionCriteria struct {
	AuthenticatorAttachment AuthenticatorAttachment     `json:"authenticatorAttachment,omitempty"` // Authenticator attachment modality.
	RequireResidentKey      bool                        `json:"requireResidentKey,omitempty"`      // Resident credential storage modality, defaulting to false.
	ResidentKey             ResidentKeyRequirement      `json:"residentKey,omitempty"`             // Supersedes RequireResidentKey.
	UserVerification        UserVerificationRequirement `json:"userVerification,omitempty"`        // Authentication factor capability, defaulting to "preferred".
}

AuthenticatorSelectionCriteria represents the Web Authentication structure of the same name, as defined in http://w3c.github.io/webauthn/#dictionary-authenticatorSelection

type AuthenticatorTransport

type AuthenticatorTransport string

AuthenticatorTransport represents the Web Authentication enumeration of the same name, as defined in http://w3c.github.io/webauthn/#enum-transport

const (
	AuthenticatorUSB      AuthenticatorTransport = "usb"      // Removable USB.
	AuthenticatorNFC      AuthenticatorTransport = "nfc"      // Near Field Communication.
	AuthenticatorBLE      AuthenticatorTransport = "ble"      // Bluetooth Low Energy.
	AuthenticatorInternal AuthenticatorTransport = "internal" // Client device specific transport.
)

AuthenticatorTransport enumeration.

type CollectedClientData

type CollectedClientData struct {
	Raw          []byte        `json:"-"`            // Complete raw client data content.
	Type         string        `json:"type"`         // "webauthn.create" when creating new credentials, and "webauthn.get" when getting an assertion.
	Challenge    string        `json:"challenge"`    // base64 url encoded chanllenge provided by the Relying Party.
	Origin       string        `json:"origin"`       // Fully qualified origin of the requester.
	TokenBinding *TokenBinding `json:"tokenBinding"` // State of the Token Binding protocol used when communicating with the Relying Party.  Its absence indicates that the client doesn't support token binding.
}

CollectedClientData represents the Web Authentication structure of the same name, as defined in http://w3c.github.io/webauthn/#dictionary-client-data

type Config

type Config struct {
	ChallengeLength         int
	Timeout                 uint64
	RPID                    string
	RPName                  string
	RPIcon                  string
	AuthenticatorAttachment AuthenticatorAttachment
	ResidentKey             ResidentKeyRequirement
	UserVerification        UserVerificationRequirement
	Attestation             AttestationConveyancePreference
	CredentialAlgs          []int
}

Config represents Relying Party settings used to create attestation and assertion options. Zero value Config is not valid.

func (*Config) Valid

func (c *Config) Valid() error

Valid checks Config settings and returns error if it is invalid.

type Credential

type Credential struct {
	Raw []byte
	SignatureAlgorithm
	crypto.PublicKey
}

Credential represents credential algorithm and public key used to verify assertion signatures.

func ParseCredential

func ParseCredential(coseKeyData []byte) (c *Credential, rest []byte, err error)

ParseCredential parses credential public key encoded in COSE_Key format.

func (*Credential) MarshalPKIXPublicKeyPEM

func (c *Credential) MarshalPKIXPublicKeyPEM() ([]byte, error)

MarshalPKIXPublicKeyPEM serializes public key to PEM-encoded PKIX format.

func (*Credential) Verify

func (c *Credential) Verify(message []byte, signature []byte) error

Verify verifies the signature of hashed message using credential algorithm and public key.

type PublicKeyCredentialAssertion

type PublicKeyCredentialAssertion struct {
	ID         string               // Base64url encoded credential ID.
	RawID      []byte               // Raw credential ID.
	ClientData *CollectedClientData // Client data passed to the authenticator by the client.
	AuthnData  *AuthenticatorData   // Authenticator data returned by the authenticator.
	Signature  []byte               // Raw signature returned from the authenticator.
	UserHandle []byte               // User handle returned from the authenticator, or null.
}

PublicKeyCredentialAssertion represents the Web Authentication structure of PublicKeyCredential for assertions, as defined in http://w3c.github.io/webauthn/#iface-pkcredential

func ParseAssertion

func ParseAssertion(r io.Reader) (*PublicKeyCredentialAssertion, error)

ParseAssertion parses credential assertion and returns PublicKeyCredentialAssertion.

func (*PublicKeyCredentialAssertion) UnmarshalJSON

func (credentialAssertion *PublicKeyCredentialAssertion) UnmarshalJSON(data []byte) (err error)

UnmarshalJSON implements json.Unmarshaler interface. rawId, clientDataJSON, authenticatorData, signature, and userHandle are base64 URL encoded.

type PublicKeyCredentialAttestation

type PublicKeyCredentialAttestation struct {
	ID         string
	RawID      []byte
	ClientData *CollectedClientData
	AuthnData  *AuthenticatorData
	AttStmt    AttestationStatement
}

PublicKeyCredentialAttestation represents the Web Authentication structure of PublicKeyCredential for new credentials, as defined in http://w3c.github.io/webauthn/#iface-pkcredential

func ParseAttestation

func ParseAttestation(r io.Reader) (*PublicKeyCredentialAttestation, error)

ParseAttestation parses credential attestation and returns PublicKeyCredentialAttestation.

func (*PublicKeyCredentialAttestation) UnmarshalJSON

func (credentialAttestation *PublicKeyCredentialAttestation) UnmarshalJSON(data []byte) (err error)

UnmarshalJSON implements json.Unmarshaler interface. rawId, clientDataJSON, and attestationObject are base64 URL encoded.

func (*PublicKeyCredentialAttestation) VerifyAttestationStatement

func (credentialAttestation *PublicKeyCredentialAttestation) VerifyAttestationStatement() (attType AttestationType, trustPath interface{}, err error)

VerifyAttestationStatement verifies attestation statement and returns attestation type and trust path, or an error.

type PublicKeyCredentialCreationOptions

type PublicKeyCredentialCreationOptions struct {
	RP                     PublicKeyCredentialRpEntity     `json:"rp"`                               // Relying Party data responsible for the request.
	User                   PublicKeyCredentialUserEntity   `json:"user"`                             // User data for which the Relying Party is requesting attestation.
	Challenge              bufferString                    `json:"challenge"`                        // Challenge for generating new credential's attestation object.
	PubKeyCredParams       []PublicKeyCredentialParameters `json:"pubKeyCredParams"`                 // Desired properties of the credential to be created.  The sequence is ordered from most preferred to least preferred.
	Timeout                uint64                          `json:"timeout,omitempty"`                // Time in milliseconds for client to wait for the call to complete.  Client can override this value.
	ExcludeCredentials     []PublicKeyCredentialDescriptor `json:"excludeCredentials,omitempty"`     // Used by Relying Parties to limit the creation of multiple credentials for the same account on a single authenticator.
	AuthenticatorSelection AuthenticatorSelectionCriteria  `json:"authenticatorSelection,omitempty"` // Used by Relying Parties to select appropriate authenticators.
	Attestation            AttestationConveyancePreference `json:"attestation,omitempty"`            // Used by Relying Parties to specify preference for attestation conveyance.
}

PublicKeyCredentialCreationOptions represents the Web Authentication structure of the same name, as defined in http://w3c.github.io/webauthn/#dictionary-makecredentialoptions Extensions are not supported.

func NewAttestationOptions

func NewAttestationOptions(config *Config, user *User) (*PublicKeyCredentialCreationOptions, error)

NewAttestationOptions returns a PublicKeyCredentialCreationOptions from config and user.

Example
package main

import (
	"encoding/json"
	"fmt"

	"github.com/fxamacker/webauthn"
)

func main() {
	// cfg is initialized at startup and used throughout the program to create attestation and assertion options.
	cfg := &webauthn.Config{
		RPID:                    "localhost",
		RPName:                  "WebAuthn local host",
		Timeout:                 uint64(30000),
		ChallengeLength:         64,
		AuthenticatorAttachment: webauthn.AuthenticatorPlatform,
		ResidentKey:             webauthn.ResidentKeyPreferred,
		UserVerification:        webauthn.UserVerificationPreferred,
		Attestation:             webauthn.AttestationNone,
		CredentialAlgs:          []int{webauthn.COSEAlgES256, webauthn.COSEAlgES384, webauthn.COSEAlgES512},
	}
	if err := cfg.Valid(); err != nil {
		fmt.Println("error:", err)
		return
	}

	// user contains user data for which the Relying Party is requesting attestation or assertion.
	user := &webauthn.User{
		ID:          []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
		Name:        "Jane Doe",
		DisplayName: "Jane",
	}

	creationOptions, err := webauthn.NewAttestationOptions(cfg, user)
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	creationOptionsJSON, err := json.Marshal(creationOptions)
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	// Save user and creationOptions in session to verify attestation later.
	// Send creationOptionsJSON to web client, which passes it to navigator.credentials.create().

	fmt.Printf("%s\n", creationOptionsJSON)
}
Output:

type PublicKeyCredentialDescriptor

type PublicKeyCredentialDescriptor struct {
	Type       PublicKeyCredentialType  `json:"type"`                 // Type of the public key credential.
	ID         bufferString             `json:"id"`                   // Credential ID of the public key credential.
	Transports []AuthenticatorTransport `json:"transports,omitempty"` // How the client might communicate with the authenticator of the public key credential.
}

PublicKeyCredentialDescriptor represents the Web Authentication structure of the same name, as defined in http://w3c.github.io/webauthn/#dictionary-credential-descriptor

type PublicKeyCredentialParameters

type PublicKeyCredentialParameters struct {
	Type PublicKeyCredentialType `json:"type"` // Type of credential to be created.
	// Alg identifies a cryptographic algorithm registered in the IANA COSE Algorithm registry.
	// It 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 generate.
	Alg int `json:"alg"`
}

PublicKeyCredentialParameters represents the Web Authentication structure of the same name, as defined in http://w3c.github.io/webauthn/#dictionary-credential-params

type PublicKeyCredentialRequestOptions

type PublicKeyCredentialRequestOptions struct {
	Challenge        bufferString                    `json:"challenge"`                  // Challenge that the selected authenticator signs, along with other data, when producing an authentication assertion.
	Timeout          uint64                          `json:"timeout,omitempty"`          // Time in milliseconds for client to wait for the call to complete.  Client can override this value.
	RPID             string                          `json:"rpId,omitempty"`             // Relying Party identifier.
	AllowCredentials []PublicKeyCredentialDescriptor `json:"allowCredentials,omitempty"` // A list of public key credentials acceptable to the caller.  The sequence is ordered from most preferred to least preferred.
	UserVerification UserVerificationRequirement     `json:"userVerification,omitempty"` // Relying Party's requirements for user verification.
}

PublicKeyCredentialRequestOptions represents the Web Authentication structure of the same name, as defined in http://w3c.github.io/webauthn/#dictionary-assertion-options Extensions are not supported.

func NewAssertionOptions

func NewAssertionOptions(config *Config, user *User) (*PublicKeyCredentialRequestOptions, error)

NewAssertionOptions returns a PublicKeyCredentialRequestOptions from config and user.

Example
package main

import (
	"encoding/json"
	"fmt"

	"github.com/fxamacker/webauthn"
)

func main() {
	// cfg is initialized at startup and used throughout the program to create attestation and assertion options.
	cfg := &webauthn.Config{
		RPID:                    "localhost",
		RPName:                  "WebAuthn local host",
		Timeout:                 uint64(30000),
		ChallengeLength:         64,
		AuthenticatorAttachment: webauthn.AuthenticatorPlatform,
		ResidentKey:             webauthn.ResidentKeyPreferred,
		UserVerification:        webauthn.UserVerificationPreferred,
		Attestation:             webauthn.AttestationNone,
		CredentialAlgs:          []int{webauthn.COSEAlgES256, webauthn.COSEAlgES384, webauthn.COSEAlgES512},
	}
	if err := cfg.Valid(); err != nil {
		fmt.Println("error:", err)
		return
	}

	// user contains user data for which the Relying Party is requesting attestation or assertion.
	user := &webauthn.User{
		ID:          []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
		Name:        "Jane Doe",
		DisplayName: "Jane",
		CredentialIDs: [][]byte{
			{0, 8, 71, 237, 201, 207, 68, 25, 28, 186, 72, 231, 115, 97, 182, 24, 205, 71, 229, 217, 21, 179, 211, 245, 171, 101, 68, 174, 16, 249, 238, 153, 51, 41, 88, 193, 110, 44, 93, 178, 231, 227, 94, 21, 14, 126, 32, 246, 236, 61, 21, 3, 231, 207, 41, 69, 88, 52, 97, 54, 93, 135, 35, 134, 40, 109, 96, 224, 208, 191, 236, 68, 106, 186, 101, 177, 174, 200, 199, 168, 74, 215, 113, 64, 234, 236, 145, 196, 200, 7, 11, 115, 225, 77, 188, 126, 173, 186, 191, 68, 197, 27, 104, 159, 135, 160, 101, 109, 249, 207, 54, 210, 39, 221, 161, 168, 36, 21, 29, 54, 85, 169, 252, 86, 191, 106, 235, 176, 103, 235, 49, 205, 13, 63, 195, 54, 180, 27, 182, 146, 20, 170, 165, 255, 70, 13, 169, 230, 142, 133, 237, 181, 78, 222, 227, 137, 27, 216, 84, 54, 5, 27},
		},
	}

	requestOptions, err := webauthn.NewAssertionOptions(cfg, user)
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	requestOptionsJSON, err := json.Marshal(requestOptions)
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	// Save user and requestOptions in session to verify assertion later.
	// Send requestOptionsJSON to web client, which passes it to navigator.credentials.get().

	fmt.Printf("%s\n", requestOptionsJSON)
}
Output:

type PublicKeyCredentialRpEntity

type PublicKeyCredentialRpEntity struct {
	Name string `json:"name"`           // Human-palatable identifier, intended only for display.
	Icon string `json:"icon,omitempty"` // Serialized URL which resolves to an image associated with the entity.
	ID   string `json:"id,omitempty"`   // Relying Party unique identifier (effective domain).
}

PublicKeyCredentialRpEntity represents the Web Authentication structure of the same name, as defined in http://w3c.github.io/webauthn/#dictionary-rp-credential-params

type PublicKeyCredentialType

type PublicKeyCredentialType string

PublicKeyCredentialType represents the Web Authentication enumeration of the same name, as defined in http://w3c.github.io/webauthn/#enum-credentialType

const (
	PublicKeyCredentialTypePublicKey PublicKeyCredentialType = "public-key"
)

PublicKeyCredentialType enumeration.

type PublicKeyCredentialUserEntity

type PublicKeyCredentialUserEntity struct {
	Name        string       `json:"name"`           // Human-palatable identifier, intended only for display.
	Icon        string       `json:"icon,omitempty"` // Serialized URL which resolves to an image associated with the entity.
	ID          bufferString `json:"id"`             // User handle, SHOULD NOT include personally identifying information (WebAuthn spec recommends 64 random bytes).
	DisplayName string       `json:"displayName"`    // Human-palatable name, intended only for display.
}

PublicKeyCredentialUserEntity represents the Web Authentication structure of the same name, as defined in http://w3c.github.io/webauthn/#dictionary-user-credential-params

type ResidentKeyRequirement

type ResidentKeyRequirement string

ResidentKeyRequirement represents the Web Authentication enumeration of the same name, as defined in http://w3c.github.io/webauthn/#enum-residentKeyRequirement

const (
	ResidentKeyDiscouraged ResidentKeyRequirement = "discouraged"
	ResidentKeyPreferred   ResidentKeyRequirement = "preferred"
	ResidentKeyRequired    ResidentKeyRequirement = "required"
)

ResidentKeyRequirement enumeration.

type SignatureAlgorithm

type SignatureAlgorithm struct {
	Algorithm          x509.SignatureAlgorithm
	PublicKeyAlgorithm x509.PublicKeyAlgorithm
	Hash               crypto.Hash
	COSEAlgorithm      int
}

SignatureAlgorithm represents signature algorithm, and its corresponding public key algorithm, hash function, and COSE algorithm identifier.

func CoseAlgToSignatureAlgorithm

func CoseAlgToSignatureAlgorithm(coseAlg int) (SignatureAlgorithm, error)

CoseAlgToSignatureAlgorithm returns signature algorithm of given COSE algorithm identifier.

func (SignatureAlgorithm) IsECDSA

func (alg SignatureAlgorithm) IsECDSA() bool

IsECDSA returns if signature algorithm uses ECDSA public key.

func (SignatureAlgorithm) IsRSA

func (alg SignatureAlgorithm) IsRSA() bool

IsRSA returns if signature algorithm uses RSA public key.

func (SignatureAlgorithm) IsRSAPSS

func (alg SignatureAlgorithm) IsRSAPSS() bool

IsRSAPSS returns if signature algorithm uses RSAPSS public key.

type TokenBinding

type TokenBinding struct {
	Status TokenBindingStatus `json:"status"`
	ID     string             `json:"id"` // Base64url encoded Token Binding ID that was used when communicating with the Relying Party (required if status is "present").
}

TokenBinding represents the Web Authentication structure of the same name, as defined in http://w3c.github.io/webauthn/#dictionary-client-data

type TokenBindingStatus

type TokenBindingStatus string

TokenBindingStatus represents the Web Authentication enumeration of the same name, as defined in http://w3c.github.io/webauthn/#dictionary-client-data

const (
	TokenBindingPresent   TokenBindingStatus = "present"   // Token binding was used when communicating with the Relying Party.
	TokenBindingSupported TokenBindingStatus = "supported" // Client supports token binding, but it was not negotiated when communicating with the Relying Party.
)

TokenBindingStatus enumeration.

type UnmarshalBadDataError

type UnmarshalBadDataError struct {
	Type string
	Msg  string
}

UnmarshalBadDataError results when invalid data is detected.

func (*UnmarshalBadDataError) Error

func (e *UnmarshalBadDataError) Error() string

type UnmarshalMissingFieldError

type UnmarshalMissingFieldError struct {
	Type  string
	Field string
}

UnmarshalMissingFieldError results when a required field is missing.

func (*UnmarshalMissingFieldError) Error

type UnmarshalSyntaxError

type UnmarshalSyntaxError struct {
	Type  string
	Field string
	Msg   string
}

UnmarshalSyntaxError describes a syntax error resulting from parsing webauthn data.

func (*UnmarshalSyntaxError) Error

func (e *UnmarshalSyntaxError) Error() string

type UnregisteredFeatureError

type UnregisteredFeatureError struct {
	Feature string
}

UnregisteredFeatureError describes a feature that is not registered.

func (*UnregisteredFeatureError) Error

func (e *UnregisteredFeatureError) Error() string

type UnsupportedFeatureError

type UnsupportedFeatureError struct {
	Feature string
}

UnsupportedFeatureError describes a feature that is not supported.

func (*UnsupportedFeatureError) Error

func (e *UnsupportedFeatureError) Error() string

type User

type User struct {
	ID            []byte
	Name          string
	Icon          string
	DisplayName   string
	CredentialIDs [][]byte
}

User represents user data for which the Relying Party requests attestation or assertion.

type UserVerificationRequirement

type UserVerificationRequirement string

UserVerificationRequirement represents the Web Authentication enumeration of the same name, as defined in http://w3c.github.io/webauthn/#enum-userVerificationRequirement

const (
	UserVerificationRequired    UserVerificationRequirement = "required"
	UserVerificationPreferred   UserVerificationRequirement = "preferred"
	UserVerificationDiscouraged UserVerificationRequirement = "discouraged"
)

UserVerificationRequirement enumeration.

type VerificationError

type VerificationError struct {
	Type  string
	Field string
	Msg   string
}

VerificationError describes an error resulting from verifying webauthn data.

func (*VerificationError) Error

func (e *VerificationError) Error() string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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