authelia/internal/model/webauthn.go

216 lines
5.9 KiB
Go
Raw Normal View History

package model
import (
"database/sql"
"encoding/hex"
"encoding/json"
"strings"
"time"
"github.com/go-webauthn/webauthn/protocol"
"github.com/go-webauthn/webauthn/webauthn"
"github.com/google/uuid"
)
const (
attestationTypeFIDOU2F = "fido-u2f"
)
// WebauthnUser is an object to represent a user for the Webauthn lib.
type WebauthnUser struct {
Username string
DisplayName string
Devices []WebauthnDevice
}
// HasFIDOU2F returns true if the user has any attestation type `fido-u2f` devices.
func (w WebauthnUser) HasFIDOU2F() bool {
for _, c := range w.Devices {
if c.AttestationType == attestationTypeFIDOU2F {
return true
}
}
return false
}
// WebAuthnID implements the webauthn.User interface.
func (w WebauthnUser) WebAuthnID() []byte {
return []byte(w.Username)
}
// WebAuthnName implements the webauthn.User interface.
func (w WebauthnUser) WebAuthnName() string {
return w.Username
}
// WebAuthnDisplayName implements the webauthn.User interface.
func (w WebauthnUser) WebAuthnDisplayName() string {
return w.DisplayName
}
// WebAuthnIcon implements the webauthn.User interface.
func (w WebauthnUser) WebAuthnIcon() string {
return ""
}
// WebAuthnCredentials implements the webauthn.User interface.
func (w WebauthnUser) WebAuthnCredentials() (credentials []webauthn.Credential) {
credentials = make([]webauthn.Credential, len(w.Devices))
var credential webauthn.Credential
for i, device := range w.Devices {
aaguid, err := device.AAGUID.MarshalBinary()
if err != nil {
continue
}
credential = webauthn.Credential{
ID: device.KID.Bytes(),
PublicKey: device.PublicKey,
AttestationType: device.AttestationType,
Authenticator: webauthn.Authenticator{
AAGUID: aaguid,
SignCount: device.SignCount,
CloneWarning: device.CloneWarning,
},
}
transports := strings.Split(device.Transport, ",")
credential.Transport = []protocol.AuthenticatorTransport{}
for _, t := range transports {
if t == "" {
continue
}
credential.Transport = append(credential.Transport, protocol.AuthenticatorTransport(t))
}
credentials[i] = credential
}
return credentials
}
// WebAuthnCredentialDescriptors decodes the users credentials into protocol.CredentialDescriptor's.
func (w WebauthnUser) WebAuthnCredentialDescriptors() (descriptors []protocol.CredentialDescriptor) {
credentials := w.WebAuthnCredentials()
descriptors = make([]protocol.CredentialDescriptor, len(credentials))
for i, credential := range credentials {
descriptors[i] = credential.Descriptor()
}
return descriptors
}
// NewWebauthnDeviceFromCredential creates a WebauthnDevice from a webauthn.Credential.
func NewWebauthnDeviceFromCredential(rpid, username, description string, credential *webauthn.Credential) (device WebauthnDevice) {
transport := make([]string, len(credential.Transport))
for i, t := range credential.Transport {
transport[i] = string(t)
}
device = WebauthnDevice{
RPID: rpid,
Username: username,
CreatedAt: time.Now(),
Description: description,
KID: NewBase64(credential.ID),
PublicKey: credential.PublicKey,
AttestationType: credential.AttestationType,
SignCount: credential.Authenticator.SignCount,
CloneWarning: credential.Authenticator.CloneWarning,
Transport: strings.Join(transport, ","),
}
refactor: merge master and fix missing rebinds (#4404) * build(deps): update module github.com/jackc/pgx/v5 to v5.1.0 (#4365) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * docs: add smkent as a contributor for code, design, and ideas (#4367) * update README.md * update .all-contributorsrc Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * build(deps): update module github.com/ory/fosite to v0.43.0 (#4269) This updates fosite and refactors our usage out of compose. * refactor(cmd): restrict bootstrap pnpm tasks to dev environment (#4370) * build(deps): update alpine docker tag to v3.16.3 (#4362) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update module github.com/ory/x to v0.0.514 (#4368) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * refactor: sql formatting (#4371) * refactor: sql spacing * refactor editor config * docs: clarify cloudflare docs (#4373) * build(deps): update dependency @types/react-dom to v18.0.9 (#4379) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update typescript-eslint monorepo to v5.43.0 (#4380) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency @types/jest to v29.2.3 (#4381) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency esbuild to v0.15.14 (#4383) * build(deps): update material-ui monorepo to v5.10.14 (#4385) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency vite to v3.2.4 (#4386) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update font awesome to v6.2.1 (#4389) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency typescript to v4.9.3 (#4390) * docs: adjust issue templates (#4391) * docs: adjust issue templates * docs: adjust wording * build(deps): update dependency jest-watch-typeahead to v2.2.1 (#4392) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency i18next to v22.0.6 (#4395) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update github.com/duosecurity/duo_api_golang digest to 091daa0 (#4396) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update traefik docker tag to v2.9.5 (#4398) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update module github.com/jackc/pgx/v5 to v5.1.1 (#4400) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update mariadb docker tag to v10.10.2 (#4399) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency eslint-plugin-react to v7.31.11 (#4401) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency eslint to v8.28.0 (#4402) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(storage): schema inconsistency (#4262) * fix: missing pg rebinds * fix: refactoring issues * fix: refactoring issues Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> Co-authored-by: Amir Zarrinkafsh <nightah@me.com>
2022-11-19 06:42:03 +00:00
aaguid, err := uuid.Parse(hex.EncodeToString(credential.Authenticator.AAGUID))
if err == nil && aaguid.ID() != 0 {
device.AAGUID = uuid.NullUUID{Valid: true, UUID: aaguid}
}
return device
}
// WebauthnDevice represents a Webauthn Device in the database storage.
type WebauthnDevice struct {
refactor: merge master and fix missing rebinds (#4404) * build(deps): update module github.com/jackc/pgx/v5 to v5.1.0 (#4365) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * docs: add smkent as a contributor for code, design, and ideas (#4367) * update README.md * update .all-contributorsrc Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * build(deps): update module github.com/ory/fosite to v0.43.0 (#4269) This updates fosite and refactors our usage out of compose. * refactor(cmd): restrict bootstrap pnpm tasks to dev environment (#4370) * build(deps): update alpine docker tag to v3.16.3 (#4362) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update module github.com/ory/x to v0.0.514 (#4368) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * refactor: sql formatting (#4371) * refactor: sql spacing * refactor editor config * docs: clarify cloudflare docs (#4373) * build(deps): update dependency @types/react-dom to v18.0.9 (#4379) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update typescript-eslint monorepo to v5.43.0 (#4380) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency @types/jest to v29.2.3 (#4381) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency esbuild to v0.15.14 (#4383) * build(deps): update material-ui monorepo to v5.10.14 (#4385) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency vite to v3.2.4 (#4386) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update font awesome to v6.2.1 (#4389) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency typescript to v4.9.3 (#4390) * docs: adjust issue templates (#4391) * docs: adjust issue templates * docs: adjust wording * build(deps): update dependency jest-watch-typeahead to v2.2.1 (#4392) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency i18next to v22.0.6 (#4395) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update github.com/duosecurity/duo_api_golang digest to 091daa0 (#4396) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update traefik docker tag to v2.9.5 (#4398) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update module github.com/jackc/pgx/v5 to v5.1.1 (#4400) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update mariadb docker tag to v10.10.2 (#4399) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency eslint-plugin-react to v7.31.11 (#4401) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency eslint to v8.28.0 (#4402) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(storage): schema inconsistency (#4262) * fix: missing pg rebinds * fix: refactoring issues * fix: refactoring issues Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> Co-authored-by: Amir Zarrinkafsh <nightah@me.com>
2022-11-19 06:42:03 +00:00
ID int `db:"id"`
CreatedAt time.Time `db:"created_at"`
LastUsedAt sql.NullTime `db:"last_used_at"`
RPID string `db:"rpid"`
Username string `db:"username"`
Description string `db:"description"`
KID Base64 `db:"kid"`
PublicKey []byte `db:"public_key"`
AttestationType string `db:"attestation_type"`
Transport string `db:"transport"`
AAGUID uuid.NullUUID `db:"aaguid"`
SignCount uint32 `db:"sign_count"`
CloneWarning bool `db:"clone_warning"`
}
// MarshalJSON returns the WebauthnDevice in a JSON friendly manner.
func (w *WebauthnDevice) MarshalJSON() (data []byte, err error) {
o := struct {
ID int `json:"id"`
CreatedAt time.Time `json:"created_at"`
LastUsedAt *time.Time `json:"last_used_at,omitempty"`
RPID string `json:"rpid"`
Description string `json:"description"`
KID []byte `json:"kid"`
PublicKey []byte `json:"public_key"`
AttestationType string `json:"attestation_type"`
Transports []string `json:"transports"`
refactor: merge master and fix missing rebinds (#4404) * build(deps): update module github.com/jackc/pgx/v5 to v5.1.0 (#4365) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * docs: add smkent as a contributor for code, design, and ideas (#4367) * update README.md * update .all-contributorsrc Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * build(deps): update module github.com/ory/fosite to v0.43.0 (#4269) This updates fosite and refactors our usage out of compose. * refactor(cmd): restrict bootstrap pnpm tasks to dev environment (#4370) * build(deps): update alpine docker tag to v3.16.3 (#4362) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update module github.com/ory/x to v0.0.514 (#4368) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * refactor: sql formatting (#4371) * refactor: sql spacing * refactor editor config * docs: clarify cloudflare docs (#4373) * build(deps): update dependency @types/react-dom to v18.0.9 (#4379) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update typescript-eslint monorepo to v5.43.0 (#4380) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency @types/jest to v29.2.3 (#4381) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency esbuild to v0.15.14 (#4383) * build(deps): update material-ui monorepo to v5.10.14 (#4385) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency vite to v3.2.4 (#4386) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update font awesome to v6.2.1 (#4389) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency typescript to v4.9.3 (#4390) * docs: adjust issue templates (#4391) * docs: adjust issue templates * docs: adjust wording * build(deps): update dependency jest-watch-typeahead to v2.2.1 (#4392) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency i18next to v22.0.6 (#4395) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update github.com/duosecurity/duo_api_golang digest to 091daa0 (#4396) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update traefik docker tag to v2.9.5 (#4398) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update module github.com/jackc/pgx/v5 to v5.1.1 (#4400) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update mariadb docker tag to v10.10.2 (#4399) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency eslint-plugin-react to v7.31.11 (#4401) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency eslint to v8.28.0 (#4402) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(storage): schema inconsistency (#4262) * fix: missing pg rebinds * fix: refactoring issues * fix: refactoring issues Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> Co-authored-by: Amir Zarrinkafsh <nightah@me.com>
2022-11-19 06:42:03 +00:00
AAGUID string `json:"aaguid,omitempty"`
SignCount uint32 `json:"sign_count"`
CloneWarning bool `json:"clone_warning"`
}{
ID: w.ID,
CreatedAt: w.CreatedAt,
RPID: w.RPID,
Description: w.Description,
KID: w.KID.data,
PublicKey: w.PublicKey,
AttestationType: w.AttestationType,
Transports: []string{},
SignCount: w.SignCount,
CloneWarning: w.CloneWarning,
}
refactor: merge master and fix missing rebinds (#4404) * build(deps): update module github.com/jackc/pgx/v5 to v5.1.0 (#4365) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * docs: add smkent as a contributor for code, design, and ideas (#4367) * update README.md * update .all-contributorsrc Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * build(deps): update module github.com/ory/fosite to v0.43.0 (#4269) This updates fosite and refactors our usage out of compose. * refactor(cmd): restrict bootstrap pnpm tasks to dev environment (#4370) * build(deps): update alpine docker tag to v3.16.3 (#4362) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update module github.com/ory/x to v0.0.514 (#4368) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * refactor: sql formatting (#4371) * refactor: sql spacing * refactor editor config * docs: clarify cloudflare docs (#4373) * build(deps): update dependency @types/react-dom to v18.0.9 (#4379) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update typescript-eslint monorepo to v5.43.0 (#4380) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency @types/jest to v29.2.3 (#4381) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency esbuild to v0.15.14 (#4383) * build(deps): update material-ui monorepo to v5.10.14 (#4385) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency vite to v3.2.4 (#4386) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update font awesome to v6.2.1 (#4389) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency typescript to v4.9.3 (#4390) * docs: adjust issue templates (#4391) * docs: adjust issue templates * docs: adjust wording * build(deps): update dependency jest-watch-typeahead to v2.2.1 (#4392) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency i18next to v22.0.6 (#4395) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update github.com/duosecurity/duo_api_golang digest to 091daa0 (#4396) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update traefik docker tag to v2.9.5 (#4398) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update module github.com/jackc/pgx/v5 to v5.1.1 (#4400) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update mariadb docker tag to v10.10.2 (#4399) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency eslint-plugin-react to v7.31.11 (#4401) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * build(deps): update dependency eslint to v8.28.0 (#4402) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(storage): schema inconsistency (#4262) * fix: missing pg rebinds * fix: refactoring issues * fix: refactoring issues Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> Co-authored-by: Amir Zarrinkafsh <nightah@me.com>
2022-11-19 06:42:03 +00:00
if w.AAGUID.Valid {
o.AAGUID = w.AAGUID.UUID.String()
}
if w.Transport != "" {
o.Transports = strings.Split(w.Transport, ",")
}
if w.LastUsedAt.Valid {
o.LastUsedAt = &w.LastUsedAt.Time
}
return json.Marshal(o)
}
// UpdateSignInInfo adjusts the values of the WebauthnDevice after a sign in.
func (w *WebauthnDevice) UpdateSignInInfo(config *webauthn.Config, now time.Time, signCount uint32) {
w.LastUsedAt = sql.NullTime{Time: now, Valid: true}
w.SignCount = signCount
if w.RPID != "" {
return
}
switch w.AttestationType {
case attestationTypeFIDOU2F:
w.RPID = config.RPOrigin
default:
w.RPID = config.RPID
}
}