From d8defe52c6ddc42b8ae70fb93c80ffcd6e5f5853 Mon Sep 17 00:00:00 2001 From: Henning Perl Date: Mon, 17 Jul 2023 10:55:12 +0200 Subject: [PATCH] feat: support multiple origins for WebAuthN Users can now supply a list of origins for webauthn in the configuration. --- driver/config/config.go | 16 +- driver/config/config_test.go | 45 ++++ .../config/stub/.kratos.webauthn.invalid.yaml | 231 ++++++++++++++++++ .../config/stub/.kratos.webauthn.origin.yaml | 227 +++++++++++++++++ .../config/stub/.kratos.webauthn.origins.yaml | 230 +++++++++++++++++ driver/config/stub/.kratos.yaml | 6 + embedx/config.schema.json | 61 ++++- go.mod | 18 +- go.sum | 24 +- identity/credentials_webauthn.go | 2 +- identity/credentials_webauthn_test.go | 2 +- .../strategy/code/strategy_recovery_test.go | 2 +- ...oad_is_set_when_identity_has_webauthn.json | 2 +- ...ebauthn_login_is_invalid-type=browser.json | 2 +- ...if_webauthn_login_is_invalid-type=spa.json | 2 +- ...passwordless_enabled=false#01-browser.json | 2 +- ...als-passwordless_enabled=false#01-spa.json | 2 +- ...passwordless_enabled=false#02-browser.json | 2 +- ...als-passwordless_enabled=false#02-spa.json | 2 +- ...ls-passwordless_enabled=false-browser.json | 2 +- ...ntials-passwordless_enabled=false-spa.json | 2 +- ...-passwordless_enabled=true#01-browser.json | 2 +- ...ials-passwordless_enabled=true#01-spa.json | 2 +- ...-passwordless_enabled=true#02-browser.json | 2 +- ...ials-passwordless_enabled=true#02-spa.json | 2 +- ...als-passwordless_enabled=true-browser.json | 2 +- ...entials-passwordless_enabled=true-spa.json | 2 +- ...device_is_shown_which_can_be_unlinked.json | 2 +- ...-case=one_activation_element_is_shown.json | 2 +- ...n-case=webauthn_button_exists-browser.json | 2 +- ...ation-case=webauthn_button_exists-spa.json | 2 +- selfservice/strategy/webauthn/js/webauthn.js | 151 +++++++----- selfservice/strategy/webauthn/login.go | 4 +- selfservice/strategy/webauthn/login_test.go | 2 +- selfservice/strategy/webauthn/registration.go | 4 +- selfservice/strategy/webauthn/settings.go | 6 +- selfservice/strategy/webauthn/user.go | 4 +- 37 files changed, 957 insertions(+), 116 deletions(-) create mode 100644 driver/config/stub/.kratos.webauthn.invalid.yaml create mode 100644 driver/config/stub/.kratos.webauthn.origin.yaml create mode 100644 driver/config/stub/.kratos.webauthn.origins.yaml diff --git a/driver/config/config.go b/driver/config/config.go index bfa08bae2a3f..35bf9f4bd1d2 100644 --- a/driver/config/config.go +++ b/driver/config/config.go @@ -18,8 +18,8 @@ import ( "testing" "time" - "github.com/duo-labs/webauthn/protocol" - "github.com/duo-labs/webauthn/webauthn" + "github.com/go-webauthn/webauthn/protocol" + "github.com/go-webauthn/webauthn/webauthn" "github.com/gofrs/uuid" "github.com/inhies/go-bytesize" kjson "github.com/knadh/koanf/parsers/json" @@ -178,7 +178,7 @@ const ( ViperKeyWebAuthnRPDisplayName = "selfservice.methods.webauthn.config.rp.display_name" ViperKeyWebAuthnRPID = "selfservice.methods.webauthn.config.rp.id" ViperKeyWebAuthnRPOrigin = "selfservice.methods.webauthn.config.rp.origin" - ViperKeyWebAuthnRPIcon = "selfservice.methods.webauthn.config.rp.issuer" + ViperKeyWebAuthnRPOrigins = "selfservice.methods.webauthn.config.rp.origins" ViperKeyWebAuthnPasswordless = "selfservice.methods.webauthn.config.passwordless" ViperKeyOAuth2ProviderURL = "oauth2_provider.url" ViperKeyOAuth2ProviderHeader = "oauth2_provider.headers" @@ -1364,14 +1364,18 @@ func (p *Config) WebAuthnForPasswordless(ctx context.Context) bool { } func (p *Config) WebAuthnConfig(ctx context.Context) *webauthn.Config { + scheme := p.SelfPublicURL(ctx).Scheme + id := p.GetProvider(ctx).String(ViperKeyWebAuthnRPID) + origin := p.GetProvider(ctx).String(ViperKeyWebAuthnRPOrigin) + origins := p.GetProvider(ctx).StringsF(ViperKeyWebAuthnRPOrigins, []string{stringsx.Coalesce(origin, scheme+"://"+id)}) return &webauthn.Config{ RPDisplayName: p.GetProvider(ctx).String(ViperKeyWebAuthnRPDisplayName), - RPID: p.GetProvider(ctx).String(ViperKeyWebAuthnRPID), - RPOrigin: p.GetProvider(ctx).String(ViperKeyWebAuthnRPOrigin), - RPIcon: p.GetProvider(ctx).String(ViperKeyWebAuthnRPIcon), + RPID: id, + RPOrigins: origins, AuthenticatorSelection: protocol.AuthenticatorSelection{ UserVerification: protocol.VerificationDiscouraged, }, + EncodeUserIDAsString: false, } } diff --git a/driver/config/config_test.go b/driver/config/config_test.go index 87271e3d0cca..95cd4e6c70bb 100644 --- a/driver/config/config_test.go +++ b/driver/config/config_test.go @@ -1194,6 +1194,51 @@ func TestOAuth2Provider(t *testing.T) { }) } +func TestWebauthn(t *testing.T) { + ctx := context.Background() + + t.Run("case=multiple origins", func(t *testing.T) { + conf, err := config.New(ctx, logrusx.New("", ""), os.Stderr, + configx.WithConfigFiles("stub/.kratos.webauthn.origins.yaml")) + require.NoError(t, err) + webAuthnConfig := conf.WebAuthnConfig(ctx) + assert.Equal(t, "https://example.com/webauthn", webAuthnConfig.RPID) + assert.EqualValues(t, []string{ + "https://origin-a.example.com", + "https://origin-b.example.com", + "https://origin-c.example.com", + }, webAuthnConfig.RPOrigins) + }) + + t.Run("case=one origin", func(t *testing.T) { + conf, err := config.New(ctx, logrusx.New("", ""), os.Stderr, + configx.WithConfigFiles("stub/.kratos.webauthn.origin.yaml")) + require.NoError(t, err) + webAuthnConfig := conf.WebAuthnConfig(ctx) + assert.Equal(t, "https://example.com/webauthn", webAuthnConfig.RPID) + assert.EqualValues(t, []string{ + "https://origin-a.example.com", + }, webAuthnConfig.RPOrigins) + }) + + t.Run("case=id as origin", func(t *testing.T) { + conf, err := config.New(ctx, logrusx.New("", ""), os.Stderr, + configx.WithConfigFiles("stub/.kratos.yaml")) + require.NoError(t, err) + webAuthnConfig := conf.WebAuthnConfig(ctx) + assert.Equal(t, "example.com", webAuthnConfig.RPID) + assert.EqualValues(t, []string{ + "http://example.com", + }, webAuthnConfig.RPOrigins) + }) + + t.Run("case=invalid", func(t *testing.T) { + _, err := config.New(ctx, logrusx.New("", ""), os.Stderr, + configx.WithConfigFiles("stub/.kratos.webauthn.invalid.yaml")) + assert.Error(t, err) + }) +} + func TestCourierTemplatesConfig(t *testing.T) { ctx := context.Background() diff --git a/driver/config/stub/.kratos.webauthn.invalid.yaml b/driver/config/stub/.kratos.webauthn.invalid.yaml new file mode 100644 index 000000000000..01fc9f5adaad --- /dev/null +++ b/driver/config/stub/.kratos.webauthn.invalid.yaml @@ -0,0 +1,231 @@ +# serve controls the configuration for the http(s) daemon +serve: + admin: + base_url: http://admin.kratos.ory.sh + port: 1234 + host: admin.kratos.ory.sh + public: + base_url: http://public.kratos.ory.sh + port: 1235 + host: public.kratos.ory.sh + +dsn: sqlite://foo.db?mode=memory&_fk=true + +log: + level: debug + +courier: + smtp: + connection_uri: smtp://foo:bar@baz/ + +identity: + default_schema_id: default + schemas: + - id: default + url: base64://ewogICIkaWQiOiAib3J5Oi8vaWRlbnRpdHktdGVzdC1zY2hlbWEiLAogICIkc2NoZW1hIjogImh0dHA6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQtMDcvc2NoZW1hIyIsCiAgInRpdGxlIjogIklkZW50aXR5U2NoZW1hIiwKICAidHlwZSI6ICJvYmplY3QiLAogICJwcm9wZXJ0aWVzIjogewogICAgInRyYWl0cyI6IHsKICAgICAgInR5cGUiOiAib2JqZWN0IiwKICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgIm5hbWUiOiB7CiAgICAgICAgICAidHlwZSI6ICJvYmplY3QiLAogICAgICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgICAgICJmaXJzdCI6IHsKICAgICAgICAgICAgICAidHlwZSI6ICJzdHJpbmciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJsYXN0IjogewogICAgICAgICAgICAgICJ0eXBlIjogInN0cmluZyIKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSwKICAgICAgInJlcXVpcmVkIjogWwogICAgICAgICJuYW1lIgogICAgICBdLAogICAgICAiYWRkaXRpb25hbFByb3BlcnRpZXMiOiB0cnVlCiAgICB9CiAgfQp9 + - id: other + url: base64://ewogICIkaWQiOiAib3J5Oi8vaWRlbnRpdHktb3RoZXItc2NoZW1hIiwKICAiJHNjaGVtYSI6ICJodHRwOi8vanNvbi1zY2hlbWEub3JnL2RyYWZ0LTA3L3NjaGVtYSMiLAogICJ0aXRsZSI6ICJJZGVudGl0eU90aGVyU2NoZW1hIiwKICAidHlwZSI6ICJvYmplY3QiLAogICJwcm9wZXJ0aWVzIjogewogICAgInRyYWl0cyI6IHsKICAgICAgInR5cGUiOiAib2JqZWN0IiwKICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgIm90aGVyIjogewogICAgICAgICAgInR5cGUiOiAic3RyaW5nIgogICAgICAgIH0sCiAgICAgICAgImVtYWlsIjogewogICAgICAgICAgInR5cGUiOiAic3RyaW5nIiwKICAgICAgICAgICJ0aXRsZSI6ICJlbWFpbCIsCiAgICAgICAgICAib3J5LnNoL2tyYXRvcyI6IHsKICAgICAgICAgICAgImNyZWRlbnRpYWxzIjogewogICAgICAgICAgICAgICJwYXNzd29yZCI6IHsKICAgICAgICAgICAgICAgICJpZGVudGlmaWVyIjogdHJ1ZQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSwKICAgICAgInJlcXVpcmVkIjogWwogICAgICAgICJvdGhlciIsCiAgICAgICAgImVtYWlsIgogICAgICBdLAogICAgICAiYWRkaXRpb25hbFByb3BlcnRpZXMiOiB0cnVlCiAgICB9CiAgfQp9 + +hashers: + argon2: + memory: 1MB + iterations: 2 + parallelism: 4 + salt_length: 16 + key_length: 32 + dedicated_memory: 1GB + expected_duration: 500ms + expected_deviation: 500ms + +secrets: + cookie: + - session-key-7f8a9b77-1 + - session-key-7f8a9b77-2 + cipher: + - secret-thirty-two-character-long + +ciphers: + algorithm: xchacha20-poly1305 + +selfservice: + default_browser_return_url: http://return-to-3-test.ory.sh/ + allowed_return_urls: + - http://return-to-1-test.ory.sh/ + - http://return-to-2-test.ory.sh/ + - http://*.wildcards.ory.sh + - http://*.sh + - http://*.com + - http://*.com.pl + - http://* + - /return-to-relative-test/ + methods: + totp: + enabled: true + config: + issuer: issuer.ory.sh + password: + enabled: true + oidc: + enabled: true + config: + providers: + - id: github + provider: github + client_id: a + client_secret: b + mapper_url: http://test.kratos.ory.sh/default-identity.schema.json + webauthn: + enabled: true + config: + rp: + id: https://example.com/webauthn + display_name: Webauthn + origin: https://origin-a.example.com + origins: + - https://origin-a.example.com + - https://origin-b.example.com + - https://origin-c.example.com + flows: + error: + ui_url: http://test.kratos.ory.sh/error + + logout: + after: + default_browser_return_url: http://test.kratos.ory.sh:4000/ + + recovery: + enabled: true + ui_url: http://test.kratos.ory.sh/recovery + lifespan: 98m + after: + default_browser_return_url: http://test.kratos.ory.sh/dashboard + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_recovery_hook + method: GET + body: /path/to/template.jsonnet + + verification: + enabled: true + lifespan: 97m + ui_url: http://test.kratos.ory.sh/verification + after: + default_browser_return_url: http://test.kratos.ory.sh/dashboard + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_verification_hook + method: GET + body: /path/to/template.jsonnet + + settings: + ui_url: http://test.kratos.ory.sh/settings + lifespan: 99m + privileged_session_max_age: 5m + after: + default_browser_return_url: https://self-service/settings/return_to + password: + default_browser_return_url: https://self-service/settings/password/return_to + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_settings_password_hook + method: POST + body: /path/to/template.jsonnet + profile: + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_settings_profile_hook + method: POST + body: /path/to/template.jsonnet + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_settings_global_hook + method: POST + body: /path/to/template.jsonnet + + login: + ui_url: http://test.kratos.ory.sh/login + lifespan: 99m + before: + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/before_login_hook + method: POST + after: + default_browser_return_url: https://self-service/login/return_to + password: + default_browser_return_url: https://self-service/login/password/return_to + hooks: + - hook: revoke_active_sessions + - hook: require_verified_address + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_login_password_hook + method: POST + body: /path/to/template.jsonnet + auth: + type: basic_auth + config: + user: test-user + password: super-secret + oidc: + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_login_oidc_hook + method: GET + body: /path/to/template.jsonnet + - hook: revoke_active_sessions + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_login_global_hook + method: POST + body: /path/to/template.jsonnet + + registration: + enabled: true + ui_url: http://test.kratos.ory.sh/register + lifespan: 98m + before: + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/before_registration_hook + method: GET + after: + default_browser_return_url: https://self-service/registration/return_to + password: + hooks: + - hook: session + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_registration_password_hook + method: POST + body: /path/to/template.jsonnet + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_registration_global_hook + method: POST + body: /path/to/template.jsonnet + auth: + type: api_key + config: + name: My-Key + value: My-Key-Value + in: header + oidc: + default_browser_return_url: https://self-service/registration/oidc/return_to + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_registration_oidc_hook + method: GET + body: /path/to/template.jsonnet + - hook: session diff --git a/driver/config/stub/.kratos.webauthn.origin.yaml b/driver/config/stub/.kratos.webauthn.origin.yaml new file mode 100644 index 000000000000..1b2ff11e9d8f --- /dev/null +++ b/driver/config/stub/.kratos.webauthn.origin.yaml @@ -0,0 +1,227 @@ +# serve controls the configuration for the http(s) daemon +serve: + admin: + base_url: http://admin.kratos.ory.sh + port: 1234 + host: admin.kratos.ory.sh + public: + base_url: http://public.kratos.ory.sh + port: 1235 + host: public.kratos.ory.sh + +dsn: sqlite://foo.db?mode=memory&_fk=true + +log: + level: debug + +courier: + smtp: + connection_uri: smtp://foo:bar@baz/ + +identity: + default_schema_id: default + schemas: + - id: default + url: base64://ewogICIkaWQiOiAib3J5Oi8vaWRlbnRpdHktdGVzdC1zY2hlbWEiLAogICIkc2NoZW1hIjogImh0dHA6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQtMDcvc2NoZW1hIyIsCiAgInRpdGxlIjogIklkZW50aXR5U2NoZW1hIiwKICAidHlwZSI6ICJvYmplY3QiLAogICJwcm9wZXJ0aWVzIjogewogICAgInRyYWl0cyI6IHsKICAgICAgInR5cGUiOiAib2JqZWN0IiwKICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgIm5hbWUiOiB7CiAgICAgICAgICAidHlwZSI6ICJvYmplY3QiLAogICAgICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgICAgICJmaXJzdCI6IHsKICAgICAgICAgICAgICAidHlwZSI6ICJzdHJpbmciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJsYXN0IjogewogICAgICAgICAgICAgICJ0eXBlIjogInN0cmluZyIKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSwKICAgICAgInJlcXVpcmVkIjogWwogICAgICAgICJuYW1lIgogICAgICBdLAogICAgICAiYWRkaXRpb25hbFByb3BlcnRpZXMiOiB0cnVlCiAgICB9CiAgfQp9 + - id: other + url: base64://ewogICIkaWQiOiAib3J5Oi8vaWRlbnRpdHktb3RoZXItc2NoZW1hIiwKICAiJHNjaGVtYSI6ICJodHRwOi8vanNvbi1zY2hlbWEub3JnL2RyYWZ0LTA3L3NjaGVtYSMiLAogICJ0aXRsZSI6ICJJZGVudGl0eU90aGVyU2NoZW1hIiwKICAidHlwZSI6ICJvYmplY3QiLAogICJwcm9wZXJ0aWVzIjogewogICAgInRyYWl0cyI6IHsKICAgICAgInR5cGUiOiAib2JqZWN0IiwKICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgIm90aGVyIjogewogICAgICAgICAgInR5cGUiOiAic3RyaW5nIgogICAgICAgIH0sCiAgICAgICAgImVtYWlsIjogewogICAgICAgICAgInR5cGUiOiAic3RyaW5nIiwKICAgICAgICAgICJ0aXRsZSI6ICJlbWFpbCIsCiAgICAgICAgICAib3J5LnNoL2tyYXRvcyI6IHsKICAgICAgICAgICAgImNyZWRlbnRpYWxzIjogewogICAgICAgICAgICAgICJwYXNzd29yZCI6IHsKICAgICAgICAgICAgICAgICJpZGVudGlmaWVyIjogdHJ1ZQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSwKICAgICAgInJlcXVpcmVkIjogWwogICAgICAgICJvdGhlciIsCiAgICAgICAgImVtYWlsIgogICAgICBdLAogICAgICAiYWRkaXRpb25hbFByb3BlcnRpZXMiOiB0cnVlCiAgICB9CiAgfQp9 + +hashers: + argon2: + memory: 1MB + iterations: 2 + parallelism: 4 + salt_length: 16 + key_length: 32 + dedicated_memory: 1GB + expected_duration: 500ms + expected_deviation: 500ms + +secrets: + cookie: + - session-key-7f8a9b77-1 + - session-key-7f8a9b77-2 + cipher: + - secret-thirty-two-character-long + +ciphers: + algorithm: xchacha20-poly1305 + +selfservice: + default_browser_return_url: http://return-to-3-test.ory.sh/ + allowed_return_urls: + - http://return-to-1-test.ory.sh/ + - http://return-to-2-test.ory.sh/ + - http://*.wildcards.ory.sh + - http://*.sh + - http://*.com + - http://*.com.pl + - http://* + - /return-to-relative-test/ + methods: + totp: + enabled: true + config: + issuer: issuer.ory.sh + password: + enabled: true + oidc: + enabled: true + config: + providers: + - id: github + provider: github + client_id: a + client_secret: b + mapper_url: http://test.kratos.ory.sh/default-identity.schema.json + webauthn: + enabled: true + config: + rp: + id: https://example.com/webauthn + display_name: Webauthn + origin: https://origin-a.example.com + flows: + error: + ui_url: http://test.kratos.ory.sh/error + + logout: + after: + default_browser_return_url: http://test.kratos.ory.sh:4000/ + + recovery: + enabled: true + ui_url: http://test.kratos.ory.sh/recovery + lifespan: 98m + after: + default_browser_return_url: http://test.kratos.ory.sh/dashboard + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_recovery_hook + method: GET + body: /path/to/template.jsonnet + + verification: + enabled: true + lifespan: 97m + ui_url: http://test.kratos.ory.sh/verification + after: + default_browser_return_url: http://test.kratos.ory.sh/dashboard + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_verification_hook + method: GET + body: /path/to/template.jsonnet + + settings: + ui_url: http://test.kratos.ory.sh/settings + lifespan: 99m + privileged_session_max_age: 5m + after: + default_browser_return_url: https://self-service/settings/return_to + password: + default_browser_return_url: https://self-service/settings/password/return_to + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_settings_password_hook + method: POST + body: /path/to/template.jsonnet + profile: + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_settings_profile_hook + method: POST + body: /path/to/template.jsonnet + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_settings_global_hook + method: POST + body: /path/to/template.jsonnet + + login: + ui_url: http://test.kratos.ory.sh/login + lifespan: 99m + before: + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/before_login_hook + method: POST + after: + default_browser_return_url: https://self-service/login/return_to + password: + default_browser_return_url: https://self-service/login/password/return_to + hooks: + - hook: revoke_active_sessions + - hook: require_verified_address + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_login_password_hook + method: POST + body: /path/to/template.jsonnet + auth: + type: basic_auth + config: + user: test-user + password: super-secret + oidc: + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_login_oidc_hook + method: GET + body: /path/to/template.jsonnet + - hook: revoke_active_sessions + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_login_global_hook + method: POST + body: /path/to/template.jsonnet + + registration: + enabled: true + ui_url: http://test.kratos.ory.sh/register + lifespan: 98m + before: + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/before_registration_hook + method: GET + after: + default_browser_return_url: https://self-service/registration/return_to + password: + hooks: + - hook: session + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_registration_password_hook + method: POST + body: /path/to/template.jsonnet + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_registration_global_hook + method: POST + body: /path/to/template.jsonnet + auth: + type: api_key + config: + name: My-Key + value: My-Key-Value + in: header + oidc: + default_browser_return_url: https://self-service/registration/oidc/return_to + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_registration_oidc_hook + method: GET + body: /path/to/template.jsonnet + - hook: session diff --git a/driver/config/stub/.kratos.webauthn.origins.yaml b/driver/config/stub/.kratos.webauthn.origins.yaml new file mode 100644 index 000000000000..f9349c670ac0 --- /dev/null +++ b/driver/config/stub/.kratos.webauthn.origins.yaml @@ -0,0 +1,230 @@ +# serve controls the configuration for the http(s) daemon +serve: + admin: + base_url: http://admin.kratos.ory.sh + port: 1234 + host: admin.kratos.ory.sh + public: + base_url: http://public.kratos.ory.sh + port: 1235 + host: public.kratos.ory.sh + +dsn: sqlite://foo.db?mode=memory&_fk=true + +log: + level: debug + +courier: + smtp: + connection_uri: smtp://foo:bar@baz/ + +identity: + default_schema_id: default + schemas: + - id: default + url: base64://ewogICIkaWQiOiAib3J5Oi8vaWRlbnRpdHktdGVzdC1zY2hlbWEiLAogICIkc2NoZW1hIjogImh0dHA6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQtMDcvc2NoZW1hIyIsCiAgInRpdGxlIjogIklkZW50aXR5U2NoZW1hIiwKICAidHlwZSI6ICJvYmplY3QiLAogICJwcm9wZXJ0aWVzIjogewogICAgInRyYWl0cyI6IHsKICAgICAgInR5cGUiOiAib2JqZWN0IiwKICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgIm5hbWUiOiB7CiAgICAgICAgICAidHlwZSI6ICJvYmplY3QiLAogICAgICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgICAgICJmaXJzdCI6IHsKICAgICAgICAgICAgICAidHlwZSI6ICJzdHJpbmciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJsYXN0IjogewogICAgICAgICAgICAgICJ0eXBlIjogInN0cmluZyIKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSwKICAgICAgInJlcXVpcmVkIjogWwogICAgICAgICJuYW1lIgogICAgICBdLAogICAgICAiYWRkaXRpb25hbFByb3BlcnRpZXMiOiB0cnVlCiAgICB9CiAgfQp9 + - id: other + url: base64://ewogICIkaWQiOiAib3J5Oi8vaWRlbnRpdHktb3RoZXItc2NoZW1hIiwKICAiJHNjaGVtYSI6ICJodHRwOi8vanNvbi1zY2hlbWEub3JnL2RyYWZ0LTA3L3NjaGVtYSMiLAogICJ0aXRsZSI6ICJJZGVudGl0eU90aGVyU2NoZW1hIiwKICAidHlwZSI6ICJvYmplY3QiLAogICJwcm9wZXJ0aWVzIjogewogICAgInRyYWl0cyI6IHsKICAgICAgInR5cGUiOiAib2JqZWN0IiwKICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgIm90aGVyIjogewogICAgICAgICAgInR5cGUiOiAic3RyaW5nIgogICAgICAgIH0sCiAgICAgICAgImVtYWlsIjogewogICAgICAgICAgInR5cGUiOiAic3RyaW5nIiwKICAgICAgICAgICJ0aXRsZSI6ICJlbWFpbCIsCiAgICAgICAgICAib3J5LnNoL2tyYXRvcyI6IHsKICAgICAgICAgICAgImNyZWRlbnRpYWxzIjogewogICAgICAgICAgICAgICJwYXNzd29yZCI6IHsKICAgICAgICAgICAgICAgICJpZGVudGlmaWVyIjogdHJ1ZQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSwKICAgICAgInJlcXVpcmVkIjogWwogICAgICAgICJvdGhlciIsCiAgICAgICAgImVtYWlsIgogICAgICBdLAogICAgICAiYWRkaXRpb25hbFByb3BlcnRpZXMiOiB0cnVlCiAgICB9CiAgfQp9 + +hashers: + argon2: + memory: 1MB + iterations: 2 + parallelism: 4 + salt_length: 16 + key_length: 32 + dedicated_memory: 1GB + expected_duration: 500ms + expected_deviation: 500ms + +secrets: + cookie: + - session-key-7f8a9b77-1 + - session-key-7f8a9b77-2 + cipher: + - secret-thirty-two-character-long + +ciphers: + algorithm: xchacha20-poly1305 + +selfservice: + default_browser_return_url: http://return-to-3-test.ory.sh/ + allowed_return_urls: + - http://return-to-1-test.ory.sh/ + - http://return-to-2-test.ory.sh/ + - http://*.wildcards.ory.sh + - http://*.sh + - http://*.com + - http://*.com.pl + - http://* + - /return-to-relative-test/ + methods: + totp: + enabled: true + config: + issuer: issuer.ory.sh + password: + enabled: true + oidc: + enabled: true + config: + providers: + - id: github + provider: github + client_id: a + client_secret: b + mapper_url: http://test.kratos.ory.sh/default-identity.schema.json + webauthn: + enabled: true + config: + rp: + id: https://example.com/webauthn + display_name: Webauthn + origins: + - https://origin-a.example.com + - https://origin-b.example.com + - https://origin-c.example.com + flows: + error: + ui_url: http://test.kratos.ory.sh/error + + logout: + after: + default_browser_return_url: http://test.kratos.ory.sh:4000/ + + recovery: + enabled: true + ui_url: http://test.kratos.ory.sh/recovery + lifespan: 98m + after: + default_browser_return_url: http://test.kratos.ory.sh/dashboard + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_recovery_hook + method: GET + body: /path/to/template.jsonnet + + verification: + enabled: true + lifespan: 97m + ui_url: http://test.kratos.ory.sh/verification + after: + default_browser_return_url: http://test.kratos.ory.sh/dashboard + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_verification_hook + method: GET + body: /path/to/template.jsonnet + + settings: + ui_url: http://test.kratos.ory.sh/settings + lifespan: 99m + privileged_session_max_age: 5m + after: + default_browser_return_url: https://self-service/settings/return_to + password: + default_browser_return_url: https://self-service/settings/password/return_to + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_settings_password_hook + method: POST + body: /path/to/template.jsonnet + profile: + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_settings_profile_hook + method: POST + body: /path/to/template.jsonnet + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_settings_global_hook + method: POST + body: /path/to/template.jsonnet + + login: + ui_url: http://test.kratos.ory.sh/login + lifespan: 99m + before: + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/before_login_hook + method: POST + after: + default_browser_return_url: https://self-service/login/return_to + password: + default_browser_return_url: https://self-service/login/password/return_to + hooks: + - hook: revoke_active_sessions + - hook: require_verified_address + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_login_password_hook + method: POST + body: /path/to/template.jsonnet + auth: + type: basic_auth + config: + user: test-user + password: super-secret + oidc: + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_login_oidc_hook + method: GET + body: /path/to/template.jsonnet + - hook: revoke_active_sessions + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_login_global_hook + method: POST + body: /path/to/template.jsonnet + + registration: + enabled: true + ui_url: http://test.kratos.ory.sh/register + lifespan: 98m + before: + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/before_registration_hook + method: GET + after: + default_browser_return_url: https://self-service/registration/return_to + password: + hooks: + - hook: session + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_registration_password_hook + method: POST + body: /path/to/template.jsonnet + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_registration_global_hook + method: POST + body: /path/to/template.jsonnet + auth: + type: api_key + config: + name: My-Key + value: My-Key-Value + in: header + oidc: + default_browser_return_url: https://self-service/registration/oidc/return_to + hooks: + - hook: web_hook + config: + url: https://test.kratos.ory.sh/after_registration_oidc_hook + method: GET + body: /path/to/template.jsonnet + - hook: session diff --git a/driver/config/stub/.kratos.yaml b/driver/config/stub/.kratos.yaml index ce4d2f3c27a5..b50341928ad8 100644 --- a/driver/config/stub/.kratos.yaml +++ b/driver/config/stub/.kratos.yaml @@ -74,6 +74,12 @@ selfservice: client_id: a client_secret: b mapper_url: http://test.kratos.ory.sh/default-identity.schema.json + webauthn: + enabled: true + config: + rp: + id: example.com + display_name: Webauthn flows: error: ui_url: http://test.kratos.ory.sh/error diff --git a/embedx/config.schema.json b/embedx/config.schema.json index ece7f175b20b..2aa5eb1e056d 100644 --- a/embedx/config.schema.json +++ b/embedx/config.schema.json @@ -1578,10 +1578,6 @@ }, "rp": { "title": "Relying Party (RP) Config", - "required": [ - "id", - "display_name" - ], "properties": { "display_name": { "type": "string", @@ -1602,23 +1598,72 @@ "origin": { "type": "string", "title": "Relying Party Origin", - "description": "An explicit RP origin. If left empty, this defaults to `id`.", + "description": "An explicit RP origin. If left empty, this defaults to `id`, prepended with the current protocol schema (HTTP or HTTPS).", "format": "uri", + "deprecationMessage": "This field is deprecated. Use `origins` instead.", "examples": [ - "https://www.ory.sh/login" + "https://www.ory.sh" ] }, + "origins": { + "type": "array", + "title": "Relying Party Origins", + "description": "A list of explicit RP origins. If left empty, this defaults to either `origin` or `id`, prepended with the current protocol schema (HTTP or HTTPS).", + "items": { + "type": "string", + "format": "uri", + "examples": [ + "https://www.ory.sh", + "https://auth.ory.sh" + ] + } + }, "icon": { "type": "string", "title": "Relying Party Icon", "description": "An icon to help the user identify this RP.", "format": "uri", + "deprecationMessage": "This field is deprecated and ignored due to security considerations.", "examples": [ "https://www.ory.sh/an-icon.png" ] } }, - "type": "object" + "type": "object", + "oneOf": [ + { + "required": [ + "id", + "display_name" + ], + "properties": { + "origin": {"not": {}}, + "origins": {"not": {}} + } + }, + { + "required": [ + "id", + "display_name", + "origin" + ], + "properties": { + "origin": {"type": "string"}, + "origins": {"not": {}} + } + }, + { + "required": [ + "id", + "display_name", + "origins" + ], + "properties": { + "origin": {"not": {}}, + "origins": {"type": "array", "items": {"type": "string"}} + } + } + ] } }, "additionalProperties": false @@ -2740,4 +2785,4 @@ "selfservice" ], "additionalProperties": false -} \ No newline at end of file +} diff --git a/go.mod b/go.mod index 9e8d579bc483..e1e44a675583 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,6 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/davidrjonas/semver-cli v0.0.0-20190116233701-ee19a9a0dda6 github.com/dgraph-io/ristretto v0.1.1 - github.com/duo-labs/webauthn v0.0.0-20220330035159-03696f3d4499 github.com/fatih/color v1.13.0 github.com/ghodss/yaml v1.0.0 github.com/go-crypt/crypt v0.2.9 @@ -37,11 +36,12 @@ require ( github.com/go-openapi/strfmt v0.21.3 github.com/go-playground/validator/v10 v10.4.1 github.com/go-swagger/go-swagger v0.30.3 + github.com/go-webauthn/webauthn v0.8.4 github.com/gobuffalo/fizz v1.14.4 github.com/gobuffalo/httptest v1.5.2 github.com/gobuffalo/pop/v6 v6.1.2-0.20230318123913-c85387acc9a0 github.com/gofrs/uuid v4.3.1+incompatible - github.com/golang-jwt/jwt/v4 v4.1.0 + github.com/golang-jwt/jwt/v4 v4.5.0 github.com/golang/gddo v0.0.0-20190904175337-72a348e765d2 github.com/golang/mock v1.6.0 github.com/google/go-github/v27 v27.0.1 @@ -87,7 +87,7 @@ require ( github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 github.com/sqs/goreturns v0.0.0-20181028201513-538ac6014518 - github.com/stretchr/testify v1.8.2 + github.com/stretchr/testify v1.8.4 github.com/tidwall/gjson v1.14.3 github.com/tidwall/sjson v1.2.5 github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 @@ -96,8 +96,8 @@ require ( go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.36.4 go.opentelemetry.io/otel v1.11.1 go.opentelemetry.io/otel/trace v1.11.1 - golang.org/x/crypto v0.5.0 - golang.org/x/net v0.8.0 + golang.org/x/crypto v0.11.0 + golang.org/x/net v0.10.0 golang.org/x/oauth2 v0.6.0 golang.org/x/sync v0.1.0 golang.org/x/tools/cmd/cover v0.1.0-deprecated @@ -171,6 +171,7 @@ require ( github.com/go-playground/locales v0.13.0 // indirect github.com/go-playground/universal-translator v0.17.0 // indirect github.com/go-sql-driver/mysql v1.7.0 // indirect + github.com/go-webauthn/x v0.1.4 // indirect github.com/gobuffalo/envy v1.10.2 // indirect github.com/gobuffalo/flect v1.0.0 // indirect github.com/gobuffalo/github_flavored_markdown v1.1.3 // indirect @@ -188,6 +189,7 @@ require ( github.com/google/btree v1.0.1 // indirect github.com/google/certificate-transparency-go v1.1.2-0.20210511102531-373a877eec92 // indirect github.com/google/go-querystring v1.0.0 // indirect + github.com/google/go-tpm v0.9.0 // indirect github.com/google/pprof v0.0.0-20221010195024-131d412537ea // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.0 // indirect @@ -340,9 +342,9 @@ require ( go.uber.org/zap v1.21.0 // indirect golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect golang.org/x/mod v0.10.0 // indirect - golang.org/x/sys v0.8.0 // indirect - golang.org/x/term v0.6.0 // indirect - golang.org/x/text v0.8.0 // indirect + golang.org/x/sys v0.10.0 // indirect + golang.org/x/term v0.10.0 // indirect + golang.org/x/text v0.11.0 // indirect golang.org/x/time v0.1.0 // indirect golang.org/x/tools v0.7.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect diff --git a/go.sum b/go.sum index 73270b1447db..ba9c3f08b0ba 100644 --- a/go.sum +++ b/go.sum @@ -296,8 +296,6 @@ github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5Xh github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/duo-labs/webauthn v0.0.0-20220330035159-03696f3d4499 h1:jaQHuGKk9NVcfu9VbA7ygslr/7utxdYs47i4osBhZP8= -github.com/duo-labs/webauthn v0.0.0-20220330035159-03696f3d4499/go.mod h1:UMk1JMDgQDcdI2vQz+WJOIUTSjIq07qSepAVgc93rUc= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -446,6 +444,12 @@ github.com/go-swagger/go-swagger v0.30.3/go.mod h1:neDPes8r8PCz2JPvHRDj8BTULLh4V github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013 h1:l9rI6sNaZgNC0LnF3MiE+qTmyBA/tZAg1rtyrGbUMK0= github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-webauthn/webauthn v0.0.0-20220330035159-03696f3d4499 h1:jaQHuGKk9NVcfu9VbA7ygslr/7utxdYs47i4osBhZP8= +github.com/go-webauthn/webauthn v0.0.0-20220330035159-03696f3d4499/go.mod h1:UMk1JMDgQDcdI2vQz+WJOIUTSjIq07qSepAVgc93rUc= +github.com/go-webauthn/webauthn v0.8.4 h1:/emQ9b9Rj4flWO94Fo8KJeYvZ6VzPywXsmqyDA/WicY= +github.com/go-webauthn/webauthn v0.8.4/go.mod h1:ZqEa9OnSCdQf6CJvTWTDCsUcPRi8F3h7XCIDINwbBgI= +github.com/go-webauthn/x v0.1.4 h1:sGmIFhcY70l6k7JIDfnjVBiAAFEssga5lXIUXe0GtAs= +github.com/go-webauthn/x v0.1.4/go.mod h1:75Ug0oK6KYpANh5hDOanfDI+dvPWHk788naJVG/37H8= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= github.com/gobuffalo/attrs v1.0.3/go.mod h1:KvDJCE0avbufqS0Bw3UV7RQynESY0jjod+572ctX4t8= github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= @@ -520,6 +524,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0= github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/gddo v0.0.0-20190904175337-72a348e765d2 h1:xisWqjiKEff2B0KfFYGpCqc3M3zdTz+OHQHRc09FeYk= github.com/golang/gddo v0.0.0-20190904175337-72a348e765d2/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -598,6 +604,8 @@ github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASu github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE= github.com/google/go-replayers/httpreplay v0.1.0/go.mod h1:YKZViNhiGgqdBlUbI2MwGpq4pXxNmhJLPHQ7cv2b5no= +github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk= +github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/licenseclassifier v0.0.0-20210325184830-bb04aff29e72/go.mod h1:qsqn2hxC+vURpyBRygGUuinTO42MFRLcsmQ/P8v94+M= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -1365,6 +1373,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= @@ -1596,6 +1606,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1707,6 +1719,8 @@ golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfS golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1851,6 +1865,8 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20191110171634-ad39bd3f0407/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1861,6 +1877,8 @@ golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1873,6 +1891,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/identity/credentials_webauthn.go b/identity/credentials_webauthn.go index a41a15a9e70f..ecfd132ea0b1 100644 --- a/identity/credentials_webauthn.go +++ b/identity/credentials_webauthn.go @@ -6,7 +6,7 @@ package identity import ( "time" - "github.com/duo-labs/webauthn/webauthn" + "github.com/go-webauthn/webauthn/webauthn" ) // CredentialsConfig is the struct that is being used as part of the identity credentials. diff --git a/identity/credentials_webauthn_test.go b/identity/credentials_webauthn_test.go index 5386d212f559..c081c1826c41 100644 --- a/identity/credentials_webauthn_test.go +++ b/identity/credentials_webauthn_test.go @@ -6,7 +6,7 @@ package identity import ( "testing" - "github.com/duo-labs/webauthn/webauthn" + "github.com/go-webauthn/webauthn/webauthn" "github.com/stretchr/testify/assert" ) diff --git a/selfservice/strategy/code/strategy_recovery_test.go b/selfservice/strategy/code/strategy_recovery_test.go index db6af2c126b1..e07c0fb28f50 100644 --- a/selfservice/strategy/code/strategy_recovery_test.go +++ b/selfservice/strategy/code/strategy_recovery_test.go @@ -545,7 +545,7 @@ func TestRecovery(t *testing.T) { body = checkRecovery(t, client, RecoveryFlowTypeBrowser, email, body) - assert.Equal(t, text.NewRecoverySuccessful(time.Now().Add(time.Hour)).Text, + require.Equal(t, text.NewRecoverySuccessful(time.Now().Add(time.Hour)).Text, gjson.Get(body, "ui.messages.0.text").String()) settingsId := gjson.Get(body, "id").String() diff --git a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=mfa-case=webauthn_payload_is_set_when_identity_has_webauthn.json b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=mfa-case=webauthn_payload_is_set_when_identity_has_webauthn.json index eeddaab6c127..0e2e343e00e0 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=mfa-case=webauthn_payload_is_set_when_identity_has_webauthn.json +++ b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=mfa-case=webauthn_payload_is_set_when_identity_has_webauthn.json @@ -61,7 +61,7 @@ "async": true, "crossorigin": "anonymous", "id": "webauthn_script", - "integrity": "sha512-8GWpMHzEByiefeXeZNxg1k16eFoSoff1mQVa4vUUruBughTU/Yt4WGl7yteMa11UgygiMEbH8Xn1oKxh8PbkiA==", + "integrity": "sha512-RI23aG5lwYTo7zknGdc++eHUMimUWhkyFzrGid6HkVSdUSjdESPtM3KufXGq/lo4Ut0jI9mDiZeT8tHoSvaHvg==", "node_type": "script", "referrerpolicy": "no-referrer", "type": "text/javascript" diff --git a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=passwordless-case=should_fail_if_webauthn_login_is_invalid-type=browser.json b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=passwordless-case=should_fail_if_webauthn_login_is_invalid-type=browser.json index 0a7494871340..815e99cb456b 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=passwordless-case=should_fail_if_webauthn_login_is_invalid-type=browser.json +++ b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=passwordless-case=should_fail_if_webauthn_login_is_invalid-type=browser.json @@ -36,7 +36,7 @@ "async": true, "referrerpolicy": "no-referrer", "crossorigin": "anonymous", - "integrity": "sha512-8GWpMHzEByiefeXeZNxg1k16eFoSoff1mQVa4vUUruBughTU/Yt4WGl7yteMa11UgygiMEbH8Xn1oKxh8PbkiA==", + "integrity": "sha512-RI23aG5lwYTo7zknGdc++eHUMimUWhkyFzrGid6HkVSdUSjdESPtM3KufXGq/lo4Ut0jI9mDiZeT8tHoSvaHvg==", "type": "text/javascript", "node_type": "script" }, diff --git a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=passwordless-case=should_fail_if_webauthn_login_is_invalid-type=spa.json b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=passwordless-case=should_fail_if_webauthn_login_is_invalid-type=spa.json index 0a7494871340..815e99cb456b 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=passwordless-case=should_fail_if_webauthn_login_is_invalid-type=spa.json +++ b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=passwordless-case=should_fail_if_webauthn_login_is_invalid-type=spa.json @@ -36,7 +36,7 @@ "async": true, "referrerpolicy": "no-referrer", "crossorigin": "anonymous", - "integrity": "sha512-8GWpMHzEByiefeXeZNxg1k16eFoSoff1mQVa4vUUruBughTU/Yt4WGl7yteMa11UgygiMEbH8Xn1oKxh8PbkiA==", + "integrity": "sha512-RI23aG5lwYTo7zknGdc++eHUMimUWhkyFzrGid6HkVSdUSjdESPtM3KufXGq/lo4Ut0jI9mDiZeT8tHoSvaHvg==", "type": "text/javascript", "node_type": "script" }, diff --git a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false#01-browser.json b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false#01-browser.json index fef5b394c157..8b27f6ca0daf 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false#01-browser.json +++ b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false#01-browser.json @@ -62,7 +62,7 @@ "async": true, "crossorigin": "anonymous", "id": "webauthn_script", - "integrity": "sha512-8GWpMHzEByiefeXeZNxg1k16eFoSoff1mQVa4vUUruBughTU/Yt4WGl7yteMa11UgygiMEbH8Xn1oKxh8PbkiA==", + "integrity": "sha512-RI23aG5lwYTo7zknGdc++eHUMimUWhkyFzrGid6HkVSdUSjdESPtM3KufXGq/lo4Ut0jI9mDiZeT8tHoSvaHvg==", "node_type": "script", "referrerpolicy": "no-referrer", "type": "text/javascript" diff --git a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false#01-spa.json b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false#01-spa.json index fef5b394c157..8b27f6ca0daf 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false#01-spa.json +++ b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false#01-spa.json @@ -62,7 +62,7 @@ "async": true, "crossorigin": "anonymous", "id": "webauthn_script", - "integrity": "sha512-8GWpMHzEByiefeXeZNxg1k16eFoSoff1mQVa4vUUruBughTU/Yt4WGl7yteMa11UgygiMEbH8Xn1oKxh8PbkiA==", + "integrity": "sha512-RI23aG5lwYTo7zknGdc++eHUMimUWhkyFzrGid6HkVSdUSjdESPtM3KufXGq/lo4Ut0jI9mDiZeT8tHoSvaHvg==", "node_type": "script", "referrerpolicy": "no-referrer", "type": "text/javascript" diff --git a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false#02-browser.json b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false#02-browser.json index fef5b394c157..8b27f6ca0daf 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false#02-browser.json +++ b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false#02-browser.json @@ -62,7 +62,7 @@ "async": true, "crossorigin": "anonymous", "id": "webauthn_script", - "integrity": "sha512-8GWpMHzEByiefeXeZNxg1k16eFoSoff1mQVa4vUUruBughTU/Yt4WGl7yteMa11UgygiMEbH8Xn1oKxh8PbkiA==", + "integrity": "sha512-RI23aG5lwYTo7zknGdc++eHUMimUWhkyFzrGid6HkVSdUSjdESPtM3KufXGq/lo4Ut0jI9mDiZeT8tHoSvaHvg==", "node_type": "script", "referrerpolicy": "no-referrer", "type": "text/javascript" diff --git a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false#02-spa.json b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false#02-spa.json index fef5b394c157..8b27f6ca0daf 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false#02-spa.json +++ b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false#02-spa.json @@ -62,7 +62,7 @@ "async": true, "crossorigin": "anonymous", "id": "webauthn_script", - "integrity": "sha512-8GWpMHzEByiefeXeZNxg1k16eFoSoff1mQVa4vUUruBughTU/Yt4WGl7yteMa11UgygiMEbH8Xn1oKxh8PbkiA==", + "integrity": "sha512-RI23aG5lwYTo7zknGdc++eHUMimUWhkyFzrGid6HkVSdUSjdESPtM3KufXGq/lo4Ut0jI9mDiZeT8tHoSvaHvg==", "node_type": "script", "referrerpolicy": "no-referrer", "type": "text/javascript" diff --git a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false-browser.json b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false-browser.json index fef5b394c157..8b27f6ca0daf 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false-browser.json +++ b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false-browser.json @@ -62,7 +62,7 @@ "async": true, "crossorigin": "anonymous", "id": "webauthn_script", - "integrity": "sha512-8GWpMHzEByiefeXeZNxg1k16eFoSoff1mQVa4vUUruBughTU/Yt4WGl7yteMa11UgygiMEbH8Xn1oKxh8PbkiA==", + "integrity": "sha512-RI23aG5lwYTo7zknGdc++eHUMimUWhkyFzrGid6HkVSdUSjdESPtM3KufXGq/lo4Ut0jI9mDiZeT8tHoSvaHvg==", "node_type": "script", "referrerpolicy": "no-referrer", "type": "text/javascript" diff --git a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false-spa.json b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false-spa.json index fef5b394c157..8b27f6ca0daf 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false-spa.json +++ b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=false-spa.json @@ -62,7 +62,7 @@ "async": true, "crossorigin": "anonymous", "id": "webauthn_script", - "integrity": "sha512-8GWpMHzEByiefeXeZNxg1k16eFoSoff1mQVa4vUUruBughTU/Yt4WGl7yteMa11UgygiMEbH8Xn1oKxh8PbkiA==", + "integrity": "sha512-RI23aG5lwYTo7zknGdc++eHUMimUWhkyFzrGid6HkVSdUSjdESPtM3KufXGq/lo4Ut0jI9mDiZeT8tHoSvaHvg==", "node_type": "script", "referrerpolicy": "no-referrer", "type": "text/javascript" diff --git a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true#01-browser.json b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true#01-browser.json index fef5b394c157..8b27f6ca0daf 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true#01-browser.json +++ b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true#01-browser.json @@ -62,7 +62,7 @@ "async": true, "crossorigin": "anonymous", "id": "webauthn_script", - "integrity": "sha512-8GWpMHzEByiefeXeZNxg1k16eFoSoff1mQVa4vUUruBughTU/Yt4WGl7yteMa11UgygiMEbH8Xn1oKxh8PbkiA==", + "integrity": "sha512-RI23aG5lwYTo7zknGdc++eHUMimUWhkyFzrGid6HkVSdUSjdESPtM3KufXGq/lo4Ut0jI9mDiZeT8tHoSvaHvg==", "node_type": "script", "referrerpolicy": "no-referrer", "type": "text/javascript" diff --git a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true#01-spa.json b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true#01-spa.json index fef5b394c157..8b27f6ca0daf 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true#01-spa.json +++ b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true#01-spa.json @@ -62,7 +62,7 @@ "async": true, "crossorigin": "anonymous", "id": "webauthn_script", - "integrity": "sha512-8GWpMHzEByiefeXeZNxg1k16eFoSoff1mQVa4vUUruBughTU/Yt4WGl7yteMa11UgygiMEbH8Xn1oKxh8PbkiA==", + "integrity": "sha512-RI23aG5lwYTo7zknGdc++eHUMimUWhkyFzrGid6HkVSdUSjdESPtM3KufXGq/lo4Ut0jI9mDiZeT8tHoSvaHvg==", "node_type": "script", "referrerpolicy": "no-referrer", "type": "text/javascript" diff --git a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true#02-browser.json b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true#02-browser.json index fef5b394c157..8b27f6ca0daf 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true#02-browser.json +++ b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true#02-browser.json @@ -62,7 +62,7 @@ "async": true, "crossorigin": "anonymous", "id": "webauthn_script", - "integrity": "sha512-8GWpMHzEByiefeXeZNxg1k16eFoSoff1mQVa4vUUruBughTU/Yt4WGl7yteMa11UgygiMEbH8Xn1oKxh8PbkiA==", + "integrity": "sha512-RI23aG5lwYTo7zknGdc++eHUMimUWhkyFzrGid6HkVSdUSjdESPtM3KufXGq/lo4Ut0jI9mDiZeT8tHoSvaHvg==", "node_type": "script", "referrerpolicy": "no-referrer", "type": "text/javascript" diff --git a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true#02-spa.json b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true#02-spa.json index fef5b394c157..8b27f6ca0daf 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true#02-spa.json +++ b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true#02-spa.json @@ -62,7 +62,7 @@ "async": true, "crossorigin": "anonymous", "id": "webauthn_script", - "integrity": "sha512-8GWpMHzEByiefeXeZNxg1k16eFoSoff1mQVa4vUUruBughTU/Yt4WGl7yteMa11UgygiMEbH8Xn1oKxh8PbkiA==", + "integrity": "sha512-RI23aG5lwYTo7zknGdc++eHUMimUWhkyFzrGid6HkVSdUSjdESPtM3KufXGq/lo4Ut0jI9mDiZeT8tHoSvaHvg==", "node_type": "script", "referrerpolicy": "no-referrer", "type": "text/javascript" diff --git a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true-browser.json b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true-browser.json index fef5b394c157..8b27f6ca0daf 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true-browser.json +++ b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true-browser.json @@ -62,7 +62,7 @@ "async": true, "crossorigin": "anonymous", "id": "webauthn_script", - "integrity": "sha512-8GWpMHzEByiefeXeZNxg1k16eFoSoff1mQVa4vUUruBughTU/Yt4WGl7yteMa11UgygiMEbH8Xn1oKxh8PbkiA==", + "integrity": "sha512-RI23aG5lwYTo7zknGdc++eHUMimUWhkyFzrGid6HkVSdUSjdESPtM3KufXGq/lo4Ut0jI9mDiZeT8tHoSvaHvg==", "node_type": "script", "referrerpolicy": "no-referrer", "type": "text/javascript" diff --git a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true-spa.json b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true-spa.json index fef5b394c157..8b27f6ca0daf 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true-spa.json +++ b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=refresh-case=passwordless-case=mfa_v0_credentials-passwordless_enabled=true-spa.json @@ -62,7 +62,7 @@ "async": true, "crossorigin": "anonymous", "id": "webauthn_script", - "integrity": "sha512-8GWpMHzEByiefeXeZNxg1k16eFoSoff1mQVa4vUUruBughTU/Yt4WGl7yteMa11UgygiMEbH8Xn1oKxh8PbkiA==", + "integrity": "sha512-RI23aG5lwYTo7zknGdc++eHUMimUWhkyFzrGid6HkVSdUSjdESPtM3KufXGq/lo4Ut0jI9mDiZeT8tHoSvaHvg==", "node_type": "script", "referrerpolicy": "no-referrer", "type": "text/javascript" diff --git a/selfservice/strategy/webauthn/.snapshots/TestCompleteSettings-case=a_device_is_shown_which_can_be_unlinked.json b/selfservice/strategy/webauthn/.snapshots/TestCompleteSettings-case=a_device_is_shown_which_can_be_unlinked.json index 14c7a09cc543..43a740b43790 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestCompleteSettings-case=a_device_is_shown_which_can_be_unlinked.json +++ b/selfservice/strategy/webauthn/.snapshots/TestCompleteSettings-case=a_device_is_shown_which_can_be_unlinked.json @@ -114,7 +114,7 @@ "async": true, "crossorigin": "anonymous", "id": "webauthn_script", - "integrity": "sha512-8GWpMHzEByiefeXeZNxg1k16eFoSoff1mQVa4vUUruBughTU/Yt4WGl7yteMa11UgygiMEbH8Xn1oKxh8PbkiA==", + "integrity": "sha512-RI23aG5lwYTo7zknGdc++eHUMimUWhkyFzrGid6HkVSdUSjdESPtM3KufXGq/lo4Ut0jI9mDiZeT8tHoSvaHvg==", "node_type": "script", "referrerpolicy": "no-referrer", "type": "text/javascript" diff --git a/selfservice/strategy/webauthn/.snapshots/TestCompleteSettings-case=one_activation_element_is_shown.json b/selfservice/strategy/webauthn/.snapshots/TestCompleteSettings-case=one_activation_element_is_shown.json index 94897f01f337..ab20337abc14 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestCompleteSettings-case=one_activation_element_is_shown.json +++ b/selfservice/strategy/webauthn/.snapshots/TestCompleteSettings-case=one_activation_element_is_shown.json @@ -68,7 +68,7 @@ "async": true, "crossorigin": "anonymous", "id": "webauthn_script", - "integrity": "sha512-8GWpMHzEByiefeXeZNxg1k16eFoSoff1mQVa4vUUruBughTU/Yt4WGl7yteMa11UgygiMEbH8Xn1oKxh8PbkiA==", + "integrity": "sha512-RI23aG5lwYTo7zknGdc++eHUMimUWhkyFzrGid6HkVSdUSjdESPtM3KufXGq/lo4Ut0jI9mDiZeT8tHoSvaHvg==", "node_type": "script", "referrerpolicy": "no-referrer", "type": "text/javascript" diff --git a/selfservice/strategy/webauthn/.snapshots/TestRegistration-case=webauthn_button_exists-browser.json b/selfservice/strategy/webauthn/.snapshots/TestRegistration-case=webauthn_button_exists-browser.json index d02f55750550..09b1f9ed6449 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestRegistration-case=webauthn_button_exists-browser.json +++ b/selfservice/strategy/webauthn/.snapshots/TestRegistration-case=webauthn_button_exists-browser.json @@ -94,7 +94,7 @@ "async": true, "crossorigin": "anonymous", "id": "webauthn_script", - "integrity": "sha512-8GWpMHzEByiefeXeZNxg1k16eFoSoff1mQVa4vUUruBughTU/Yt4WGl7yteMa11UgygiMEbH8Xn1oKxh8PbkiA==", + "integrity": "sha512-RI23aG5lwYTo7zknGdc++eHUMimUWhkyFzrGid6HkVSdUSjdESPtM3KufXGq/lo4Ut0jI9mDiZeT8tHoSvaHvg==", "node_type": "script", "referrerpolicy": "no-referrer", "type": "text/javascript" diff --git a/selfservice/strategy/webauthn/.snapshots/TestRegistration-case=webauthn_button_exists-spa.json b/selfservice/strategy/webauthn/.snapshots/TestRegistration-case=webauthn_button_exists-spa.json index d02f55750550..09b1f9ed6449 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestRegistration-case=webauthn_button_exists-spa.json +++ b/selfservice/strategy/webauthn/.snapshots/TestRegistration-case=webauthn_button_exists-spa.json @@ -94,7 +94,7 @@ "async": true, "crossorigin": "anonymous", "id": "webauthn_script", - "integrity": "sha512-8GWpMHzEByiefeXeZNxg1k16eFoSoff1mQVa4vUUruBughTU/Yt4WGl7yteMa11UgygiMEbH8Xn1oKxh8PbkiA==", + "integrity": "sha512-RI23aG5lwYTo7zknGdc++eHUMimUWhkyFzrGid6HkVSdUSjdESPtM3KufXGq/lo4Ut0jI9mDiZeT8tHoSvaHvg==", "node_type": "script", "referrerpolicy": "no-referrer", "type": "text/javascript" diff --git a/selfservice/strategy/webauthn/js/webauthn.js b/selfservice/strategy/webauthn/js/webauthn.js index fd62c1213764..44c389d6f16b 100644 --- a/selfservice/strategy/webauthn/js/webauthn.js +++ b/selfservice/strategy/webauthn/js/webauthn.js @@ -1,13 +1,13 @@ // Copyright © 2023 Ory Corp // SPDX-License-Identifier: Apache-2.0 -(function () { +;(function () { if (!window) { return } if (!window.PublicKeyCredential) { - alert('This browser does not support WebAuthn!'); + alert("This browser does not support WebAuthn!") } if (window.__oryWebAuthnInitialized) { @@ -15,85 +15,116 @@ } function __oryWebAuthnBufferDecode(value) { - return Uint8Array.from(atob(value), function (c) { - return c.charCodeAt(0) - }); + return Uint8Array.from( + atob(value.replaceAll("-", "+").replaceAll("_", "/")), + function (c) { + return c.charCodeAt(0) + }, + ) } function __oryWebAuthnBufferEncode(value) { return btoa(String.fromCharCode.apply(null, new Uint8Array(value))) - .replace(/\+/g, '-') - .replace(/\//g, '_') - .replace(/=/g, ''); + .replaceAll("+", "-") + .replaceAll("/", "_") + .replaceAll("=", "") } - function __oryWebAuthnLogin(opt, resultQuerySelector = '*[name="webauthn_login"]', triggerQuerySelector = '*[name="webauthn_login_trigger"]') { + function __oryWebAuthnLogin( + opt, + resultQuerySelector = '*[name="webauthn_login"]', + triggerQuerySelector = '*[name="webauthn_login_trigger"]', + ) { if (!window.PublicKeyCredential) { - alert('This browser does not support WebAuthn!'); + alert("This browser does not support WebAuthn!") } - opt.publicKey.challenge = __oryWebAuthnBufferDecode(opt.publicKey.challenge); - opt.publicKey.allowCredentials = opt.publicKey.allowCredentials.map(function (value) { - return { - ...value, - id: __oryWebAuthnBufferDecode(value.id) - } - }); + opt.publicKey.challenge = __oryWebAuthnBufferDecode(opt.publicKey.challenge) + opt.publicKey.allowCredentials = opt.publicKey.allowCredentials.map( + function (value) { + return { + ...value, + id: __oryWebAuthnBufferDecode(value.id), + } + }, + ) - navigator.credentials.get(opt).then(function (credential) { - document.querySelector(resultQuerySelector).value = JSON.stringify({ - id: credential.id, - rawId: __oryWebAuthnBufferEncode(credential.rawId), - type: credential.type, - response: { - authenticatorData: __oryWebAuthnBufferEncode(credential.response.authenticatorData), - clientDataJSON: __oryWebAuthnBufferEncode(credential.response.clientDataJSON), - signature: __oryWebAuthnBufferEncode(credential.response.signature), - userHandle: __oryWebAuthnBufferEncode(credential.response.userHandle), - }, - }) + navigator.credentials + .get(opt) + .then(function (credential) { + document.querySelector(resultQuerySelector).value = JSON.stringify({ + id: credential.id, + rawId: __oryWebAuthnBufferEncode(credential.rawId), + type: credential.type, + response: { + authenticatorData: __oryWebAuthnBufferEncode( + credential.response.authenticatorData, + ), + clientDataJSON: __oryWebAuthnBufferEncode( + credential.response.clientDataJSON, + ), + signature: __oryWebAuthnBufferEncode(credential.response.signature), + userHandle: __oryWebAuthnBufferEncode( + credential.response.userHandle, + ), + }, + }) - document.querySelector(triggerQuerySelector).closest('form').submit() - }).catch((err) => { - alert(err) - }) + document.querySelector(triggerQuerySelector).closest("form").submit() + }) + .catch((err) => { + alert(err) + }) } - function __oryWebAuthnRegistration(opt, resultQuerySelector = '*[name="webauthn_register"]', triggerQuerySelector = '*[name="webauthn_register_trigger"]') { + function __oryWebAuthnRegistration( + opt, + resultQuerySelector = '*[name="webauthn_register"]', + triggerQuerySelector = '*[name="webauthn_register_trigger"]', + ) { if (!window.PublicKeyCredential) { - alert('This browser does not support WebAuthn!'); + alert("This browser does not support WebAuthn!") } - opt.publicKey.user.id = __oryWebAuthnBufferDecode(opt.publicKey.user.id); - opt.publicKey.challenge = __oryWebAuthnBufferDecode(opt.publicKey.challenge); + opt.publicKey.user.id = __oryWebAuthnBufferDecode(opt.publicKey.user.id) + opt.publicKey.challenge = __oryWebAuthnBufferDecode(opt.publicKey.challenge) if (opt.publicKey.excludeCredentials) { - opt.publicKey.excludeCredentials = opt.publicKey.excludeCredentials.map(function (value) { - return { - ...value, - id: __oryWebAuthnBufferDecode(value.id) - } - }) + opt.publicKey.excludeCredentials = opt.publicKey.excludeCredentials.map( + function (value) { + return { + ...value, + id: __oryWebAuthnBufferDecode(value.id), + } + }, + ) } - navigator.credentials.create(opt).then(function (credential) { - document.querySelector(resultQuerySelector).value = JSON.stringify({ - id: credential.id, - rawId: __oryWebAuthnBufferEncode(credential.rawId), - type: credential.type, - response: { - attestationObject: __oryWebAuthnBufferEncode(credential.response.attestationObject), - clientDataJSON: __oryWebAuthnBufferEncode(credential.response.clientDataJSON), - }, - }) + navigator.credentials + .create(opt) + .then(function (credential) { + document.querySelector(resultQuerySelector).value = JSON.stringify({ + id: credential.id, + rawId: __oryWebAuthnBufferEncode(credential.rawId), + type: credential.type, + response: { + attestationObject: __oryWebAuthnBufferEncode( + credential.response.attestationObject, + ), + clientDataJSON: __oryWebAuthnBufferEncode( + credential.response.clientDataJSON, + ), + }, + }) - document.querySelector(triggerQuerySelector).closest('form').submit() - }).catch((err) => { - alert(err) - }) + document.querySelector(triggerQuerySelector).closest("form").submit() + }) + .catch((err) => { + alert(err) + }) } - window['__oryWebAuthnLogin'] = __oryWebAuthnLogin - window['__oryWebAuthnRegistration'] = __oryWebAuthnRegistration - window['__oryWebAuthnInitialized'] = true + window["__oryWebAuthnLogin"] = __oryWebAuthnLogin + window["__oryWebAuthnRegistration"] = __oryWebAuthnRegistration + window["__oryWebAuthnInitialized"] = true })() diff --git a/selfservice/strategy/webauthn/login.go b/selfservice/strategy/webauthn/login.go index 33e2689ea315..58cf7b0f25a1 100644 --- a/selfservice/strategy/webauthn/login.go +++ b/selfservice/strategy/webauthn/login.go @@ -19,8 +19,8 @@ import ( "github.com/ory/x/urlx" - "github.com/duo-labs/webauthn/protocol" - "github.com/duo-labs/webauthn/webauthn" + "github.com/go-webauthn/webauthn/protocol" + "github.com/go-webauthn/webauthn/webauthn" "github.com/tidwall/gjson" "github.com/tidwall/sjson" diff --git a/selfservice/strategy/webauthn/login_test.go b/selfservice/strategy/webauthn/login_test.go index 6c8bfc8a27b2..f5d332182163 100644 --- a/selfservice/strategy/webauthn/login_test.go +++ b/selfservice/strategy/webauthn/login_test.go @@ -15,7 +15,7 @@ import ( "github.com/ory/x/jsonx" - "github.com/duo-labs/webauthn/protocol" + "github.com/go-webauthn/webauthn/protocol" kratos "github.com/ory/kratos/internal/httpclient" "github.com/ory/kratos/text" diff --git a/selfservice/strategy/webauthn/registration.go b/selfservice/strategy/webauthn/registration.go index 96b67244abaa..fab8e2cb77c5 100644 --- a/selfservice/strategy/webauthn/registration.go +++ b/selfservice/strategy/webauthn/registration.go @@ -9,8 +9,8 @@ import ( "strings" "time" - "github.com/duo-labs/webauthn/protocol" - "github.com/duo-labs/webauthn/webauthn" + "github.com/go-webauthn/webauthn/protocol" + "github.com/go-webauthn/webauthn/webauthn" "github.com/pkg/errors" "github.com/tidwall/gjson" "github.com/tidwall/sjson" diff --git a/selfservice/strategy/webauthn/settings.go b/selfservice/strategy/webauthn/settings.go index a6e513a20c99..ad00289c010a 100644 --- a/selfservice/strategy/webauthn/settings.go +++ b/selfservice/strategy/webauthn/settings.go @@ -14,8 +14,8 @@ import ( "github.com/ory/x/urlx" - "github.com/duo-labs/webauthn/protocol" - "github.com/duo-labs/webauthn/webauthn" + "github.com/go-webauthn/webauthn/protocol" + "github.com/go-webauthn/webauthn/webauthn" "github.com/ory/x/sqlcon" "github.com/ory/x/sqlxx" @@ -361,7 +361,7 @@ func (s *Strategy) PopulateSettingsMethod(r *http.Request, id *identity.Identity return errors.WithStack(err) } - option, sessionData, err := web.BeginRegistration(NewUser(id.ID[:], nil, web.Config)) + option, sessionData, err := web.BeginRegistration(NewUser(id.ID.Bytes(), nil, web.Config)) if err != nil { return errors.WithStack(err) } diff --git a/selfservice/strategy/webauthn/user.go b/selfservice/strategy/webauthn/user.go index 4d644afbe7fd..823ca93de106 100644 --- a/selfservice/strategy/webauthn/user.go +++ b/selfservice/strategy/webauthn/user.go @@ -3,7 +3,7 @@ package webauthn -import "github.com/duo-labs/webauthn/webauthn" +import "github.com/go-webauthn/webauthn/webauthn" var _ webauthn.User = (*User)(nil) @@ -34,7 +34,7 @@ func (u *User) WebAuthnDisplayName() string { } func (u *User) WebAuthnIcon() string { - return u.cfg.RPIcon + return "" // Icon option has been removed due to security considerations. } func (u *User) WebAuthnCredentials() []webauthn.Credential {