docs: adjust references of webauthn (#5203)
Signed-off-by: James Elliott <james-d-elliott@users.noreply.github.com>pull/5205/head
parent
304467c10f
commit
157675f1f3
|
@ -7,5 +7,5 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
const (
|
const (
|
||||||
versionSwaggerUI = "4.18.1"
|
versionSwaggerUI = "4.18.2"
|
||||||
)
|
)
|
||||||
|
|
|
@ -49,7 +49,7 @@ authelia configuration, and authelia database prior to attempting to do so._
|
||||||
Notable Missing Features from this build:
|
Notable Missing Features from this build:
|
||||||
|
|
||||||
- OpenID Connect 1.0 PAR
|
- OpenID Connect 1.0 PAR
|
||||||
- Multi-Device Webauthn
|
- Multi-Device WebAuthn
|
||||||
- Device Registration OTP
|
- Device Registration OTP
|
||||||
|
|
||||||
- Container Images:
|
- Container Images:
|
||||||
|
@ -144,7 +144,7 @@ Please see the [roadmap](../../roadmap/active/openid-connect.md) for more inform
|
||||||
|
|
||||||
##### Initial Implementation
|
##### Initial Implementation
|
||||||
|
|
||||||
_**Important Note:** This feature at the time of this writing, will not work well with Webauthn. Steps are being taken
|
_**Important Note:** This feature at the time of this writing, will not work well with WebAuthn. Steps are being taken
|
||||||
to address this however it will not specifically delay the release of this feature._
|
to address this however it will not specifically delay the release of this feature._
|
||||||
|
|
||||||
This release see's the initial implementation of multi-domain protection. Users will be able to configure more than a
|
This release see's the initial implementation of multi-domain protection. Users will be able to configure more than a
|
||||||
|
@ -160,14 +160,14 @@ NGINX/NGINX Proxy Manager/SWAG/HAProxy with the use of the new
|
||||||
[Customizable Authorization Endpoints](#customizable-authorization-endpoints). This is important as it means you only
|
[Customizable Authorization Endpoints](#customizable-authorization-endpoints). This is important as it means you only
|
||||||
need to configure a single middleware or helper to perform automatic redirection.
|
need to configure a single middleware or helper to perform automatic redirection.
|
||||||
|
|
||||||
## Webauthn
|
## WebAuthn
|
||||||
|
|
||||||
As part of our ongoing effort for comprehensive support for Webauthn we'll be introducing several important
|
As part of our ongoing effort for comprehensive support for WebAuthn we'll be introducing several important
|
||||||
features. Please see the [roadmap](../../roadmap/active/webauthn.md) for more information.
|
features. Please see the [roadmap](../../roadmap/active/webauthn.md) for more information.
|
||||||
|
|
||||||
##### Multiple Webauthn Credentials Per-User
|
##### Multiple WebAuthn Credentials Per-User
|
||||||
|
|
||||||
In this release we see full support for multiple Webauthn credentials. This is a fairly basic feature but getting the
|
In this release we see full support for multiple WebAuthn credentials. This is a fairly basic feature but getting the
|
||||||
frontend experience right is important to us. This is going to be supported via the
|
frontend experience right is important to us. This is going to be supported via the
|
||||||
[User Control Panel](#user-dashboard--control-panel).
|
[User Control Panel](#user-dashboard--control-panel).
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Testing"
|
title: "Testing"
|
||||||
description: "Authelia Development Testing Guidelines"
|
description: "Authelia Development Testing Guidelines"
|
||||||
lead: "This section covers the testing guidelines."
|
lead: "This section covers the testing guidelines."
|
||||||
date: 2022-06-15T17:51:47+10:00
|
date: 2023-03-20T15:03:52+11:00
|
||||||
draft: false
|
draft: false
|
||||||
images: []
|
images: []
|
||||||
menu:
|
menu:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
title: "Amir Zarrinkafsh"
|
title: "Amir Zarrinkafsh"
|
||||||
date: 2022-06-15T17:51:47+10:00
|
date: 2023-03-19T16:29:12+10:00
|
||||||
draft: false
|
draft: false
|
||||||
images: []
|
images: []
|
||||||
---
|
---
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
title: "Clément Michaud"
|
title: "Clément Michaud"
|
||||||
date: 2022-06-15T17:51:47+10:00
|
date: 2023-03-19T16:29:12+10:00
|
||||||
draft: false
|
draft: false
|
||||||
images: []
|
images: []
|
||||||
---
|
---
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
title: "Manuel Nuñez"
|
title: "Manuel Nuñez"
|
||||||
date: 2022-06-15T17:51:47+10:00
|
date: 2023-03-19T16:29:12+10:00
|
||||||
draft: false
|
draft: false
|
||||||
images: []
|
images: []
|
||||||
---
|
---
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
title: "About"
|
title: "About"
|
||||||
description: "About Authelia and the Authelia Team"
|
description: "About Authelia and the Authelia Team"
|
||||||
date: 2022-06-15T17:51:47+10:00
|
date: 2023-03-19T16:29:12+10:00
|
||||||
draft: false
|
draft: false
|
||||||
images: []
|
images: []
|
||||||
aliases:
|
aliases:
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Firezone"
|
title: "Firezone"
|
||||||
description: "Integrating Firezone with the Authelia OpenID Connect Provider."
|
description: "Integrating Firezone with the Authelia OpenID Connect Provider."
|
||||||
lead: ""
|
lead: ""
|
||||||
date: 2023-03-25T13:07:02+10:00
|
date: 2023-03-28T20:29:13+11:00
|
||||||
draft: false
|
draft: false
|
||||||
images: []
|
images: []
|
||||||
menu:
|
menu:
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
title: "MinIO"
|
title: "MinIO"
|
||||||
description: "Integrating MinIO with the Authelia OpenID Connect Provider."
|
description: "Integrating MinIO with the Authelia OpenID Connect Provider."
|
||||||
lead: ""
|
lead: ""
|
||||||
date: 2022-06-15T17:51:47+10:00
|
date: 2023-03-21T11:21:23+11:00
|
||||||
draft: false
|
draft: false
|
||||||
images: []
|
images: []
|
||||||
menu:
|
menu:
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Misago"
|
title: "Misago"
|
||||||
description: "Integrating Misago with the Authelia OpenID Connect Provider."
|
description: "Integrating Misago with the Authelia OpenID Connect Provider."
|
||||||
lead: ""
|
lead: ""
|
||||||
date: 2023-03-04T13:20:00+00:00
|
date: 2023-03-14T08:51:13+11:00
|
||||||
draft: false
|
draft: false
|
||||||
images: []
|
images: []
|
||||||
menu:
|
menu:
|
||||||
|
|
|
@ -73,7 +73,7 @@ serving Authelia at `auth.example.com`.
|
||||||
```nginx
|
```nginx
|
||||||
## Set $authelia_backend to route requests to the current domain by default
|
## Set $authelia_backend to route requests to the current domain by default
|
||||||
set $authelia_backend $http_host;
|
set $authelia_backend $http_host;
|
||||||
## In order for Webauthn to work with multiple domains authelia must operate on a separate subdomain
|
## In order for WebAuthn to work with multiple domains authelia must operate on a separate subdomain
|
||||||
## To use authelia on a separate subdomain:
|
## To use authelia on a separate subdomain:
|
||||||
## * comment the $authelia_backend line above
|
## * comment the $authelia_backend line above
|
||||||
## * rename /config/nginx/proxy-confs/authelia.conf.sample to /config/nginx/proxy-confs/authelia.conf
|
## * rename /config/nginx/proxy-confs/authelia.conf.sample to /config/nginx/proxy-confs/authelia.conf
|
||||||
|
@ -88,7 +88,7 @@ serving Authelia at `auth.example.com`.
|
||||||
```nginx
|
```nginx
|
||||||
## Set $authelia_backend to route requests to the current domain by default
|
## Set $authelia_backend to route requests to the current domain by default
|
||||||
# set $authelia_backend $http_host;
|
# set $authelia_backend $http_host;
|
||||||
## In order for Webauthn to work with multiple domains authelia must operate on a separate subdomain
|
## In order for WebAuthn to work with multiple domains authelia must operate on a separate subdomain
|
||||||
## To use authelia on a separate subdomain:
|
## To use authelia on a separate subdomain:
|
||||||
## * comment the $authelia_backend line above
|
## * comment the $authelia_backend line above
|
||||||
## * rename /config/nginx/proxy-confs/authelia.conf.sample to /config/nginx/proxy-confs/authelia.conf
|
## * rename /config/nginx/proxy-confs/authelia.conf.sample to /config/nginx/proxy-confs/authelia.conf
|
||||||
|
|
|
@ -63,5 +63,5 @@ authelia storage user --help
|
||||||
* [authelia storage](authelia_storage.md) - Manage the Authelia storage
|
* [authelia storage](authelia_storage.md) - Manage the Authelia storage
|
||||||
* [authelia storage user identifiers](authelia_storage_user_identifiers.md) - Manage user opaque identifiers
|
* [authelia storage user identifiers](authelia_storage_user_identifiers.md) - Manage user opaque identifiers
|
||||||
* [authelia storage user totp](authelia_storage_user_totp.md) - Manage TOTP configurations
|
* [authelia storage user totp](authelia_storage_user_totp.md) - Manage TOTP configurations
|
||||||
* [authelia storage user webauthn](authelia_storage_user_webauthn.md) - Manage Webauthn devices
|
* [authelia storage user webauthn](authelia_storage_user_webauthn.md) - Manage WebAuthn devices
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,13 @@ toc: true
|
||||||
|
|
||||||
## authelia storage user webauthn
|
## authelia storage user webauthn
|
||||||
|
|
||||||
Manage Webauthn devices
|
Manage WebAuthn devices
|
||||||
|
|
||||||
### Synopsis
|
### Synopsis
|
||||||
|
|
||||||
Manage Webauthn devices.
|
Manage WebAuthn devices.
|
||||||
|
|
||||||
This subcommand allows interacting with Webauthn devices.
|
This subcommand allows interacting with WebAuthn devices.
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
|
@ -61,8 +61,8 @@ authelia storage user webauthn --help
|
||||||
### SEE ALSO
|
### SEE ALSO
|
||||||
|
|
||||||
* [authelia storage user](authelia_storage_user.md) - Manages user settings
|
* [authelia storage user](authelia_storage_user.md) - Manages user settings
|
||||||
* [authelia storage user webauthn delete](authelia_storage_user_webauthn_delete.md) - Delete a Webauthn device
|
* [authelia storage user webauthn delete](authelia_storage_user_webauthn_delete.md) - Delete a WebAuthn device
|
||||||
* [authelia storage user webauthn export](authelia_storage_user_webauthn_export.md) - Perform exports of the Webauthn devices
|
* [authelia storage user webauthn export](authelia_storage_user_webauthn_export.md) - Perform exports of the WebAuthn devices
|
||||||
* [authelia storage user webauthn import](authelia_storage_user_webauthn_import.md) - Perform imports of the Webauthn devices
|
* [authelia storage user webauthn import](authelia_storage_user_webauthn_import.md) - Perform imports of the WebAuthn devices
|
||||||
* [authelia storage user webauthn list](authelia_storage_user_webauthn_list.md) - List Webauthn devices
|
* [authelia storage user webauthn list](authelia_storage_user_webauthn_list.md) - List WebAuthn devices
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,13 @@ toc: true
|
||||||
|
|
||||||
## authelia storage user webauthn delete
|
## authelia storage user webauthn delete
|
||||||
|
|
||||||
Delete a Webauthn device
|
Delete a WebAuthn device
|
||||||
|
|
||||||
### Synopsis
|
### Synopsis
|
||||||
|
|
||||||
Delete a Webauthn device.
|
Delete a WebAuthn device.
|
||||||
|
|
||||||
This subcommand allows deleting a Webauthn device directly from the database.
|
This subcommand allows deleting a WebAuthn device directly from the database.
|
||||||
|
|
||||||
```
|
```
|
||||||
authelia storage user webauthn delete [username] [flags]
|
authelia storage user webauthn delete [username] [flags]
|
||||||
|
@ -75,5 +75,5 @@ authelia storage user webauthn delete --kid abc123 --encryption-key b3453fde-ecc
|
||||||
|
|
||||||
### SEE ALSO
|
### SEE ALSO
|
||||||
|
|
||||||
* [authelia storage user webauthn](authelia_storage_user_webauthn.md) - Manage Webauthn devices
|
* [authelia storage user webauthn](authelia_storage_user_webauthn.md) - Manage WebAuthn devices
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,13 @@ toc: true
|
||||||
|
|
||||||
## authelia storage user webauthn export
|
## authelia storage user webauthn export
|
||||||
|
|
||||||
Perform exports of the Webauthn devices
|
Perform exports of the WebAuthn devices
|
||||||
|
|
||||||
### Synopsis
|
### Synopsis
|
||||||
|
|
||||||
Perform exports of the Webauthn devices.
|
Perform exports of the WebAuthn devices.
|
||||||
|
|
||||||
This subcommand allows exporting Webauthn devices to various formats.
|
This subcommand allows exporting WebAuthn devices to various formats.
|
||||||
|
|
||||||
```
|
```
|
||||||
authelia storage user webauthn export [flags]
|
authelia storage user webauthn export [flags]
|
||||||
|
@ -68,5 +68,5 @@ authelia storage user webauthn export--encryption-key b3453fde-ecc2-4a1f-9422-27
|
||||||
|
|
||||||
### SEE ALSO
|
### SEE ALSO
|
||||||
|
|
||||||
* [authelia storage user webauthn](authelia_storage_user_webauthn.md) - Manage Webauthn devices
|
* [authelia storage user webauthn](authelia_storage_user_webauthn.md) - Manage WebAuthn devices
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,13 @@ toc: true
|
||||||
|
|
||||||
## authelia storage user webauthn import
|
## authelia storage user webauthn import
|
||||||
|
|
||||||
Perform imports of the Webauthn devices
|
Perform imports of the WebAuthn devices
|
||||||
|
|
||||||
### Synopsis
|
### Synopsis
|
||||||
|
|
||||||
Perform imports of the Webauthn devices.
|
Perform imports of the WebAuthn devices.
|
||||||
|
|
||||||
This subcommand allows importing Webauthn devices from various formats.
|
This subcommand allows importing WebAuthn devices from various formats.
|
||||||
|
|
||||||
```
|
```
|
||||||
authelia storage user webauthn import <filename> [flags]
|
authelia storage user webauthn import <filename> [flags]
|
||||||
|
@ -67,5 +67,5 @@ authelia storage user webauthn import --file authelia.export.webauthn.yaml --enc
|
||||||
|
|
||||||
### SEE ALSO
|
### SEE ALSO
|
||||||
|
|
||||||
* [authelia storage user webauthn](authelia_storage_user_webauthn.md) - Manage Webauthn devices
|
* [authelia storage user webauthn](authelia_storage_user_webauthn.md) - Manage WebAuthn devices
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,13 @@ toc: true
|
||||||
|
|
||||||
## authelia storage user webauthn list
|
## authelia storage user webauthn list
|
||||||
|
|
||||||
List Webauthn devices
|
List WebAuthn devices
|
||||||
|
|
||||||
### Synopsis
|
### Synopsis
|
||||||
|
|
||||||
List Webauthn devices.
|
List WebAuthn devices.
|
||||||
|
|
||||||
This subcommand allows listing Webauthn devices.
|
This subcommand allows listing WebAuthn devices.
|
||||||
|
|
||||||
```
|
```
|
||||||
authelia storage user webauthn list [username] [flags]
|
authelia storage user webauthn list [username] [flags]
|
||||||
|
@ -69,5 +69,5 @@ authelia storage user webauthn list john --encryption-key b3453fde-ecc2-4a1f-942
|
||||||
|
|
||||||
### SEE ALSO
|
### SEE ALSO
|
||||||
|
|
||||||
* [authelia storage user webauthn](authelia_storage_user_webauthn.md) - Manage Webauthn devices
|
* [authelia storage user webauthn](authelia_storage_user_webauthn.md) - Manage WebAuthn devices
|
||||||
|
|
||||||
|
|
|
@ -177,56 +177,56 @@ This subcommand allows manually adding an opaque identifier for a user to the da
|
||||||
authelia storage user identifiers add john --identifier f0919359-9d15-4e15-bcba-83b41620a073 --config config.yml
|
authelia storage user identifiers add john --identifier f0919359-9d15-4e15-bcba-83b41620a073 --config config.yml
|
||||||
authelia storage user identifiers add john --identifier f0919359-9d15-4e15-bcba-83b41620a073 --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw`
|
authelia storage user identifiers add john --identifier f0919359-9d15-4e15-bcba-83b41620a073 --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw`
|
||||||
|
|
||||||
cmdAutheliaStorageUserWebauthnShort = "Manage Webauthn devices"
|
cmdAutheliaStorageUserWebAuthnShort = "Manage WebAuthn devices"
|
||||||
|
|
||||||
cmdAutheliaStorageUserWebauthnLong = `Manage Webauthn devices.
|
cmdAutheliaStorageUserWebAuthnLong = `Manage WebAuthn devices.
|
||||||
|
|
||||||
This subcommand allows interacting with Webauthn devices.`
|
This subcommand allows interacting with WebAuthn devices.`
|
||||||
|
|
||||||
cmdAutheliaStorageUserWebauthnExample = `authelia storage user webauthn --help`
|
cmdAutheliaStorageUserWebAuthnExample = `authelia storage user webauthn --help`
|
||||||
|
|
||||||
cmdAutheliaStorageUserWebauthnImportShort = "Perform imports of the Webauthn devices"
|
cmdAutheliaStorageUserWebAuthnImportShort = "Perform imports of the WebAuthn devices"
|
||||||
|
|
||||||
cmdAutheliaStorageUserWebauthnImportLong = `Perform imports of the Webauthn devices.
|
cmdAutheliaStorageUserWebAuthnImportLong = `Perform imports of the WebAuthn devices.
|
||||||
|
|
||||||
This subcommand allows importing Webauthn devices from various formats.`
|
This subcommand allows importing WebAuthn devices from various formats.`
|
||||||
|
|
||||||
cmdAutheliaStorageUserWebauthnImportExample = `authelia storage user webauthn export
|
cmdAutheliaStorageUserWebAuthnImportExample = `authelia storage user webauthn export
|
||||||
authelia storage user webauthn import --file authelia.export.webauthn.yaml
|
authelia storage user webauthn import --file authelia.export.webauthn.yaml
|
||||||
authelia storage user webauthn import --file authelia.export.webauthn.yaml --config config.yml
|
authelia storage user webauthn import --file authelia.export.webauthn.yaml --config config.yml
|
||||||
authelia storage user webauthn import --file authelia.export.webauthn.yaml --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw`
|
authelia storage user webauthn import --file authelia.export.webauthn.yaml --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw`
|
||||||
|
|
||||||
cmdAutheliaStorageUserWebauthnExportShort = "Perform exports of the Webauthn devices"
|
cmdAutheliaStorageUserWebAuthnExportShort = "Perform exports of the WebAuthn devices"
|
||||||
|
|
||||||
cmdAutheliaStorageUserWebauthnExportLong = `Perform exports of the Webauthn devices.
|
cmdAutheliaStorageUserWebAuthnExportLong = `Perform exports of the WebAuthn devices.
|
||||||
|
|
||||||
This subcommand allows exporting Webauthn devices to various formats.`
|
This subcommand allows exporting WebAuthn devices to various formats.`
|
||||||
|
|
||||||
cmdAutheliaStorageUserWebauthnExportExample = `authelia storage user webauthn export
|
cmdAutheliaStorageUserWebAuthnExportExample = `authelia storage user webauthn export
|
||||||
authelia storage user webauthn export --file authelia.export.webauthn.yaml
|
authelia storage user webauthn export --file authelia.export.webauthn.yaml
|
||||||
authelia storage user webauthn export --config config.yml
|
authelia storage user webauthn export --config config.yml
|
||||||
authelia storage user webauthn export--encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw`
|
authelia storage user webauthn export--encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw`
|
||||||
|
|
||||||
cmdAutheliaStorageUserWebauthnListShort = "List Webauthn devices"
|
cmdAutheliaStorageUserWebAuthnListShort = "List WebAuthn devices"
|
||||||
|
|
||||||
cmdAutheliaStorageUserWebauthnListLong = `List Webauthn devices.
|
cmdAutheliaStorageUserWebAuthnListLong = `List WebAuthn devices.
|
||||||
|
|
||||||
This subcommand allows listing Webauthn devices.`
|
This subcommand allows listing WebAuthn devices.`
|
||||||
|
|
||||||
cmdAutheliaStorageUserWebauthnListExample = `authelia storage user webauthn list
|
cmdAutheliaStorageUserWebAuthnListExample = `authelia storage user webauthn list
|
||||||
authelia storage user webauthn list john
|
authelia storage user webauthn list john
|
||||||
authelia storage user webauthn list --config config.yml
|
authelia storage user webauthn list --config config.yml
|
||||||
authelia storage user webauthn list john --config config.yml
|
authelia storage user webauthn list john --config config.yml
|
||||||
authelia storage user webauthn list --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw
|
authelia storage user webauthn list --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw
|
||||||
authelia storage user webauthn list john --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw`
|
authelia storage user webauthn list john --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw`
|
||||||
|
|
||||||
cmdAutheliaStorageUserWebauthnDeleteShort = "Delete a Webauthn device"
|
cmdAutheliaStorageUserWebAuthnDeleteShort = "Delete a WebAuthn device"
|
||||||
|
|
||||||
cmdAutheliaStorageUserWebauthnDeleteLong = `Delete a Webauthn device.
|
cmdAutheliaStorageUserWebAuthnDeleteLong = `Delete a WebAuthn device.
|
||||||
|
|
||||||
This subcommand allows deleting a Webauthn device directly from the database.`
|
This subcommand allows deleting a WebAuthn device directly from the database.`
|
||||||
|
|
||||||
cmdAutheliaStorageUserWebauthnDeleteExample = `authelia storage user webauthn delete john --all
|
cmdAutheliaStorageUserWebAuthnDeleteExample = `authelia storage user webauthn delete john --all
|
||||||
authelia storage user webauthn delete john --all --config config.yml
|
authelia storage user webauthn delete john --all --config config.yml
|
||||||
authelia storage user webauthn delete john --all --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw
|
authelia storage user webauthn delete john --all --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw
|
||||||
authelia storage user webauthn delete john --description Primary
|
authelia storage user webauthn delete john --description Primary
|
||||||
|
|
|
@ -68,7 +68,7 @@ func storageTOTPGenerateRunEOptsFromFlags(flags *pflag.FlagSet) (force bool, fil
|
||||||
return force, filename, secret, nil
|
return force, filename, secret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func storageWebauthnDeleteRunEOptsFromFlags(flags *pflag.FlagSet, args []string) (all, byKID bool, description, kid, user string, err error) {
|
func storageWebAuthnDeleteRunEOptsFromFlags(flags *pflag.FlagSet, args []string) (all, byKID bool, description, kid, user string, err error) {
|
||||||
if len(args) != 0 {
|
if len(args) != 0 {
|
||||||
user = args[0]
|
user = args[0]
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,7 @@ func newStorageUserCmd(ctx *CmdCtx) (cmd *cobra.Command) {
|
||||||
cmd.AddCommand(
|
cmd.AddCommand(
|
||||||
newStorageUserIdentifiersCmd(ctx),
|
newStorageUserIdentifiersCmd(ctx),
|
||||||
newStorageUserTOTPCmd(ctx),
|
newStorageUserTOTPCmd(ctx),
|
||||||
newStorageUserWebauthnCmd(ctx),
|
newStorageUserWebAuthnCmd(ctx),
|
||||||
)
|
)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
|
@ -221,34 +221,34 @@ func newStorageUserIdentifiersAddCmd(ctx *CmdCtx) (cmd *cobra.Command) {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func newStorageUserWebauthnCmd(ctx *CmdCtx) (cmd *cobra.Command) {
|
func newStorageUserWebAuthnCmd(ctx *CmdCtx) (cmd *cobra.Command) {
|
||||||
cmd = &cobra.Command{
|
cmd = &cobra.Command{
|
||||||
Use: "webauthn",
|
Use: "webauthn",
|
||||||
Short: cmdAutheliaStorageUserWebauthnShort,
|
Short: cmdAutheliaStorageUserWebAuthnShort,
|
||||||
Long: cmdAutheliaStorageUserWebauthnLong,
|
Long: cmdAutheliaStorageUserWebAuthnLong,
|
||||||
Example: cmdAutheliaStorageUserWebauthnExample,
|
Example: cmdAutheliaStorageUserWebAuthnExample,
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
|
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.AddCommand(
|
cmd.AddCommand(
|
||||||
newStorageUserWebauthnListCmd(ctx),
|
newStorageUserWebAuthnListCmd(ctx),
|
||||||
newStorageUserWebauthnDeleteCmd(ctx),
|
newStorageUserWebAuthnDeleteCmd(ctx),
|
||||||
newStorageUserWebauthnExportCmd(ctx),
|
newStorageUserWebAuthnExportCmd(ctx),
|
||||||
newStorageUserWebauthnImportCmd(ctx),
|
newStorageUserWebAuthnImportCmd(ctx),
|
||||||
)
|
)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func newStorageUserWebauthnImportCmd(ctx *CmdCtx) (cmd *cobra.Command) {
|
func newStorageUserWebAuthnImportCmd(ctx *CmdCtx) (cmd *cobra.Command) {
|
||||||
cmd = &cobra.Command{
|
cmd = &cobra.Command{
|
||||||
Use: cmdUseImportFileName,
|
Use: cmdUseImportFileName,
|
||||||
Short: cmdAutheliaStorageUserWebauthnImportShort,
|
Short: cmdAutheliaStorageUserWebAuthnImportShort,
|
||||||
Long: cmdAutheliaStorageUserWebauthnImportLong,
|
Long: cmdAutheliaStorageUserWebAuthnImportLong,
|
||||||
Example: cmdAutheliaStorageUserWebauthnImportExample,
|
Example: cmdAutheliaStorageUserWebAuthnImportExample,
|
||||||
RunE: ctx.StorageUserWebauthnImportRunE,
|
RunE: ctx.StorageUserWebAuthnImportRunE,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
|
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
|
@ -257,13 +257,13 @@ func newStorageUserWebauthnImportCmd(ctx *CmdCtx) (cmd *cobra.Command) {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func newStorageUserWebauthnExportCmd(ctx *CmdCtx) (cmd *cobra.Command) {
|
func newStorageUserWebAuthnExportCmd(ctx *CmdCtx) (cmd *cobra.Command) {
|
||||||
cmd = &cobra.Command{
|
cmd = &cobra.Command{
|
||||||
Use: cmdUseExport,
|
Use: cmdUseExport,
|
||||||
Short: cmdAutheliaStorageUserWebauthnExportShort,
|
Short: cmdAutheliaStorageUserWebAuthnExportShort,
|
||||||
Long: cmdAutheliaStorageUserWebauthnExportLong,
|
Long: cmdAutheliaStorageUserWebAuthnExportLong,
|
||||||
Example: cmdAutheliaStorageUserWebauthnExportExample,
|
Example: cmdAutheliaStorageUserWebAuthnExportExample,
|
||||||
RunE: ctx.StorageUserWebauthnExportRunE,
|
RunE: ctx.StorageUserWebAuthnExportRunE,
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
|
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
|
@ -274,13 +274,13 @@ func newStorageUserWebauthnExportCmd(ctx *CmdCtx) (cmd *cobra.Command) {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func newStorageUserWebauthnListCmd(ctx *CmdCtx) (cmd *cobra.Command) {
|
func newStorageUserWebAuthnListCmd(ctx *CmdCtx) (cmd *cobra.Command) {
|
||||||
cmd = &cobra.Command{
|
cmd = &cobra.Command{
|
||||||
Use: "list [username]",
|
Use: "list [username]",
|
||||||
Short: cmdAutheliaStorageUserWebauthnListShort,
|
Short: cmdAutheliaStorageUserWebAuthnListShort,
|
||||||
Long: cmdAutheliaStorageUserWebauthnListLong,
|
Long: cmdAutheliaStorageUserWebAuthnListLong,
|
||||||
Example: cmdAutheliaStorageUserWebauthnListExample,
|
Example: cmdAutheliaStorageUserWebAuthnListExample,
|
||||||
RunE: ctx.StorageUserWebauthnListRunE,
|
RunE: ctx.StorageUserWebAuthnListRunE,
|
||||||
Args: cobra.MaximumNArgs(1),
|
Args: cobra.MaximumNArgs(1),
|
||||||
|
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
|
@ -289,13 +289,13 @@ func newStorageUserWebauthnListCmd(ctx *CmdCtx) (cmd *cobra.Command) {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func newStorageUserWebauthnDeleteCmd(ctx *CmdCtx) (cmd *cobra.Command) {
|
func newStorageUserWebAuthnDeleteCmd(ctx *CmdCtx) (cmd *cobra.Command) {
|
||||||
cmd = &cobra.Command{
|
cmd = &cobra.Command{
|
||||||
Use: "delete [username]",
|
Use: "delete [username]",
|
||||||
Short: cmdAutheliaStorageUserWebauthnDeleteShort,
|
Short: cmdAutheliaStorageUserWebAuthnDeleteShort,
|
||||||
Long: cmdAutheliaStorageUserWebauthnDeleteLong,
|
Long: cmdAutheliaStorageUserWebAuthnDeleteLong,
|
||||||
Example: cmdAutheliaStorageUserWebauthnDeleteExample,
|
Example: cmdAutheliaStorageUserWebAuthnDeleteExample,
|
||||||
RunE: ctx.StorageUserWebauthnDeleteRunE,
|
RunE: ctx.StorageUserWebAuthnDeleteRunE,
|
||||||
Args: cobra.MaximumNArgs(1),
|
Args: cobra.MaximumNArgs(1),
|
||||||
|
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
|
|
|
@ -415,7 +415,7 @@ func (ctx *CmdCtx) StorageSchemaInfoRunE(_ *cobra.Command, _ []string) (err erro
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *CmdCtx) StorageUserWebauthnExportRunE(cmd *cobra.Command, args []string) (err error) {
|
func (ctx *CmdCtx) StorageUserWebAuthnExportRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = ctx.providers.StorageProvider.Close()
|
_ = ctx.providers.StorageProvider.Close()
|
||||||
}()
|
}()
|
||||||
|
@ -443,11 +443,11 @@ func (ctx *CmdCtx) StorageUserWebauthnExportRunE(cmd *cobra.Command, args []stri
|
||||||
count := 0
|
count := 0
|
||||||
|
|
||||||
var (
|
var (
|
||||||
devices []model.WebauthnDevice
|
devices []model.WebAuthnDevice
|
||||||
)
|
)
|
||||||
|
|
||||||
export := &model.WebauthnDeviceExport{
|
export := &model.WebAuthnDeviceExport{
|
||||||
WebauthnDevices: nil,
|
WebAuthnDevices: nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
for page := 0; true; page++ {
|
for page := 0; true; page++ {
|
||||||
|
@ -455,7 +455,7 @@ func (ctx *CmdCtx) StorageUserWebauthnExportRunE(cmd *cobra.Command, args []stri
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
export.WebauthnDevices = append(export.WebauthnDevices, devices...)
|
export.WebAuthnDevices = append(export.WebAuthnDevices, devices...)
|
||||||
|
|
||||||
l := len(devices)
|
l := len(devices)
|
||||||
|
|
||||||
|
@ -476,12 +476,12 @@ func (ctx *CmdCtx) StorageUserWebauthnExportRunE(cmd *cobra.Command, args []stri
|
||||||
return fmt.Errorf("error occurred writing to file '%s': %w", filename, err)
|
return fmt.Errorf("error occurred writing to file '%s': %w", filename, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf(cliOutputFmtSuccessfulUserExportFile, count, "Webauthn devices", "YAML", filename)
|
fmt.Printf(cliOutputFmtSuccessfulUserExportFile, count, "WebAuthn devices", "YAML", filename)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *CmdCtx) StorageUserWebauthnImportRunE(cmd *cobra.Command, args []string) (err error) {
|
func (ctx *CmdCtx) StorageUserWebAuthnImportRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = ctx.providers.StorageProvider.Close()
|
_ = ctx.providers.StorageProvider.Close()
|
||||||
}()
|
}()
|
||||||
|
@ -507,46 +507,46 @@ func (ctx *CmdCtx) StorageUserWebauthnImportRunE(cmd *cobra.Command, args []stri
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
export := &model.WebauthnDeviceExport{}
|
export := &model.WebAuthnDeviceExport{}
|
||||||
|
|
||||||
if err = yaml.Unmarshal(data, export); err != nil {
|
if err = yaml.Unmarshal(data, export); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(export.WebauthnDevices) == 0 {
|
if len(export.WebAuthnDevices) == 0 {
|
||||||
return fmt.Errorf("can't import a YAML file without Webauthn devices data")
|
return fmt.Errorf("can't import a YAML file without WebAuthn devices data")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = ctx.CheckSchema(); err != nil {
|
if err = ctx.CheckSchema(); err != nil {
|
||||||
return storageWrapCheckSchemaErr(err)
|
return storageWrapCheckSchemaErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, device := range export.WebauthnDevices {
|
for _, device := range export.WebAuthnDevices {
|
||||||
if err = ctx.providers.StorageProvider.SaveWebauthnDevice(ctx, device); err != nil {
|
if err = ctx.providers.StorageProvider.SaveWebauthnDevice(ctx, device); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf(cliOutputFmtSuccessfulUserImportFile, len(export.WebauthnDevices), "Webauthn devices", "YAML", filename)
|
fmt.Printf(cliOutputFmtSuccessfulUserImportFile, len(export.WebAuthnDevices), "WebAuthn devices", "YAML", filename)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// StorageUserWebauthnListRunE is the RunE for the authelia storage user webauthn list command.
|
// StorageUserWebAuthnListRunE is the RunE for the authelia storage user webauthn list command.
|
||||||
func (ctx *CmdCtx) StorageUserWebauthnListRunE(cmd *cobra.Command, args []string) (err error) {
|
func (ctx *CmdCtx) StorageUserWebAuthnListRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = ctx.providers.StorageProvider.Close()
|
_ = ctx.providers.StorageProvider.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if len(args) == 0 || args[0] == "" {
|
if len(args) == 0 || args[0] == "" {
|
||||||
return ctx.StorageUserWebauthnListAllRunE(cmd, args)
|
return ctx.StorageUserWebAuthnListAllRunE(cmd, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = ctx.CheckSchema(); err != nil {
|
if err = ctx.CheckSchema(); err != nil {
|
||||||
return storageWrapCheckSchemaErr(err)
|
return storageWrapCheckSchemaErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var devices []model.WebauthnDevice
|
var devices []model.WebAuthnDevice
|
||||||
|
|
||||||
user := args[0]
|
user := args[0]
|
||||||
|
|
||||||
|
@ -558,7 +558,7 @@ func (ctx *CmdCtx) StorageUserWebauthnListRunE(cmd *cobra.Command, args []string
|
||||||
case err != nil:
|
case err != nil:
|
||||||
return fmt.Errorf("can't list devices for user '%s': %w", user, err)
|
return fmt.Errorf("can't list devices for user '%s': %w", user, err)
|
||||||
default:
|
default:
|
||||||
fmt.Printf("Webauthn Devices for user '%s':\n\n", user)
|
fmt.Printf("WebAuthn Devices for user '%s':\n\n", user)
|
||||||
fmt.Printf("ID\tKID\tDescription\n")
|
fmt.Printf("ID\tKID\tDescription\n")
|
||||||
|
|
||||||
for _, device := range devices {
|
for _, device := range devices {
|
||||||
|
@ -569,8 +569,8 @@ func (ctx *CmdCtx) StorageUserWebauthnListRunE(cmd *cobra.Command, args []string
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// StorageUserWebauthnListAllRunE is the RunE for the authelia storage user webauthn list command when no args are specified.
|
// StorageUserWebAuthnListAllRunE is the RunE for the authelia storage user webauthn list command when no args are specified.
|
||||||
func (ctx *CmdCtx) StorageUserWebauthnListAllRunE(_ *cobra.Command, _ []string) (err error) {
|
func (ctx *CmdCtx) StorageUserWebAuthnListAllRunE(_ *cobra.Command, _ []string) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = ctx.providers.StorageProvider.Close()
|
_ = ctx.providers.StorageProvider.Close()
|
||||||
}()
|
}()
|
||||||
|
@ -579,7 +579,7 @@ func (ctx *CmdCtx) StorageUserWebauthnListAllRunE(_ *cobra.Command, _ []string)
|
||||||
return storageWrapCheckSchemaErr(err)
|
return storageWrapCheckSchemaErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var devices []model.WebauthnDevice
|
var devices []model.WebAuthnDevice
|
||||||
|
|
||||||
limit := 10
|
limit := 10
|
||||||
|
|
||||||
|
@ -603,14 +603,14 @@ func (ctx *CmdCtx) StorageUserWebauthnListAllRunE(_ *cobra.Command, _ []string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Webauthn Devices:\n\nID\tKID\tDescription\tUsername\n")
|
fmt.Printf("WebAuthn Devices:\n\nID\tKID\tDescription\tUsername\n")
|
||||||
fmt.Println(output.String())
|
fmt.Println(output.String())
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// StorageUserWebauthnDeleteRunE is the RunE for the authelia storage user webauthn delete command.
|
// StorageUserWebAuthnDeleteRunE is the RunE for the authelia storage user webauthn delete command.
|
||||||
func (ctx *CmdCtx) StorageUserWebauthnDeleteRunE(cmd *cobra.Command, args []string) (err error) {
|
func (ctx *CmdCtx) StorageUserWebAuthnDeleteRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = ctx.providers.StorageProvider.Close()
|
_ = ctx.providers.StorageProvider.Close()
|
||||||
}()
|
}()
|
||||||
|
@ -624,7 +624,7 @@ func (ctx *CmdCtx) StorageUserWebauthnDeleteRunE(cmd *cobra.Command, args []stri
|
||||||
description, kid, user string
|
description, kid, user string
|
||||||
)
|
)
|
||||||
|
|
||||||
if all, byKID, description, kid, user, err = storageWebauthnDeleteRunEOptsFromFlags(cmd.Flags(), args); err != nil {
|
if all, byKID, description, kid, user, err = storageWebAuthnDeleteRunEOptsFromFlags(cmd.Flags(), args); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -633,7 +633,7 @@ func (ctx *CmdCtx) StorageUserWebauthnDeleteRunE(cmd *cobra.Command, args []stri
|
||||||
return fmt.Errorf("failed to delete webauthn device with kid '%s': %w", kid, err)
|
return fmt.Errorf("failed to delete webauthn device with kid '%s': %w", kid, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Successfully deleted Webauthn device with key id '%s'\n", kid)
|
fmt.Printf("Successfully deleted WebAuthn device with key id '%s'\n", kid)
|
||||||
} else {
|
} else {
|
||||||
err = ctx.providers.StorageProvider.DeleteWebauthnDeviceByUsername(ctx, user, description)
|
err = ctx.providers.StorageProvider.DeleteWebauthnDeviceByUsername(ctx, user, description)
|
||||||
|
|
||||||
|
@ -642,13 +642,13 @@ func (ctx *CmdCtx) StorageUserWebauthnDeleteRunE(cmd *cobra.Command, args []stri
|
||||||
return fmt.Errorf("failed to delete all webauthn devices with username '%s': %w", user, err)
|
return fmt.Errorf("failed to delete all webauthn devices with username '%s': %w", user, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Successfully deleted all Webauthn devices for user '%s'\n", user)
|
fmt.Printf("Successfully deleted all WebAuthn devices for user '%s'\n", user)
|
||||||
} else {
|
} else {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to delete webauthn device with username '%s' and description '%s': %w", user, description, err)
|
return fmt.Errorf("failed to delete webauthn device with username '%s' and description '%s': %w", user, description, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Successfully deleted Webauthn device with description '%s' for user '%s'\n", description, user)
|
fmt.Printf("Successfully deleted WebAuthn device with description '%s' for user '%s'\n", description, user)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ var WebauthnIdentityFinish = middlewares.IdentityVerificationFinish(
|
||||||
func SecondFactorWebauthnAttestationGET(ctx *middlewares.AutheliaCtx, _ string) {
|
func SecondFactorWebauthnAttestationGET(ctx *middlewares.AutheliaCtx, _ string) {
|
||||||
var (
|
var (
|
||||||
w *webauthn.WebAuthn
|
w *webauthn.WebAuthn
|
||||||
user *model.WebauthnUser
|
user *model.WebAuthnUser
|
||||||
userSession session.UserSession
|
userSession session.UserSession
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
@ -94,7 +94,7 @@ func WebauthnAttestationPOST(ctx *middlewares.AutheliaCtx) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
w *webauthn.WebAuthn
|
w *webauthn.WebAuthn
|
||||||
user *model.WebauthnUser
|
user *model.WebAuthnUser
|
||||||
|
|
||||||
userSession session.UserSession
|
userSession session.UserSession
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ func WebauthnAttestationPOST(ctx *middlewares.AutheliaCtx) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
device := model.NewWebauthnDeviceFromCredential(w.Config.RPID, userSession.Username, "Primary", credential)
|
device := model.NewWebAuthnDeviceFromCredential(w.Config.RPID, userSession.Username, "Primary", credential)
|
||||||
|
|
||||||
if err = ctx.Providers.StorageProvider.SaveWebauthnDevice(ctx, device); err != nil {
|
if err = ctx.Providers.StorageProvider.SaveWebauthnDevice(ctx, device); err != nil {
|
||||||
ctx.Logger.Errorf("Unable to load %s devices for assertion challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
|
ctx.Logger.Errorf("Unable to load %s devices for assertion challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
|
||||||
|
|
|
@ -16,7 +16,7 @@ import (
|
||||||
func WebauthnAssertionGET(ctx *middlewares.AutheliaCtx) {
|
func WebauthnAssertionGET(ctx *middlewares.AutheliaCtx) {
|
||||||
var (
|
var (
|
||||||
w *webauthn.WebAuthn
|
w *webauthn.WebAuthn
|
||||||
user *model.WebauthnUser
|
user *model.WebAuthnUser
|
||||||
userSession session.UserSession
|
userSession session.UserSession
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
@ -134,7 +134,7 @@ func WebauthnAssertionPOST(ctx *middlewares.AutheliaCtx) {
|
||||||
var (
|
var (
|
||||||
assertionResponse *protocol.ParsedCredentialAssertionData
|
assertionResponse *protocol.ParsedCredentialAssertionData
|
||||||
credential *webauthn.Credential
|
credential *webauthn.Credential
|
||||||
user *model.WebauthnUser
|
user *model.WebAuthnUser
|
||||||
)
|
)
|
||||||
|
|
||||||
if assertionResponse, err = protocol.ParseCredentialRequestResponseBody(bytes.NewReader(ctx.PostBody())); err != nil {
|
if assertionResponse, err = protocol.ParseCredentialRequestResponseBody(bytes.NewReader(ctx.PostBody())); err != nil {
|
||||||
|
|
|
@ -62,7 +62,7 @@ func TestUserInfoEndpoint_SetCorrectMethod(t *testing.T) {
|
||||||
{
|
{
|
||||||
db: model.UserInfo{
|
db: model.UserInfo{
|
||||||
Method: "webauthn",
|
Method: "webauthn",
|
||||||
HasWebauthn: true,
|
HasWebAuthn: true,
|
||||||
HasTOTP: true,
|
HasTOTP: true,
|
||||||
},
|
},
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -70,7 +70,7 @@ func TestUserInfoEndpoint_SetCorrectMethod(t *testing.T) {
|
||||||
{
|
{
|
||||||
db: model.UserInfo{
|
db: model.UserInfo{
|
||||||
Method: "webauthn",
|
Method: "webauthn",
|
||||||
HasWebauthn: true,
|
HasWebAuthn: true,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
},
|
},
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -78,7 +78,7 @@ func TestUserInfoEndpoint_SetCorrectMethod(t *testing.T) {
|
||||||
{
|
{
|
||||||
db: model.UserInfo{
|
db: model.UserInfo{
|
||||||
Method: "mobile_push",
|
Method: "mobile_push",
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
},
|
},
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -128,7 +128,7 @@ func TestUserInfoEndpoint_SetCorrectMethod(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("registered webauthn", func(t *testing.T) {
|
t.Run("registered webauthn", func(t *testing.T) {
|
||||||
assert.Equal(t, resp.api.HasWebauthn, actualPreferences.HasWebauthn)
|
assert.Equal(t, resp.api.HasWebAuthn, actualPreferences.HasWebAuthn)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("registered totp", func(t *testing.T) {
|
t.Run("registered totp", func(t *testing.T) {
|
||||||
|
@ -160,13 +160,13 @@ func TestUserInfoEndpoint_SetDefaultMethod(t *testing.T) {
|
||||||
db: model.UserInfo{
|
db: model.UserInfo{
|
||||||
Method: "",
|
Method: "",
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
},
|
},
|
||||||
api: &model.UserInfo{
|
api: &model.UserInfo{
|
||||||
Method: "totp",
|
Method: "totp",
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
},
|
},
|
||||||
config: &schema.Configuration{},
|
config: &schema.Configuration{},
|
||||||
|
@ -178,13 +178,13 @@ func TestUserInfoEndpoint_SetDefaultMethod(t *testing.T) {
|
||||||
db: model.UserInfo{
|
db: model.UserInfo{
|
||||||
Method: "",
|
Method: "",
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
HasDuo: true,
|
HasDuo: true,
|
||||||
},
|
},
|
||||||
api: &model.UserInfo{
|
api: &model.UserInfo{
|
||||||
Method: "mobile_push",
|
Method: "mobile_push",
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
HasDuo: true,
|
HasDuo: true,
|
||||||
},
|
},
|
||||||
config: &schema.Configuration{},
|
config: &schema.Configuration{},
|
||||||
|
@ -196,13 +196,13 @@ func TestUserInfoEndpoint_SetDefaultMethod(t *testing.T) {
|
||||||
db: model.UserInfo{
|
db: model.UserInfo{
|
||||||
Method: "",
|
Method: "",
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
HasDuo: true,
|
HasDuo: true,
|
||||||
},
|
},
|
||||||
api: &model.UserInfo{
|
api: &model.UserInfo{
|
||||||
Method: "totp",
|
Method: "totp",
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
HasDuo: true,
|
HasDuo: true,
|
||||||
},
|
},
|
||||||
config: &schema.Configuration{DuoAPI: schema.DuoAPIConfiguration{Disable: true}},
|
config: &schema.Configuration{DuoAPI: schema.DuoAPIConfiguration{Disable: true}},
|
||||||
|
@ -214,13 +214,13 @@ func TestUserInfoEndpoint_SetDefaultMethod(t *testing.T) {
|
||||||
db: model.UserInfo{
|
db: model.UserInfo{
|
||||||
Method: "",
|
Method: "",
|
||||||
HasTOTP: true,
|
HasTOTP: true,
|
||||||
HasWebauthn: true,
|
HasWebAuthn: true,
|
||||||
HasDuo: true,
|
HasDuo: true,
|
||||||
},
|
},
|
||||||
api: &model.UserInfo{
|
api: &model.UserInfo{
|
||||||
Method: "webauthn",
|
Method: "webauthn",
|
||||||
HasTOTP: true,
|
HasTOTP: true,
|
||||||
HasWebauthn: true,
|
HasWebAuthn: true,
|
||||||
HasDuo: true,
|
HasDuo: true,
|
||||||
},
|
},
|
||||||
config: &schema.Configuration{
|
config: &schema.Configuration{
|
||||||
|
@ -236,13 +236,13 @@ func TestUserInfoEndpoint_SetDefaultMethod(t *testing.T) {
|
||||||
db: model.UserInfo{
|
db: model.UserInfo{
|
||||||
Method: "",
|
Method: "",
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
},
|
},
|
||||||
api: &model.UserInfo{
|
api: &model.UserInfo{
|
||||||
Method: "totp",
|
Method: "totp",
|
||||||
HasTOTP: true,
|
HasTOTP: true,
|
||||||
HasWebauthn: true,
|
HasWebAuthn: true,
|
||||||
HasDuo: true,
|
HasDuo: true,
|
||||||
},
|
},
|
||||||
config: &schema.Configuration{},
|
config: &schema.Configuration{},
|
||||||
|
@ -322,7 +322,7 @@ func TestUserInfoEndpoint_SetDefaultMethod(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("registered webauthn", func(t *testing.T) {
|
t.Run("registered webauthn", func(t *testing.T) {
|
||||||
assert.Equal(t, resp.api.HasWebauthn, actualPreferences.HasWebauthn)
|
assert.Equal(t, resp.api.HasWebAuthn, actualPreferences.HasWebAuthn)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("registered totp", func(t *testing.T) {
|
t.Run("registered totp", func(t *testing.T) {
|
||||||
|
|
|
@ -12,8 +12,8 @@ import (
|
||||||
"github.com/authelia/authelia/v4/internal/session"
|
"github.com/authelia/authelia/v4/internal/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getWebAuthnUser(ctx *middlewares.AutheliaCtx, userSession session.UserSession) (user *model.WebauthnUser, err error) {
|
func getWebAuthnUser(ctx *middlewares.AutheliaCtx, userSession session.UserSession) (user *model.WebAuthnUser, err error) {
|
||||||
user = &model.WebauthnUser{
|
user = &model.WebAuthnUser{
|
||||||
Username: userSession.Username,
|
Username: userSession.Username,
|
||||||
DisplayName: userSession.DisplayName,
|
DisplayName: userSession.DisplayName,
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ func TestWebauthnGetUser(t *testing.T) {
|
||||||
DisplayName: "John Smith",
|
DisplayName: "John Smith",
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.StorageMock.EXPECT().LoadWebauthnDevicesByUsername(ctx.Ctx, "john").Return([]model.WebauthnDevice{
|
ctx.StorageMock.EXPECT().LoadWebauthnDevicesByUsername(ctx.Ctx, "john").Return([]model.WebAuthnDevice{
|
||||||
{
|
{
|
||||||
ID: 1,
|
ID: 1,
|
||||||
RPID: "https://example.com",
|
RPID: "https://example.com",
|
||||||
|
@ -106,7 +106,7 @@ func TestWebauthnGetUserWithoutDisplayName(t *testing.T) {
|
||||||
Username: "john",
|
Username: "john",
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.StorageMock.EXPECT().LoadWebauthnDevicesByUsername(ctx.Ctx, "john").Return([]model.WebauthnDevice{
|
ctx.StorageMock.EXPECT().LoadWebauthnDevicesByUsername(ctx.Ctx, "john").Return([]model.WebAuthnDevice{
|
||||||
{
|
{
|
||||||
ID: 1,
|
ID: 1,
|
||||||
RPID: "https://example.com",
|
RPID: "https://example.com",
|
||||||
|
|
|
@ -50,7 +50,7 @@ func (ctx *AutheliaCtx) AvailableSecondFactorMethods() (methods []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ctx.Configuration.Webauthn.Disable {
|
if !ctx.Configuration.Webauthn.Disable {
|
||||||
methods = append(methods, model.SecondFactorMethodWebauthn)
|
methods = append(methods, model.SecondFactorMethodWebAuthn)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ctx.Configuration.DuoAPI.Disable {
|
if !ctx.Configuration.DuoAPI.Disable {
|
||||||
|
|
|
@ -235,15 +235,15 @@ func TestShouldReturnCorrectSecondFactorMethods(t *testing.T) {
|
||||||
|
|
||||||
mock.Ctx.Configuration.DuoAPI.Disable = true
|
mock.Ctx.Configuration.DuoAPI.Disable = true
|
||||||
|
|
||||||
assert.Equal(t, []string{model.SecondFactorMethodTOTP, model.SecondFactorMethodWebauthn}, mock.Ctx.AvailableSecondFactorMethods())
|
assert.Equal(t, []string{model.SecondFactorMethodTOTP, model.SecondFactorMethodWebAuthn}, mock.Ctx.AvailableSecondFactorMethods())
|
||||||
|
|
||||||
mock.Ctx.Configuration.DuoAPI.Disable = false
|
mock.Ctx.Configuration.DuoAPI.Disable = false
|
||||||
|
|
||||||
assert.Equal(t, []string{model.SecondFactorMethodTOTP, model.SecondFactorMethodWebauthn, model.SecondFactorMethodDuo}, mock.Ctx.AvailableSecondFactorMethods())
|
assert.Equal(t, []string{model.SecondFactorMethodTOTP, model.SecondFactorMethodWebAuthn, model.SecondFactorMethodDuo}, mock.Ctx.AvailableSecondFactorMethods())
|
||||||
|
|
||||||
mock.Ctx.Configuration.TOTP.Disable = true
|
mock.Ctx.Configuration.TOTP.Disable = true
|
||||||
|
|
||||||
assert.Equal(t, []string{model.SecondFactorMethodWebauthn, model.SecondFactorMethodDuo}, mock.Ctx.AvailableSecondFactorMethods())
|
assert.Equal(t, []string{model.SecondFactorMethodWebAuthn, model.SecondFactorMethodDuo}, mock.Ctx.AvailableSecondFactorMethods())
|
||||||
|
|
||||||
mock.Ctx.Configuration.Webauthn.Disable = true
|
mock.Ctx.Configuration.Webauthn.Disable = true
|
||||||
|
|
||||||
|
|
|
@ -421,10 +421,10 @@ func (mr *MockStorageMockRecorder) LoadUserOpaqueIdentifiers(arg0 interface{}) *
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadWebauthnDevices mocks base method.
|
// LoadWebauthnDevices mocks base method.
|
||||||
func (m *MockStorage) LoadWebauthnDevices(arg0 context.Context, arg1, arg2 int) ([]model.WebauthnDevice, error) {
|
func (m *MockStorage) LoadWebauthnDevices(arg0 context.Context, arg1, arg2 int) ([]model.WebAuthnDevice, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "LoadWebauthnDevices", arg0, arg1, arg2)
|
ret := m.ctrl.Call(m, "LoadWebauthnDevices", arg0, arg1, arg2)
|
||||||
ret0, _ := ret[0].([]model.WebauthnDevice)
|
ret0, _ := ret[0].([]model.WebAuthnDevice)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
@ -436,10 +436,10 @@ func (mr *MockStorageMockRecorder) LoadWebauthnDevices(arg0, arg1, arg2 interfac
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadWebauthnDevicesByUsername mocks base method.
|
// LoadWebauthnDevicesByUsername mocks base method.
|
||||||
func (m *MockStorage) LoadWebauthnDevicesByUsername(arg0 context.Context, arg1 string) ([]model.WebauthnDevice, error) {
|
func (m *MockStorage) LoadWebauthnDevicesByUsername(arg0 context.Context, arg1 string) ([]model.WebAuthnDevice, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "LoadWebauthnDevicesByUsername", arg0, arg1)
|
ret := m.ctrl.Call(m, "LoadWebauthnDevicesByUsername", arg0, arg1)
|
||||||
ret0, _ := ret[0].([]model.WebauthnDevice)
|
ret0, _ := ret[0].([]model.WebAuthnDevice)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
@ -690,7 +690,7 @@ func (mr *MockStorageMockRecorder) SaveUserOpaqueIdentifier(arg0, arg1 interface
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveWebauthnDevice mocks base method.
|
// SaveWebauthnDevice mocks base method.
|
||||||
func (m *MockStorage) SaveWebauthnDevice(arg0 context.Context, arg1 model.WebauthnDevice) error {
|
func (m *MockStorage) SaveWebauthnDevice(arg0 context.Context, arg1 model.WebAuthnDevice) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "SaveWebauthnDevice", arg0, arg1)
|
ret := m.ctrl.Call(m, "SaveWebauthnDevice", arg0, arg1)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
|
|
|
@ -15,8 +15,8 @@ const (
|
||||||
// SecondFactorMethodTOTP method using Time-Based One-Time Password applications like Google Authenticator.
|
// SecondFactorMethodTOTP method using Time-Based One-Time Password applications like Google Authenticator.
|
||||||
SecondFactorMethodTOTP = "totp"
|
SecondFactorMethodTOTP = "totp"
|
||||||
|
|
||||||
// SecondFactorMethodWebauthn method using Webauthn devices like YubiKey's.
|
// SecondFactorMethodWebAuthn method using WebAuthn devices like YubiKey's.
|
||||||
SecondFactorMethodWebauthn = "webauthn"
|
SecondFactorMethodWebAuthn = "webauthn"
|
||||||
|
|
||||||
// SecondFactorMethodDuo method using Duo application to receive push notifications.
|
// SecondFactorMethodDuo method using Duo application to receive push notifications.
|
||||||
SecondFactorMethodDuo = "mobile_push"
|
SecondFactorMethodDuo = "mobile_push"
|
||||||
|
|
|
@ -15,8 +15,8 @@ type UserInfo struct {
|
||||||
// True if a TOTP device has been registered.
|
// True if a TOTP device has been registered.
|
||||||
HasTOTP bool `db:"has_totp" json:"has_totp" valid:"required"`
|
HasTOTP bool `db:"has_totp" json:"has_totp" valid:"required"`
|
||||||
|
|
||||||
// True if a Webauthn device has been registered.
|
// True if a WebAuthn device has been registered.
|
||||||
HasWebauthn bool `db:"has_webauthn" json:"has_webauthn" valid:"required"`
|
HasWebAuthn bool `db:"has_webauthn" json:"has_webauthn" valid:"required"`
|
||||||
|
|
||||||
// True if a duo device has been configured as the preferred.
|
// True if a duo device has been configured as the preferred.
|
||||||
HasDuo bool `db:"has_duo" json:"has_duo" valid:"required"`
|
HasDuo bool `db:"has_duo" json:"has_duo" valid:"required"`
|
||||||
|
@ -31,7 +31,7 @@ func (i *UserInfo) SetDefaultPreferred2FAMethod(methods []string, fallback strin
|
||||||
|
|
||||||
before := i.Method
|
before := i.Method
|
||||||
|
|
||||||
totp, webauthn, duo := utils.IsStringInSlice(SecondFactorMethodTOTP, methods), utils.IsStringInSlice(SecondFactorMethodWebauthn, methods), utils.IsStringInSlice(SecondFactorMethodDuo, methods)
|
totp, webauthn, duo := utils.IsStringInSlice(SecondFactorMethodTOTP, methods), utils.IsStringInSlice(SecondFactorMethodWebAuthn, methods), utils.IsStringInSlice(SecondFactorMethodDuo, methods)
|
||||||
|
|
||||||
if i.Method == "" && utils.IsStringInSlice(fallback, methods) {
|
if i.Method == "" && utils.IsStringInSlice(fallback, methods) {
|
||||||
i.Method = fallback
|
i.Method = fallback
|
||||||
|
@ -50,8 +50,8 @@ func (i *UserInfo) setMethod(totp, webauthn, duo bool, methods []string, fallbac
|
||||||
switch {
|
switch {
|
||||||
case i.HasTOTP && totp:
|
case i.HasTOTP && totp:
|
||||||
i.Method = SecondFactorMethodTOTP
|
i.Method = SecondFactorMethodTOTP
|
||||||
case i.HasWebauthn && webauthn:
|
case i.HasWebAuthn && webauthn:
|
||||||
i.Method = SecondFactorMethodWebauthn
|
i.Method = SecondFactorMethodWebAuthn
|
||||||
case i.HasDuo && duo:
|
case i.HasDuo && duo:
|
||||||
i.Method = SecondFactorMethodDuo
|
i.Method = SecondFactorMethodDuo
|
||||||
case fallback != "" && utils.IsStringInSlice(fallback, methods):
|
case fallback != "" && utils.IsStringInSlice(fallback, methods):
|
||||||
|
@ -59,7 +59,7 @@ func (i *UserInfo) setMethod(totp, webauthn, duo bool, methods []string, fallbac
|
||||||
case totp:
|
case totp:
|
||||||
i.Method = SecondFactorMethodTOTP
|
i.Method = SecondFactorMethodTOTP
|
||||||
case webauthn:
|
case webauthn:
|
||||||
i.Method = SecondFactorMethodWebauthn
|
i.Method = SecondFactorMethodWebAuthn
|
||||||
case duo:
|
case duo:
|
||||||
i.Method = SecondFactorMethodDuo
|
i.Method = SecondFactorMethodDuo
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ func TestUserInfo_SetDefaultMethod(t *testing.T) {
|
||||||
|
|
||||||
has := ""
|
has := ""
|
||||||
|
|
||||||
if have.HasTOTP || have.HasDuo || have.HasWebauthn {
|
if have.HasTOTP || have.HasDuo || have.HasWebAuthn {
|
||||||
has += " has"
|
has += " has"
|
||||||
|
|
||||||
if have.HasTOTP {
|
if have.HasTOTP {
|
||||||
|
@ -31,8 +31,8 @@ func TestUserInfo_SetDefaultMethod(t *testing.T) {
|
||||||
has += " " + SecondFactorMethodDuo
|
has += " " + SecondFactorMethodDuo
|
||||||
}
|
}
|
||||||
|
|
||||||
if have.HasWebauthn {
|
if have.HasWebAuthn {
|
||||||
has += " " + SecondFactorMethodWebauthn
|
has += " " + SecondFactorMethodWebAuthn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,60 +62,60 @@ func TestUserInfo_SetDefaultMethod(t *testing.T) {
|
||||||
Method: SecondFactorMethodTOTP,
|
Method: SecondFactorMethodTOTP,
|
||||||
HasDuo: true,
|
HasDuo: true,
|
||||||
HasTOTP: true,
|
HasTOTP: true,
|
||||||
HasWebauthn: true,
|
HasWebAuthn: true,
|
||||||
},
|
},
|
||||||
want: UserInfo{
|
want: UserInfo{
|
||||||
Method: SecondFactorMethodWebauthn,
|
Method: SecondFactorMethodWebAuthn,
|
||||||
HasDuo: true,
|
HasDuo: true,
|
||||||
HasTOTP: true,
|
HasTOTP: true,
|
||||||
HasWebauthn: true,
|
HasWebAuthn: true,
|
||||||
},
|
},
|
||||||
methods: []string{SecondFactorMethodWebauthn, SecondFactorMethodDuo},
|
methods: []string{SecondFactorMethodWebAuthn, SecondFactorMethodDuo},
|
||||||
changed: true,
|
changed: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
have: UserInfo{
|
have: UserInfo{
|
||||||
HasDuo: true,
|
HasDuo: true,
|
||||||
HasTOTP: true,
|
HasTOTP: true,
|
||||||
HasWebauthn: true,
|
HasWebAuthn: true,
|
||||||
},
|
},
|
||||||
want: UserInfo{
|
want: UserInfo{
|
||||||
Method: SecondFactorMethodTOTP,
|
Method: SecondFactorMethodTOTP,
|
||||||
HasDuo: true,
|
HasDuo: true,
|
||||||
HasTOTP: true,
|
HasTOTP: true,
|
||||||
HasWebauthn: true,
|
HasWebAuthn: true,
|
||||||
},
|
},
|
||||||
methods: []string{SecondFactorMethodTOTP, SecondFactorMethodWebauthn, SecondFactorMethodDuo},
|
methods: []string{SecondFactorMethodTOTP, SecondFactorMethodWebAuthn, SecondFactorMethodDuo},
|
||||||
changed: true,
|
changed: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
have: UserInfo{
|
have: UserInfo{
|
||||||
Method: SecondFactorMethodWebauthn,
|
Method: SecondFactorMethodWebAuthn,
|
||||||
HasDuo: true,
|
HasDuo: true,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
},
|
},
|
||||||
want: UserInfo{
|
want: UserInfo{
|
||||||
Method: SecondFactorMethodTOTP,
|
Method: SecondFactorMethodTOTP,
|
||||||
HasDuo: true,
|
HasDuo: true,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
},
|
},
|
||||||
methods: []string{SecondFactorMethodTOTP},
|
methods: []string{SecondFactorMethodTOTP},
|
||||||
changed: true,
|
changed: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
have: UserInfo{
|
have: UserInfo{
|
||||||
Method: SecondFactorMethodWebauthn,
|
Method: SecondFactorMethodWebAuthn,
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
},
|
},
|
||||||
want: UserInfo{
|
want: UserInfo{
|
||||||
Method: SecondFactorMethodTOTP,
|
Method: SecondFactorMethodTOTP,
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
},
|
},
|
||||||
methods: []string{SecondFactorMethodTOTP},
|
methods: []string{SecondFactorMethodTOTP},
|
||||||
changed: true,
|
changed: true,
|
||||||
|
@ -125,15 +125,15 @@ func TestUserInfo_SetDefaultMethod(t *testing.T) {
|
||||||
Method: SecondFactorMethodTOTP,
|
Method: SecondFactorMethodTOTP,
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
},
|
},
|
||||||
want: UserInfo{
|
want: UserInfo{
|
||||||
Method: SecondFactorMethodWebauthn,
|
Method: SecondFactorMethodWebAuthn,
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
},
|
},
|
||||||
methods: []string{SecondFactorMethodWebauthn},
|
methods: []string{SecondFactorMethodWebAuthn},
|
||||||
changed: true,
|
changed: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -141,31 +141,31 @@ func TestUserInfo_SetDefaultMethod(t *testing.T) {
|
||||||
Method: SecondFactorMethodTOTP,
|
Method: SecondFactorMethodTOTP,
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
},
|
},
|
||||||
want: UserInfo{
|
want: UserInfo{
|
||||||
Method: SecondFactorMethodDuo,
|
Method: SecondFactorMethodDuo,
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
},
|
},
|
||||||
methods: []string{SecondFactorMethodDuo},
|
methods: []string{SecondFactorMethodDuo},
|
||||||
changed: true,
|
changed: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
have: UserInfo{
|
have: UserInfo{
|
||||||
Method: SecondFactorMethodWebauthn,
|
Method: SecondFactorMethodWebAuthn,
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: true,
|
HasTOTP: true,
|
||||||
HasWebauthn: true,
|
HasWebAuthn: true,
|
||||||
},
|
},
|
||||||
want: UserInfo{
|
want: UserInfo{
|
||||||
Method: SecondFactorMethodWebauthn,
|
Method: SecondFactorMethodWebAuthn,
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: true,
|
HasTOTP: true,
|
||||||
HasWebauthn: true,
|
HasWebAuthn: true,
|
||||||
},
|
},
|
||||||
methods: []string{SecondFactorMethodTOTP, SecondFactorMethodWebauthn, SecondFactorMethodDuo},
|
methods: []string{SecondFactorMethodTOTP, SecondFactorMethodWebAuthn, SecondFactorMethodDuo},
|
||||||
changed: false,
|
changed: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -173,15 +173,15 @@ func TestUserInfo_SetDefaultMethod(t *testing.T) {
|
||||||
Method: "",
|
Method: "",
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: true,
|
HasTOTP: true,
|
||||||
HasWebauthn: true,
|
HasWebAuthn: true,
|
||||||
},
|
},
|
||||||
want: UserInfo{
|
want: UserInfo{
|
||||||
Method: SecondFactorMethodWebauthn,
|
Method: SecondFactorMethodWebAuthn,
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: true,
|
HasTOTP: true,
|
||||||
HasWebauthn: true,
|
HasWebAuthn: true,
|
||||||
},
|
},
|
||||||
methods: []string{SecondFactorMethodWebauthn, SecondFactorMethodDuo},
|
methods: []string{SecondFactorMethodWebAuthn, SecondFactorMethodDuo},
|
||||||
changed: true,
|
changed: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -189,13 +189,13 @@ func TestUserInfo_SetDefaultMethod(t *testing.T) {
|
||||||
Method: "",
|
Method: "",
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: true,
|
HasTOTP: true,
|
||||||
HasWebauthn: true,
|
HasWebAuthn: true,
|
||||||
},
|
},
|
||||||
want: UserInfo{
|
want: UserInfo{
|
||||||
Method: SecondFactorMethodDuo,
|
Method: SecondFactorMethodDuo,
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: true,
|
HasTOTP: true,
|
||||||
HasWebauthn: true,
|
HasWebAuthn: true,
|
||||||
},
|
},
|
||||||
methods: []string{SecondFactorMethodDuo},
|
methods: []string{SecondFactorMethodDuo},
|
||||||
changed: true,
|
changed: true,
|
||||||
|
@ -205,13 +205,13 @@ func TestUserInfo_SetDefaultMethod(t *testing.T) {
|
||||||
Method: "",
|
Method: "",
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: true,
|
HasTOTP: true,
|
||||||
HasWebauthn: true,
|
HasWebAuthn: true,
|
||||||
},
|
},
|
||||||
want: UserInfo{
|
want: UserInfo{
|
||||||
Method: "",
|
Method: "",
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: true,
|
HasTOTP: true,
|
||||||
HasWebauthn: true,
|
HasWebAuthn: true,
|
||||||
},
|
},
|
||||||
methods: nil,
|
methods: nil,
|
||||||
changed: false,
|
changed: false,
|
||||||
|
@ -221,15 +221,15 @@ func TestUserInfo_SetDefaultMethod(t *testing.T) {
|
||||||
Method: "",
|
Method: "",
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
},
|
},
|
||||||
want: UserInfo{
|
want: UserInfo{
|
||||||
Method: SecondFactorMethodDuo,
|
Method: SecondFactorMethodDuo,
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
},
|
},
|
||||||
methods: []string{SecondFactorMethodTOTP, SecondFactorMethodWebauthn, SecondFactorMethodDuo},
|
methods: []string{SecondFactorMethodTOTP, SecondFactorMethodWebAuthn, SecondFactorMethodDuo},
|
||||||
fallback: SecondFactorMethodDuo,
|
fallback: SecondFactorMethodDuo,
|
||||||
changed: true,
|
changed: true,
|
||||||
},
|
},
|
||||||
|
@ -238,15 +238,15 @@ func TestUserInfo_SetDefaultMethod(t *testing.T) {
|
||||||
Method: "",
|
Method: "",
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
},
|
},
|
||||||
want: UserInfo{
|
want: UserInfo{
|
||||||
Method: SecondFactorMethodTOTP,
|
Method: SecondFactorMethodTOTP,
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
},
|
},
|
||||||
methods: []string{SecondFactorMethodTOTP, SecondFactorMethodWebauthn},
|
methods: []string{SecondFactorMethodTOTP, SecondFactorMethodWebAuthn},
|
||||||
fallback: SecondFactorMethodDuo,
|
fallback: SecondFactorMethodDuo,
|
||||||
changed: true,
|
changed: true,
|
||||||
},
|
},
|
||||||
|
@ -255,15 +255,15 @@ func TestUserInfo_SetDefaultMethod(t *testing.T) {
|
||||||
Method: SecondFactorMethodTOTP,
|
Method: SecondFactorMethodTOTP,
|
||||||
HasDuo: true,
|
HasDuo: true,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
},
|
},
|
||||||
want: UserInfo{
|
want: UserInfo{
|
||||||
Method: SecondFactorMethodDuo,
|
Method: SecondFactorMethodDuo,
|
||||||
HasDuo: true,
|
HasDuo: true,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
},
|
},
|
||||||
methods: []string{SecondFactorMethodWebauthn, SecondFactorMethodDuo},
|
methods: []string{SecondFactorMethodWebAuthn, SecondFactorMethodDuo},
|
||||||
changed: true,
|
changed: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -271,30 +271,30 @@ func TestUserInfo_SetDefaultMethod(t *testing.T) {
|
||||||
Method: SecondFactorMethodTOTP,
|
Method: SecondFactorMethodTOTP,
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
},
|
},
|
||||||
want: UserInfo{
|
want: UserInfo{
|
||||||
Method: SecondFactorMethodWebauthn,
|
Method: SecondFactorMethodWebAuthn,
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
},
|
},
|
||||||
methods: []string{SecondFactorMethodWebauthn, SecondFactorMethodDuo},
|
methods: []string{SecondFactorMethodWebAuthn, SecondFactorMethodDuo},
|
||||||
fallback: SecondFactorMethodWebauthn,
|
fallback: SecondFactorMethodWebAuthn,
|
||||||
changed: true,
|
changed: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
have: UserInfo{
|
have: UserInfo{
|
||||||
Method: SecondFactorMethodWebauthn,
|
Method: SecondFactorMethodWebAuthn,
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
},
|
},
|
||||||
want: UserInfo{
|
want: UserInfo{
|
||||||
Method: SecondFactorMethodDuo,
|
Method: SecondFactorMethodDuo,
|
||||||
HasDuo: false,
|
HasDuo: false,
|
||||||
HasTOTP: false,
|
HasTOTP: false,
|
||||||
HasWebauthn: false,
|
HasWebAuthn: false,
|
||||||
},
|
},
|
||||||
methods: []string{SecondFactorMethodTOTP, SecondFactorMethodDuo},
|
methods: []string{SecondFactorMethodTOTP, SecondFactorMethodDuo},
|
||||||
fallback: SecondFactorMethodDuo,
|
fallback: SecondFactorMethodDuo,
|
||||||
|
|
|
@ -17,15 +17,15 @@ const (
|
||||||
attestationTypeFIDOU2F = "fido-u2f"
|
attestationTypeFIDOU2F = "fido-u2f"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WebauthnUser is an object to represent a user for the Webauthn lib.
|
// WebAuthnUser is an object to represent a user for the WebAuthn lib.
|
||||||
type WebauthnUser struct {
|
type WebAuthnUser struct {
|
||||||
Username string
|
Username string
|
||||||
DisplayName string
|
DisplayName string
|
||||||
Devices []WebauthnDevice
|
Devices []WebAuthnDevice
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasFIDOU2F returns true if the user has any attestation type `fido-u2f` devices.
|
// HasFIDOU2F returns true if the user has any attestation type `fido-u2f` devices.
|
||||||
func (w WebauthnUser) HasFIDOU2F() bool {
|
func (w WebAuthnUser) HasFIDOU2F() bool {
|
||||||
for _, c := range w.Devices {
|
for _, c := range w.Devices {
|
||||||
if c.AttestationType == attestationTypeFIDOU2F {
|
if c.AttestationType == attestationTypeFIDOU2F {
|
||||||
return true
|
return true
|
||||||
|
@ -36,27 +36,27 @@ func (w WebauthnUser) HasFIDOU2F() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebAuthnID implements the webauthn.User interface.
|
// WebAuthnID implements the webauthn.User interface.
|
||||||
func (w WebauthnUser) WebAuthnID() []byte {
|
func (w WebAuthnUser) WebAuthnID() []byte {
|
||||||
return []byte(w.Username)
|
return []byte(w.Username)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebAuthnName implements the webauthn.User interface.
|
// WebAuthnName implements the webauthn.User interface.
|
||||||
func (w WebauthnUser) WebAuthnName() string {
|
func (w WebAuthnUser) WebAuthnName() string {
|
||||||
return w.Username
|
return w.Username
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebAuthnDisplayName implements the webauthn.User interface.
|
// WebAuthnDisplayName implements the webauthn.User interface.
|
||||||
func (w WebauthnUser) WebAuthnDisplayName() string {
|
func (w WebAuthnUser) WebAuthnDisplayName() string {
|
||||||
return w.DisplayName
|
return w.DisplayName
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebAuthnIcon implements the webauthn.User interface.
|
// WebAuthnIcon implements the webauthn.User interface.
|
||||||
func (w WebauthnUser) WebAuthnIcon() string {
|
func (w WebAuthnUser) WebAuthnIcon() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebAuthnCredentials implements the webauthn.User interface.
|
// WebAuthnCredentials implements the webauthn.User interface.
|
||||||
func (w WebauthnUser) WebAuthnCredentials() (credentials []webauthn.Credential) {
|
func (w WebAuthnUser) WebAuthnCredentials() (credentials []webauthn.Credential) {
|
||||||
credentials = make([]webauthn.Credential, len(w.Devices))
|
credentials = make([]webauthn.Credential, len(w.Devices))
|
||||||
|
|
||||||
var credential webauthn.Credential
|
var credential webauthn.Credential
|
||||||
|
@ -96,7 +96,7 @@ func (w WebauthnUser) WebAuthnCredentials() (credentials []webauthn.Credential)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebAuthnCredentialDescriptors decodes the users credentials into protocol.CredentialDescriptor's.
|
// WebAuthnCredentialDescriptors decodes the users credentials into protocol.CredentialDescriptor's.
|
||||||
func (w WebauthnUser) WebAuthnCredentialDescriptors() (descriptors []protocol.CredentialDescriptor) {
|
func (w WebAuthnUser) WebAuthnCredentialDescriptors() (descriptors []protocol.CredentialDescriptor) {
|
||||||
credentials := w.WebAuthnCredentials()
|
credentials := w.WebAuthnCredentials()
|
||||||
|
|
||||||
descriptors = make([]protocol.CredentialDescriptor, len(credentials))
|
descriptors = make([]protocol.CredentialDescriptor, len(credentials))
|
||||||
|
@ -108,15 +108,15 @@ func (w WebauthnUser) WebAuthnCredentialDescriptors() (descriptors []protocol.Cr
|
||||||
return descriptors
|
return descriptors
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWebauthnDeviceFromCredential creates a WebauthnDevice from a webauthn.Credential.
|
// NewWebAuthnDeviceFromCredential creates a WebAuthnDevice from a webauthn.Credential.
|
||||||
func NewWebauthnDeviceFromCredential(rpid, username, description string, credential *webauthn.Credential) (device WebauthnDevice) {
|
func NewWebAuthnDeviceFromCredential(rpid, username, description string, credential *webauthn.Credential) (device WebAuthnDevice) {
|
||||||
transport := make([]string, len(credential.Transport))
|
transport := make([]string, len(credential.Transport))
|
||||||
|
|
||||||
for i, t := range credential.Transport {
|
for i, t := range credential.Transport {
|
||||||
transport[i] = string(t)
|
transport[i] = string(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
device = WebauthnDevice{
|
device = WebAuthnDevice{
|
||||||
RPID: rpid,
|
RPID: rpid,
|
||||||
Username: username,
|
Username: username,
|
||||||
CreatedAt: time.Now(),
|
CreatedAt: time.Now(),
|
||||||
|
@ -137,8 +137,8 @@ func NewWebauthnDeviceFromCredential(rpid, username, description string, credent
|
||||||
return device
|
return device
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebauthnDevice represents a Webauthn Device in the database storage.
|
// WebAuthnDevice represents a WebAuthn Device in the database storage.
|
||||||
type WebauthnDevice struct {
|
type WebAuthnDevice struct {
|
||||||
ID int `db:"id"`
|
ID int `db:"id"`
|
||||||
CreatedAt time.Time `db:"created_at"`
|
CreatedAt time.Time `db:"created_at"`
|
||||||
LastUsedAt sql.NullTime `db:"last_used_at"`
|
LastUsedAt sql.NullTime `db:"last_used_at"`
|
||||||
|
@ -154,8 +154,8 @@ type WebauthnDevice struct {
|
||||||
CloneWarning bool `db:"clone_warning"`
|
CloneWarning bool `db:"clone_warning"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateSignInInfo adjusts the values of the WebauthnDevice after a sign in.
|
// UpdateSignInInfo adjusts the values of the WebAuthnDevice after a sign in.
|
||||||
func (d *WebauthnDevice) UpdateSignInInfo(config *webauthn.Config, now time.Time, signCount uint32) {
|
func (d *WebAuthnDevice) UpdateSignInInfo(config *webauthn.Config, now time.Time, signCount uint32) {
|
||||||
d.LastUsedAt = sql.NullTime{Time: now, Valid: true}
|
d.LastUsedAt = sql.NullTime{Time: now, Valid: true}
|
||||||
|
|
||||||
d.SignCount = signCount
|
d.SignCount = signCount
|
||||||
|
@ -172,7 +172,7 @@ func (d *WebauthnDevice) UpdateSignInInfo(config *webauthn.Config, now time.Time
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *WebauthnDevice) LastUsed() *time.Time {
|
func (d *WebAuthnDevice) LastUsed() *time.Time {
|
||||||
if d.LastUsedAt.Valid {
|
if d.LastUsedAt.Valid {
|
||||||
return &d.LastUsedAt.Time
|
return &d.LastUsedAt.Time
|
||||||
}
|
}
|
||||||
|
@ -181,8 +181,8 @@ func (d *WebauthnDevice) LastUsed() *time.Time {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalYAML marshals this model into YAML.
|
// MarshalYAML marshals this model into YAML.
|
||||||
func (d *WebauthnDevice) MarshalYAML() (any, error) {
|
func (d *WebAuthnDevice) MarshalYAML() (any, error) {
|
||||||
o := WebauthnDeviceData{
|
o := WebAuthnDeviceData{
|
||||||
CreatedAt: d.CreatedAt,
|
CreatedAt: d.CreatedAt,
|
||||||
LastUsedAt: d.LastUsed(),
|
LastUsedAt: d.LastUsed(),
|
||||||
RPID: d.RPID,
|
RPID: d.RPID,
|
||||||
|
@ -201,8 +201,8 @@ func (d *WebauthnDevice) MarshalYAML() (any, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalYAML unmarshalls YAML into this model.
|
// UnmarshalYAML unmarshalls YAML into this model.
|
||||||
func (d *WebauthnDevice) UnmarshalYAML(value *yaml.Node) (err error) {
|
func (d *WebAuthnDevice) UnmarshalYAML(value *yaml.Node) (err error) {
|
||||||
o := &WebauthnDeviceData{}
|
o := &WebAuthnDeviceData{}
|
||||||
|
|
||||||
if err = value.Decode(o); err != nil {
|
if err = value.Decode(o); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -246,8 +246,8 @@ func (d *WebauthnDevice) UnmarshalYAML(value *yaml.Node) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebauthnDeviceData represents a Webauthn Device in the database storage.
|
// WebAuthnDeviceData represents a WebAuthn Device in the database storage.
|
||||||
type WebauthnDeviceData struct {
|
type WebAuthnDeviceData struct {
|
||||||
CreatedAt time.Time `yaml:"created_at"`
|
CreatedAt time.Time `yaml:"created_at"`
|
||||||
LastUsedAt *time.Time `yaml:"last_used_at"`
|
LastUsedAt *time.Time `yaml:"last_used_at"`
|
||||||
RPID string `yaml:"rpid"`
|
RPID string `yaml:"rpid"`
|
||||||
|
@ -262,7 +262,7 @@ type WebauthnDeviceData struct {
|
||||||
CloneWarning bool `yaml:"clone_warning"`
|
CloneWarning bool `yaml:"clone_warning"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebauthnDeviceExport represents a WebauthnDevice export file.
|
// WebAuthnDeviceExport represents a WebAuthnDevice export file.
|
||||||
type WebauthnDeviceExport struct {
|
type WebAuthnDeviceExport struct {
|
||||||
WebauthnDevices []WebauthnDevice `yaml:"webauthn_devices"`
|
WebAuthnDevices []WebAuthnDevice `yaml:"webauthn_devices"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,12 +38,12 @@ type Provider interface {
|
||||||
LoadTOTPConfiguration(ctx context.Context, username string) (config *model.TOTPConfiguration, err error)
|
LoadTOTPConfiguration(ctx context.Context, username string) (config *model.TOTPConfiguration, err error)
|
||||||
LoadTOTPConfigurations(ctx context.Context, limit, page int) (configs []model.TOTPConfiguration, err error)
|
LoadTOTPConfigurations(ctx context.Context, limit, page int) (configs []model.TOTPConfiguration, err error)
|
||||||
|
|
||||||
SaveWebauthnDevice(ctx context.Context, device model.WebauthnDevice) (err error)
|
SaveWebauthnDevice(ctx context.Context, device model.WebAuthnDevice) (err error)
|
||||||
UpdateWebauthnDeviceSignIn(ctx context.Context, id int, rpid string, lastUsedAt sql.NullTime, signCount uint32, cloneWarning bool) (err error)
|
UpdateWebauthnDeviceSignIn(ctx context.Context, id int, rpid string, lastUsedAt sql.NullTime, signCount uint32, cloneWarning bool) (err error)
|
||||||
DeleteWebauthnDevice(ctx context.Context, kid string) (err error)
|
DeleteWebauthnDevice(ctx context.Context, kid string) (err error)
|
||||||
DeleteWebauthnDeviceByUsername(ctx context.Context, username, description string) (err error)
|
DeleteWebauthnDeviceByUsername(ctx context.Context, username, description string) (err error)
|
||||||
LoadWebauthnDevices(ctx context.Context, limit, page int) (devices []model.WebauthnDevice, err error)
|
LoadWebauthnDevices(ctx context.Context, limit, page int) (devices []model.WebAuthnDevice, err error)
|
||||||
LoadWebauthnDevicesByUsername(ctx context.Context, username string) (devices []model.WebauthnDevice, err error)
|
LoadWebauthnDevicesByUsername(ctx context.Context, username string) (devices []model.WebAuthnDevice, err error)
|
||||||
|
|
||||||
SavePreferredDuoDevice(ctx context.Context, device model.DuoDevice) (err error)
|
SavePreferredDuoDevice(ctx context.Context, device model.DuoDevice) (err error)
|
||||||
DeletePreferredDuoDevice(ctx context.Context, username string) (err error)
|
DeletePreferredDuoDevice(ctx context.Context, username string) (err error)
|
||||||
|
|
|
@ -882,7 +882,7 @@ func (p *SQLProvider) LoadTOTPConfigurations(ctx context.Context, limit, page in
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveWebauthnDevice saves a registered Webauthn device.
|
// SaveWebauthnDevice saves a registered Webauthn device.
|
||||||
func (p *SQLProvider) SaveWebauthnDevice(ctx context.Context, device model.WebauthnDevice) (err error) {
|
func (p *SQLProvider) SaveWebauthnDevice(ctx context.Context, device model.WebAuthnDevice) (err error) {
|
||||||
if device.PublicKey, err = p.encrypt(device.PublicKey); err != nil {
|
if device.PublicKey, err = p.encrypt(device.PublicKey); err != nil {
|
||||||
return fmt.Errorf("error encrypting Webauthn device public key for user '%s' kid '%x': %w", device.Username, device.KID, err)
|
return fmt.Errorf("error encrypting Webauthn device public key for user '%s' kid '%x': %w", device.Username, device.KID, err)
|
||||||
}
|
}
|
||||||
|
@ -937,8 +937,8 @@ func (p *SQLProvider) DeleteWebauthnDeviceByUsername(ctx context.Context, userna
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadWebauthnDevices loads Webauthn device registrations.
|
// LoadWebauthnDevices loads Webauthn device registrations.
|
||||||
func (p *SQLProvider) LoadWebauthnDevices(ctx context.Context, limit, page int) (devices []model.WebauthnDevice, err error) {
|
func (p *SQLProvider) LoadWebauthnDevices(ctx context.Context, limit, page int) (devices []model.WebAuthnDevice, err error) {
|
||||||
devices = make([]model.WebauthnDevice, 0, limit)
|
devices = make([]model.WebAuthnDevice, 0, limit)
|
||||||
|
|
||||||
if err = p.db.SelectContext(ctx, &devices, p.sqlSelectWebauthnDevices, limit, limit*page); err != nil {
|
if err = p.db.SelectContext(ctx, &devices, p.sqlSelectWebauthnDevices, limit, limit*page); err != nil {
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
|
@ -958,7 +958,7 @@ func (p *SQLProvider) LoadWebauthnDevices(ctx context.Context, limit, page int)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadWebauthnDevicesByUsername loads all webauthn devices registration for a given username.
|
// LoadWebauthnDevicesByUsername loads all webauthn devices registration for a given username.
|
||||||
func (p *SQLProvider) LoadWebauthnDevicesByUsername(ctx context.Context, username string) (devices []model.WebauthnDevice, err error) {
|
func (p *SQLProvider) LoadWebauthnDevicesByUsername(ctx context.Context, username string) (devices []model.WebAuthnDevice, err error) {
|
||||||
if err = p.db.SelectContext(ctx, &devices, p.sqlSelectWebauthnDevicesByUsername, username); err != nil {
|
if err = p.db.SelectContext(ctx, &devices, p.sqlSelectWebauthnDevicesByUsername, username); err != nil {
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
return nil, ErrNoWebauthnDevice
|
return nil, ErrNoWebauthnDevice
|
||||||
|
|
Loading…
Reference in New Issue