snapshot of https://github.com/ory/kratos.git (master, 2026-09-15; blobs > 131072B omitted)
Some checks failed
CI / Run tests and lints (push) Failing after 29s
CI / Build CLI docs (push) Has been skipped
CI / Run Playwright end-to-end tests (mysql) (push) Failing after 3s
CI / Run Playwright end-to-end tests (postgres) (push) Failing after 2s
CI / Run Playwright end-to-end tests (sqlite) (push) Failing after 3s
CodeQL / Analyze (go) (push) Failing after 4s
CodeQL / Analyze (javascript) (push) Failing after 3s
Docker Image Scanners / scanners (push) Failing after 4s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Run end-to-end tests (postgres) (push) Failing after 19s
CI / Run end-to-end tests (sqlite) (push) Failing after 2s
CI / Run Playwright end-to-end tests (cockroach) (push) Failing after 2s
CI / Draft newsletter (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
Some checks failed
CI / Run tests and lints (push) Failing after 29s
CI / Build CLI docs (push) Has been skipped
CI / Run Playwright end-to-end tests (mysql) (push) Failing after 3s
CI / Run Playwright end-to-end tests (postgres) (push) Failing after 2s
CI / Run Playwright end-to-end tests (sqlite) (push) Failing after 3s
CodeQL / Analyze (go) (push) Failing after 4s
CodeQL / Analyze (javascript) (push) Failing after 3s
Docker Image Scanners / scanners (push) Failing after 4s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Run end-to-end tests (postgres) (push) Failing after 19s
CI / Run end-to-end tests (sqlite) (push) Failing after 2s
CI / Run Playwright end-to-end tests (cockroach) (push) Failing after 2s
CI / Draft newsletter (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"auth": {
|
||||
"config": {
|
||||
"password": "YourPass",
|
||||
"user": "YourUsername"
|
||||
},
|
||||
"type": "basic_auth"
|
||||
},
|
||||
"body": "file://some.jsonnet",
|
||||
"header": {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
"method": "POST",
|
||||
"url": "https://example.com/email"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"auth": {
|
||||
"config": {
|
||||
"password": "YourPass",
|
||||
"user": "YourUsername"
|
||||
},
|
||||
"type": "basic_auth"
|
||||
},
|
||||
"body": "base64://e30=",
|
||||
"header": {
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
},
|
||||
"method": "POST",
|
||||
"url": "https://api.twilio.com/2010-04-01/Accounts/YourAccountID/Messages.json"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
null
|
||||
@@ -0,0 +1,19 @@
|
||||
[
|
||||
"Accept",
|
||||
"Accept-Encoding",
|
||||
"Accept-Language",
|
||||
"Content-Length",
|
||||
"Content-Type",
|
||||
"Origin",
|
||||
"Priority",
|
||||
"Referer",
|
||||
"Sec-Ch-Ua",
|
||||
"Sec-Ch-Ua-Mobile",
|
||||
"Sec-Ch-Ua-Platform",
|
||||
"Sec-Fetch-Dest",
|
||||
"Sec-Fetch-Mode",
|
||||
"Sec-Fetch-Site",
|
||||
"Sec-Fetch-User",
|
||||
"True-Client-Ip",
|
||||
"User-Agent"
|
||||
]
|
||||
10
driver/config/buildinfo.go
Normal file
10
driver/config/buildinfo.go
Normal file
@@ -0,0 +1,10 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package config
|
||||
|
||||
var (
|
||||
Version = "master"
|
||||
Date = "undefined"
|
||||
Commit = "undefined"
|
||||
)
|
||||
1732
driver/config/config.go
Normal file
1732
driver/config/config.go
Normal file
File diff suppressed because it is too large
Load Diff
1596
driver/config/config_test.go
Normal file
1596
driver/config/config_test.go
Normal file
File diff suppressed because it is too large
Load Diff
26
driver/config/handler.go
Normal file
26
driver/config/handler.go
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/knadh/koanf/parsers/json"
|
||||
|
||||
"github.com/ory/x/httprouterx"
|
||||
)
|
||||
|
||||
func RegisterConfigHashRoute(c Provider, router *httprouterx.RouterAdmin) {
|
||||
router.GET("/health/config", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
if revision := c.Config().GetProvider(r.Context()).String("revision"); len(revision) > 0 {
|
||||
_, _ = fmt.Fprintf(w, "%s", revision)
|
||||
} else {
|
||||
bytes, _ := c.Config().GetProvider(r.Context()).Marshal(json.Parser())
|
||||
_, _ = fmt.Fprintf(w, "%x", sha256.Sum256(bytes))
|
||||
}
|
||||
})
|
||||
}
|
||||
70
driver/config/handler_test.go
Normal file
70
driver/config/handler_test.go
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package config_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/ory/kratos/driver/config"
|
||||
"github.com/ory/kratos/pkg"
|
||||
"github.com/ory/x/contextx"
|
||||
"github.com/ory/x/httprouterx"
|
||||
)
|
||||
|
||||
type configProvider struct {
|
||||
cfg *config.Config
|
||||
}
|
||||
|
||||
func (c *configProvider) Config() *config.Config {
|
||||
return c.cfg
|
||||
}
|
||||
|
||||
func TestNewConfigHashHandler(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
cfg := pkg.NewConfigurationWithDefaults(t)
|
||||
router := httprouterx.NewRouterAdmin()
|
||||
config.RegisterConfigHashRoute(&configProvider{cfg: cfg}, router)
|
||||
ts := contextx.NewConfigurableTestServer(router)
|
||||
t.Cleanup(ts.Close)
|
||||
|
||||
// first request, get baseline hash
|
||||
res, err := ts.Client(ctx).Get(ts.URL + "/health/config")
|
||||
require.NoError(t, err)
|
||||
defer func() { _ = res.Body.Close() }()
|
||||
require.Equal(t, 200, res.StatusCode)
|
||||
first, err := io.ReadAll(res.Body)
|
||||
require.NoError(t, err)
|
||||
|
||||
// second request, no config change
|
||||
res, err = ts.Client(ctx).Get(ts.URL + "/health/config")
|
||||
require.NoError(t, err)
|
||||
defer func() { _ = res.Body.Close() }()
|
||||
require.Equal(t, 200, res.StatusCode)
|
||||
second, err := io.ReadAll(res.Body)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, first, second)
|
||||
|
||||
// third request, with config change
|
||||
res, err = ts.Client(contextx.WithConfigValue(ctx, config.ViperKeySessionDomain, "foobar")).Get(ts.URL + "/health/config")
|
||||
require.NoError(t, err)
|
||||
defer func() { _ = res.Body.Close() }()
|
||||
require.Equal(t, 200, res.StatusCode)
|
||||
third, err := io.ReadAll(res.Body)
|
||||
require.NoError(t, err)
|
||||
assert.NotEqual(t, first, third)
|
||||
|
||||
// fourth request, no config change
|
||||
res, err = ts.Client(ctx).Get(ts.URL + "/health/config")
|
||||
require.NoError(t, err)
|
||||
defer func() { _ = res.Body.Close() }()
|
||||
require.Equal(t, 200, res.StatusCode)
|
||||
fourth, err := io.ReadAll(res.Body)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, first, fourth)
|
||||
}
|
||||
6
driver/config/stub/.defaults-password.yml
Normal file
6
driver/config/stub/.defaults-password.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
selfservice:
|
||||
methods:
|
||||
password:
|
||||
enabled: true
|
||||
flows:
|
||||
recovery: false
|
||||
28
driver/config/stub/.defaults-verification.yml
Normal file
28
driver/config/stub/.defaults-verification.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
selfservice:
|
||||
methods:
|
||||
password:
|
||||
enabled: true
|
||||
|
||||
flows:
|
||||
settings:
|
||||
privileged_session_max_age: 1m
|
||||
after:
|
||||
hooks:
|
||||
profile:
|
||||
- hook: show_verification_ui
|
||||
|
||||
verification:
|
||||
enabled: true
|
||||
lifespan: 5s
|
||||
after:
|
||||
default_browser_return_url: http://127.0.0.1:4455/
|
||||
|
||||
logout:
|
||||
after:
|
||||
default_browser_return_url: http://127.0.0.1:4455/auth/login
|
||||
|
||||
identity:
|
||||
default_schema_id: default
|
||||
schemas:
|
||||
- id: default
|
||||
url: file://test/e2e/profiles/verification/identity.traits.schema.json
|
||||
2
driver/config/stub/.defaults.yml
Normal file
2
driver/config/stub/.defaults.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
selfservice:
|
||||
|
||||
17
driver/config/stub/.identity.invalid.json
Normal file
17
driver/config/stub/.identity.invalid.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"$id": "ory://identity-invalid-schema",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "IdentityInvalidSchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"traits": {
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
"required": [
|
||||
"other",
|
||||
"email"
|
||||
],
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
}
|
||||
32
driver/config/stub/.identity.other.json
Normal file
32
driver/config/stub/.identity.other.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"$id": "ory://identity-other-schema",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "IdentityOtherSchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"traits": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"other": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"title": "email",
|
||||
"ory.sh/kratos": {
|
||||
"credentials": {
|
||||
"password": {
|
||||
"identifier": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"other",
|
||||
"email"
|
||||
],
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
}
|
||||
28
driver/config/stub/.identity.test.json
Normal file
28
driver/config/stub/.identity.test.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"$id": "ory://identity-test-schema",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "IdentitySchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"traits": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"first": {
|
||||
"type": "string"
|
||||
},
|
||||
"last": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
}
|
||||
16
driver/config/stub/.kratos.courier.channels.yaml
Normal file
16
driver/config/stub/.kratos.courier.channels.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
courier:
|
||||
smtp:
|
||||
connection_uri: smtp://username:password@smtp.example.com:587
|
||||
channels:
|
||||
- id: phone
|
||||
request_config:
|
||||
url: https://ory.sh
|
||||
method: GET
|
||||
body: base64://ZnVuY3Rpb24oY3R4KSB7CkJvZHk6IGN0eC5ib2R5LApUbzogY3R4LnRvLEZyb206IGN0eC5mcm9tCn0=
|
||||
headers:
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
auth:
|
||||
type: basic_auth
|
||||
config:
|
||||
user: ABC
|
||||
password: DEF
|
||||
24
driver/config/stub/.kratos.courier.email.http.yaml
Normal file
24
driver/config/stub/.kratos.courier.email.http.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
dsn: sqlite://foo.db?mode=memory&_fk=true
|
||||
|
||||
selfservice:
|
||||
default_browser_return_url: https://example.com/return_to
|
||||
|
||||
identity:
|
||||
default_schema_id: default
|
||||
schemas:
|
||||
- id: default
|
||||
url: base64://ewogICIkaWQiOiAib3J5Oi8vaWRlbnRpdHktdGVzdC1zY2hlbWEiLAogICIkc2NoZW1hIjogImh0dHA6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQtMDcvc2NoZW1hIyIsCiAgInRpdGxlIjogIklkZW50aXR5U2NoZW1hIiwKICAidHlwZSI6ICJvYmplY3QiLAogICJwcm9wZXJ0aWVzIjogewogICAgInRyYWl0cyI6IHsKICAgICAgInR5cGUiOiAib2JqZWN0IiwKICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgIm5hbWUiOiB7CiAgICAgICAgICAidHlwZSI6ICJvYmplY3QiLAogICAgICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgICAgICJmaXJzdCI6IHsKICAgICAgICAgICAgICAidHlwZSI6ICJzdHJpbmciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJsYXN0IjogewogICAgICAgICAgICAgICJ0eXBlIjogInN0cmluZyIKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSwKICAgICAgInJlcXVpcmVkIjogWwogICAgICAgICJuYW1lIgogICAgICBdLAogICAgICAiYWRkaXRpb25hbFByb3BlcnRpZXMiOiB0cnVlCiAgICB9CiAgfQp9
|
||||
|
||||
courier:
|
||||
delivery_strategy: http
|
||||
http:
|
||||
request_config:
|
||||
url: https://example.com/email
|
||||
body: file://some.jsonnet
|
||||
header:
|
||||
'Content-Type': 'application/json'
|
||||
auth:
|
||||
type: basic_auth
|
||||
config:
|
||||
user: YourUsername
|
||||
password: YourPass
|
||||
2
driver/config/stub/.kratos.courier.message_retries.yaml
Normal file
2
driver/config/stub/.kratos.courier.message_retries.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
courier:
|
||||
message_retries: 10
|
||||
@@ -0,0 +1,30 @@
|
||||
dsn: sqlite://foo.db?mode=memory&_fk=true
|
||||
|
||||
selfservice:
|
||||
default_browser_return_url: http://return-to-3-test.ory.sh/
|
||||
|
||||
identity:
|
||||
default_schema_id: default
|
||||
schemas:
|
||||
- id: default
|
||||
url: base64://ewogICIkaWQiOiAib3J5Oi8vaWRlbnRpdHktdGVzdC1zY2hlbWEiLAogICIkc2NoZW1hIjogImh0dHA6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQtMDcvc2NoZW1hIyIsCiAgInRpdGxlIjogIklkZW50aXR5U2NoZW1hIiwKICAidHlwZSI6ICJvYmplY3QiLAogICJwcm9wZXJ0aWVzIjogewogICAgInRyYWl0cyI6IHsKICAgICAgInR5cGUiOiAib2JqZWN0IiwKICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgIm5hbWUiOiB7CiAgICAgICAgICAidHlwZSI6ICJvYmplY3QiLAogICAgICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgICAgICJmaXJzdCI6IHsKICAgICAgICAgICAgICAidHlwZSI6ICJzdHJpbmciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJsYXN0IjogewogICAgICAgICAgICAgICJ0eXBlIjogInN0cmluZyIKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSwKICAgICAgInJlcXVpcmVkIjogWwogICAgICAgICJuYW1lIgogICAgICBdLAogICAgICAiYWRkaXRpb25hbFByb3BlcnRpZXMiOiB0cnVlCiAgICB9CiAgfQp9
|
||||
|
||||
courier:
|
||||
smtp:
|
||||
connection_uri: smtp://stub-url
|
||||
templates:
|
||||
recovery:
|
||||
invalid:
|
||||
email:
|
||||
body:
|
||||
html: base64://SGksCgp5b3UgKG9yIHNvbWVvbmUgZWxzZSkgZW50ZXJlZCB0aGlzIGVtYWlsIGFkZHJlc3Mgd2hlbiB0cnlpbmcgdG8gcmVjb3ZlciBhY2Nlc3MgdG8gYW4gYWNjb3VudC4KCkhvd2V2ZXIsIHRoaXMgZW1haWwgYWRkcmVzcyBpcyBub3Qgb24gb3VyIGRhdGFiYXNlIG9mIHJlZ2lzdGVyZWQgdXNlcnMgYW5kIHRoZXJlZm9yZSB0aGUgYXR0ZW1wdCBoYXMgZmFpbGVkLgoKSWYgdGhpcyB3YXMgeW91LCBjaGVjayBpZiB5b3Ugc2lnbmVkIHVwIHVzaW5nIGEgZGlmZmVyZW50IGFkZHJlc3MuCgpJZiB0aGlzIHdhcyBub3QgeW91LCBwbGVhc2UgaWdub3JlIHRoaXMgZW1haWwu
|
||||
# omit subject to verify it is validated
|
||||
valid:
|
||||
# omit template_root as it is not required on valid
|
||||
email:
|
||||
body:
|
||||
plaintext: base64://e3sgZGVmaW5lIGFmLVpBIH19CkhhbGxvLAoKSGVyc3RlbCBqb3UgcmVrZW5pbmcgZGV1ciBoaWVyZGllIHNrYWtlbCB0ZSB2b2xnOgp7ey0gZW5kIC19fQoKe3sgZGVmaW5lIGVuLVVTIH19CkhpLAoKcGxlYXNlIHJlY292ZXIgYWNjZXNzIHRvIHlvdXIgYWNjb3VudCBieSBjbGlja2luZyB0aGUgZm9sbG93aW5nIGxpbms6Cnt7LSBlbmQgLX19Cgp7ey0gaWYgZXEgLmxhbmcgImFmLVpBIiAtfX0KCnt7IHRlbXBsYXRlICJhZi1aQSIgLiB9fQoKe3stIGVsc2UgLX19Cgp7eyB0ZW1wbGF0ZSAiZW4tVVMiIH19Cgp7ey0gZW5kIC19fQp7eyAuUmVjb3ZlcnlVUkwgfX0K
|
||||
html: base64://e3sgZGVmaW5lIGFmLVpBIH19CkhhbGxvLAoKSGVyc3RlbCBqb3UgcmVrZW5pbmcgZGV1ciBoaWVyZGllIHNrYWtlbCB0ZSB2b2xnOgp7ey0gZW5kIC19fQoKe3sgZGVmaW5lIGVuLVVTIH19CkhpLAoKcGxlYXNlIHJlY292ZXIgYWNjZXNzIHRvIHlvdXIgYWNjb3VudCBieSBjbGlja2luZyB0aGUgZm9sbG93aW5nIGxpbms6Cnt7LSBlbmQgLX19Cgp7ey0gaWYgZXEgLmxhbmcgImFmLVpBIiAtfX0KCnt7IHRlbXBsYXRlICJhZi1aQSIgLiB9fQoKe3stIGVsc2UgLX19Cgp7eyB0ZW1wbGF0ZSAiZW4tVVMiIH19Cgp7ey0gZW5kIC19fQo8YSBocmVmPSJ7eyAuUmVjb3ZlcnlVUkwgfX0iPnt7IC5SZWNvdmVyeVVSTCB9fTwvYT4=
|
||||
subject: base64://UmVjb3ZlciBhY2Nlc3MgdG8geW91ciBhY2NvdW50
|
||||
# omit verification here to test templates override fallback
|
||||
template_override_path: "../../courier/template/courier/builtin/templates"
|
||||
@@ -0,0 +1,26 @@
|
||||
dsn: sqlite://foo.db?mode=memory&_fk=true
|
||||
|
||||
selfservice:
|
||||
default_browser_return_url: http://return-to-3-test.ory.sh/
|
||||
|
||||
identity:
|
||||
default_schema_id: default
|
||||
schemas:
|
||||
- id: default
|
||||
url: base64://ewogICIkaWQiOiAib3J5Oi8vaWRlbnRpdHktdGVzdC1zY2hlbWEiLAogICIkc2NoZW1hIjogImh0dHA6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQtMDcvc2NoZW1hIyIsCiAgInRpdGxlIjogIklkZW50aXR5U2NoZW1hIiwKICAidHlwZSI6ICJvYmplY3QiLAogICJwcm9wZXJ0aWVzIjogewogICAgInRyYWl0cyI6IHsKICAgICAgInR5cGUiOiAib2JqZWN0IiwKICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgIm5hbWUiOiB7CiAgICAgICAgICAidHlwZSI6ICJvYmplY3QiLAogICAgICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgICAgICJmaXJzdCI6IHsKICAgICAgICAgICAgICAidHlwZSI6ICJzdHJpbmciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJsYXN0IjogewogICAgICAgICAgICAgICJ0eXBlIjogInN0cmluZyIKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSwKICAgICAgInJlcXVpcmVkIjogWwogICAgICAgICJuYW1lIgogICAgICBdLAogICAgICAiYWRkaXRpb25hbFByb3BlcnRpZXMiOiB0cnVlCiAgICB9CiAgfQp9
|
||||
|
||||
courier:
|
||||
smtp:
|
||||
connection_uri: smtp://stub-url
|
||||
templates:
|
||||
recovery:
|
||||
invalid:
|
||||
email:
|
||||
body:
|
||||
plaintext: base64://SGksCgp5b3UgKG9yIHNvbWVvbmUgZWxzZSkgZW50ZXJlZCB0aGlzIGVtYWlsIGFkZHJlc3Mgd2hlbiB0cnlpbmcgdG8gcmVjb3ZlciBhY2Nlc3MgdG8gYW4gYWNjb3VudC4KCkhvd2V2ZXIsIHRoaXMgZW1haWwgYWRkcmVzcyBpcyBub3Qgb24gb3VyIGRhdGFiYXNlIG9mIHJlZ2lzdGVyZWQgdXNlcnMgYW5kIHRoZXJlZm9yZSB0aGUgYXR0ZW1wdCBoYXMgZmFpbGVkLgoKSWYgdGhpcyB3YXMgeW91LCBjaGVjayBpZiB5b3Ugc2lnbmVkIHVwIHVzaW5nIGEgZGlmZmVyZW50IGFkZHJlc3MuCgpJZiB0aGlzIHdhcyBub3QgeW91LCBwbGVhc2UgaWdub3JlIHRoaXMgZW1haWwu
|
||||
html: base64://SGksCgp5b3UgKG9yIHNvbWVvbmUgZWxzZSkgZW50ZXJlZCB0aGlzIGVtYWlsIGFkZHJlc3Mgd2hlbiB0cnlpbmcgdG8gcmVjb3ZlciBhY2Nlc3MgdG8gYW4gYWNjb3VudC4KCkhvd2V2ZXIsIHRoaXMgZW1haWwgYWRkcmVzcyBpcyBub3Qgb24gb3VyIGRhdGFiYXNlIG9mIHJlZ2lzdGVyZWQgdXNlcnMgYW5kIHRoZXJlZm9yZSB0aGUgYXR0ZW1wdCBoYXMgZmFpbGVkLgoKSWYgdGhpcyB3YXMgeW91LCBjaGVjayBpZiB5b3Ugc2lnbmVkIHVwIHVzaW5nIGEgZGlmZmVyZW50IGFkZHJlc3MuCgpJZiB0aGlzIHdhcyBub3QgeW91LCBwbGVhc2UgaWdub3JlIHRoaXMgZW1haWwu
|
||||
verification:
|
||||
valid:
|
||||
email:
|
||||
subject: base64://VmVyaWZpY2F0aW9uIEVtYWls
|
||||
template_override_path: "../../courier/template/courier/builtin/templates"
|
||||
30
driver/config/stub/.kratos.courier.remote.templates.yaml
Normal file
30
driver/config/stub/.kratos.courier.remote.templates.yaml
Normal file
@@ -0,0 +1,30 @@
|
||||
dsn: sqlite://foo.db?mode=memory&_fk=true
|
||||
|
||||
selfservice:
|
||||
default_browser_return_url: http://return-to-3-test.ory.sh/
|
||||
|
||||
identity:
|
||||
default_schema_id: default
|
||||
schemas:
|
||||
- id: default
|
||||
url: base64://ewogICIkaWQiOiAib3J5Oi8vaWRlbnRpdHktdGVzdC1zY2hlbWEiLAogICIkc2NoZW1hIjogImh0dHA6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQtMDcvc2NoZW1hIyIsCiAgInRpdGxlIjogIklkZW50aXR5U2NoZW1hIiwKICAidHlwZSI6ICJvYmplY3QiLAogICJwcm9wZXJ0aWVzIjogewogICAgInRyYWl0cyI6IHsKICAgICAgInR5cGUiOiAib2JqZWN0IiwKICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgIm5hbWUiOiB7CiAgICAgICAgICAidHlwZSI6ICJvYmplY3QiLAogICAgICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgICAgICJmaXJzdCI6IHsKICAgICAgICAgICAgICAidHlwZSI6ICJzdHJpbmciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJsYXN0IjogewogICAgICAgICAgICAgICJ0eXBlIjogInN0cmluZyIKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSwKICAgICAgInJlcXVpcmVkIjogWwogICAgICAgICJuYW1lIgogICAgICBdLAogICAgICAiYWRkaXRpb25hbFByb3BlcnRpZXMiOiB0cnVlCiAgICB9CiAgfQp9
|
||||
|
||||
courier:
|
||||
smtp:
|
||||
connection_uri: smtp://stub-url
|
||||
templates:
|
||||
recovery:
|
||||
invalid:
|
||||
email:
|
||||
body:
|
||||
plaintext: base64://SGksCgp5b3UgKG9yIHNvbWVvbmUgZWxzZSkgZW50ZXJlZCB0aGlzIGVtYWlsIGFkZHJlc3Mgd2hlbiB0cnlpbmcgdG8gcmVjb3ZlciBhY2Nlc3MgdG8gYW4gYWNjb3VudC4KCkhvd2V2ZXIsIHRoaXMgZW1haWwgYWRkcmVzcyBpcyBub3Qgb24gb3VyIGRhdGFiYXNlIG9mIHJlZ2lzdGVyZWQgdXNlcnMgYW5kIHRoZXJlZm9yZSB0aGUgYXR0ZW1wdCBoYXMgZmFpbGVkLgoKSWYgdGhpcyB3YXMgeW91LCBjaGVjayBpZiB5b3Ugc2lnbmVkIHVwIHVzaW5nIGEgZGlmZmVyZW50IGFkZHJlc3MuCgpJZiB0aGlzIHdhcyBub3QgeW91LCBwbGVhc2UgaWdub3JlIHRoaXMgZW1haWwu
|
||||
html: base64://SGksCgp5b3UgKG9yIHNvbWVvbmUgZWxzZSkgZW50ZXJlZCB0aGlzIGVtYWlsIGFkZHJlc3Mgd2hlbiB0cnlpbmcgdG8gcmVjb3ZlciBhY2Nlc3MgdG8gYW4gYWNjb3VudC4KCkhvd2V2ZXIsIHRoaXMgZW1haWwgYWRkcmVzcyBpcyBub3Qgb24gb3VyIGRhdGFiYXNlIG9mIHJlZ2lzdGVyZWQgdXNlcnMgYW5kIHRoZXJlZm9yZSB0aGUgYXR0ZW1wdCBoYXMgZmFpbGVkLgoKSWYgdGhpcyB3YXMgeW91LCBjaGVjayBpZiB5b3Ugc2lnbmVkIHVwIHVzaW5nIGEgZGlmZmVyZW50IGFkZHJlc3MuCgpJZiB0aGlzIHdhcyBub3QgeW91LCBwbGVhc2UgaWdub3JlIHRoaXMgZW1haWwu
|
||||
subject: base64://QWNjb3VudCBBY2Nlc3MgQXR0ZW1wdGVk
|
||||
valid:
|
||||
email:
|
||||
body:
|
||||
plaintext: base64://e3sgZGVmaW5lIGFmLVpBIH19CkhhbGxvLAoKSGVyc3RlbCBqb3UgcmVrZW5pbmcgZGV1ciBoaWVyZGllIHNrYWtlbCB0ZSB2b2xnOgp7ey0gZW5kIC19fQoKe3sgZGVmaW5lIGVuLVVTIH19CkhpLAoKcGxlYXNlIHJlY292ZXIgYWNjZXNzIHRvIHlvdXIgYWNjb3VudCBieSBjbGlja2luZyB0aGUgZm9sbG93aW5nIGxpbms6Cnt7LSBlbmQgLX19Cgp7ey0gaWYgZXEgLmxhbmcgImFmLVpBIiAtfX0KCnt7IHRlbXBsYXRlICJhZi1aQSIgLiB9fQoKe3stIGVsc2UgLX19Cgp7eyB0ZW1wbGF0ZSAiZW4tVVMiIH19Cgp7ey0gZW5kIC19fQp7eyAuUmVjb3ZlcnlVUkwgfX0K
|
||||
html: base64://e3sgZGVmaW5lIGFmLVpBIH19CkhhbGxvLAoKSGVyc3RlbCBqb3UgcmVrZW5pbmcgZGV1ciBoaWVyZGllIHNrYWtlbCB0ZSB2b2xnOgp7ey0gZW5kIC19fQoKe3sgZGVmaW5lIGVuLVVTIH19CkhpLAoKcGxlYXNlIHJlY292ZXIgYWNjZXNzIHRvIHlvdXIgYWNjb3VudCBieSBjbGlja2luZyB0aGUgZm9sbG93aW5nIGxpbms6Cnt7LSBlbmQgLX19Cgp7ey0gaWYgZXEgLmxhbmcgImFmLVpBIiAtfX0KCnt7IHRlbXBsYXRlICJhZi1aQSIgLiB9fQoKe3stIGVsc2UgLX19Cgp7eyB0ZW1wbGF0ZSAiZW4tVVMiIH19Cgp7ey0gZW5kIC19fQo8YSBocmVmPSJ7eyAuUmVjb3ZlcnlVUkwgfX0iPnt7IC5SZWNvdmVyeVVSTCB9fTwvYT4=
|
||||
subject: base64://UmVjb3ZlciBhY2Nlc3MgdG8geW91ciBhY2NvdW50
|
||||
# omit verification here to test templates override fallback
|
||||
template_override_path: "../../courier/template/courier/builtin/templates"
|
||||
28
driver/config/stub/.kratos.courier.sms.yaml
Normal file
28
driver/config/stub/.kratos.courier.sms.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
dsn: sqlite://foo.db?mode=memory&_fk=true
|
||||
|
||||
selfservice:
|
||||
default_browser_return_url: http://return-to-3-test.ory.sh/
|
||||
|
||||
identity:
|
||||
default_schema_id: default
|
||||
schemas:
|
||||
- id: default
|
||||
url: base64://ewogICIkaWQiOiAib3J5Oi8vaWRlbnRpdHktdGVzdC1zY2hlbWEiLAogICIkc2NoZW1hIjogImh0dHA6Ly9qc29uLXNjaGVtYS5vcmcvZHJhZnQtMDcvc2NoZW1hIyIsCiAgInRpdGxlIjogIklkZW50aXR5U2NoZW1hIiwKICAidHlwZSI6ICJvYmplY3QiLAogICJwcm9wZXJ0aWVzIjogewogICAgInRyYWl0cyI6IHsKICAgICAgInR5cGUiOiAib2JqZWN0IiwKICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgIm5hbWUiOiB7CiAgICAgICAgICAidHlwZSI6ICJvYmplY3QiLAogICAgICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgICAgICJmaXJzdCI6IHsKICAgICAgICAgICAgICAidHlwZSI6ICJzdHJpbmciCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJsYXN0IjogewogICAgICAgICAgICAgICJ0eXBlIjogInN0cmluZyIKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSwKICAgICAgInJlcXVpcmVkIjogWwogICAgICAgICJuYW1lIgogICAgICBdLAogICAgICAiYWRkaXRpb25hbFByb3BlcnRpZXMiOiB0cnVlCiAgICB9CiAgfQp9
|
||||
|
||||
courier:
|
||||
smtp:
|
||||
connection_uri: smtp://foo:bar@baz/
|
||||
sms:
|
||||
enabled: true
|
||||
from: '+49123456789'
|
||||
request_config:
|
||||
url: https://api.twilio.com/2010-04-01/Accounts/YourAccountID/Messages.json
|
||||
method: POST
|
||||
body: base64://e30=
|
||||
header:
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
auth:
|
||||
type: basic_auth
|
||||
config:
|
||||
user: YourUsername
|
||||
password: YourPass
|
||||
14
driver/config/stub/.kratos.invalid.identities.yaml
Normal file
14
driver/config/stub/.kratos.invalid.identities.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
dsn: sqlite://foo.db?mode=memory&_fk=true
|
||||
|
||||
selfservice:
|
||||
default_browser_return_url: http://return-to-3-test.ory.sh/
|
||||
|
||||
identity:
|
||||
default_schema_id: other
|
||||
schemas:
|
||||
- id: other
|
||||
url: file://stub/.identity.invalid.json
|
||||
|
||||
courier:
|
||||
smtp:
|
||||
connection_uri: smtp://foo:bar@baz/
|
||||
16
driver/config/stub/.kratos.mock.identities.yaml
Normal file
16
driver/config/stub/.kratos.mock.identities.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
dsn: sqlite://foo.db?mode=memory&_fk=true
|
||||
|
||||
selfservice:
|
||||
default_browser_return_url: http://return-to-3-test.ory.sh/
|
||||
|
||||
identity:
|
||||
default_schema_id: default
|
||||
schemas:
|
||||
- id: default
|
||||
url: http://test.kratos.ory.sh/default-identity.schema.json
|
||||
- id: other
|
||||
url: http://test.kratos.ory.sh/other-identity.schema.json
|
||||
|
||||
courier:
|
||||
smtp:
|
||||
connection_uri: smtp://foo:bar@baz/
|
||||
6
driver/config/stub/.kratos.notify-unknown-recipients.yml
Normal file
6
driver/config/stub/.kratos.notify-unknown-recipients.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
selfservice:
|
||||
flows:
|
||||
recovery:
|
||||
notify_unknown_recipients: true
|
||||
verification:
|
||||
notify_unknown_recipients: true
|
||||
5
driver/config/stub/.kratos.oauth2_provider.yaml
Normal file
5
driver/config/stub/.kratos.oauth2_provider.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
oauth2_provider:
|
||||
url: https://oauth2_provider/
|
||||
headers:
|
||||
Authorization: Basic
|
||||
override_return_to: true
|
||||
54
driver/config/stub/.kratos.passkey.options.yaml
Normal file
54
driver/config/stub/.kratos.passkey.options.yaml
Normal file
@@ -0,0 +1,54 @@
|
||||
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
|
||||
|
||||
secrets:
|
||||
cookie:
|
||||
- session-key-7f8a9b77-1
|
||||
cipher:
|
||||
- secret-thirty-two-character-long
|
||||
|
||||
ciphers:
|
||||
algorithm: xchacha20-poly1305
|
||||
|
||||
selfservice:
|
||||
default_browser_return_url: http://return-to-3-test.ory.sh/
|
||||
methods:
|
||||
passkey:
|
||||
enabled: true
|
||||
config:
|
||||
rp:
|
||||
id: example.com
|
||||
display_name: Example
|
||||
origins:
|
||||
- https://example.com
|
||||
authenticator_selection:
|
||||
attachment: "cross-platform"
|
||||
resident_key: "discouraged"
|
||||
user_verification: "required"
|
||||
attestation:
|
||||
preference: "direct"
|
||||
timeouts:
|
||||
registration: "30s"
|
||||
login: "45s"
|
||||
45
driver/config/stub/.kratos.passkey.yaml
Normal file
45
driver/config/stub/.kratos.passkey.yaml
Normal file
@@ -0,0 +1,45 @@
|
||||
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
|
||||
|
||||
secrets:
|
||||
cookie:
|
||||
- session-key-7f8a9b77-1
|
||||
cipher:
|
||||
- secret-thirty-two-character-long
|
||||
|
||||
ciphers:
|
||||
algorithm: xchacha20-poly1305
|
||||
|
||||
selfservice:
|
||||
default_browser_return_url: http://return-to-3-test.ory.sh/
|
||||
methods:
|
||||
passkey:
|
||||
enabled: true
|
||||
config:
|
||||
rp:
|
||||
id: example.com
|
||||
display_name: Example
|
||||
origins:
|
||||
- https://example.com
|
||||
257
driver/config/stub/.kratos.webauthn.invalid.yaml
Normal file
257
driver/config/stub/.kratos.webauthn.invalid.yaml
Normal file
@@ -0,0 +1,257 @@
|
||||
# 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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
body: /path/to/template.jsonnet
|
||||
profile:
|
||||
hooks:
|
||||
- hook: web_hook
|
||||
config:
|
||||
url: https://test.kratos.ory.sh/after_settings_profile_hook
|
||||
method: POST
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
body: /path/to/template.jsonnet
|
||||
hooks:
|
||||
- hook: web_hook
|
||||
config:
|
||||
url: https://test.kratos.ory.sh/after_settings_global_hook
|
||||
method: POST
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
body: /path/to/template.jsonnet
|
||||
hooks:
|
||||
- hook: web_hook
|
||||
config:
|
||||
url: https://test.kratos.ory.sh/after_registration_global_hook
|
||||
method: POST
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
body: /path/to/template.jsonnet
|
||||
- hook: session
|
||||
253
driver/config/stub/.kratos.webauthn.origin.yaml
Normal file
253
driver/config/stub/.kratos.webauthn.origin.yaml
Normal file
@@ -0,0 +1,253 @@
|
||||
# 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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
body: /path/to/template.jsonnet
|
||||
profile:
|
||||
hooks:
|
||||
- hook: web_hook
|
||||
config:
|
||||
url: https://test.kratos.ory.sh/after_settings_profile_hook
|
||||
method: POST
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
body: /path/to/template.jsonnet
|
||||
hooks:
|
||||
- hook: web_hook
|
||||
config:
|
||||
url: https://test.kratos.ory.sh/after_settings_global_hook
|
||||
method: POST
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
body: /path/to/template.jsonnet
|
||||
hooks:
|
||||
- hook: web_hook
|
||||
config:
|
||||
url: https://test.kratos.ory.sh/after_registration_global_hook
|
||||
method: POST
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
body: /path/to/template.jsonnet
|
||||
- hook: session
|
||||
256
driver/config/stub/.kratos.webauthn.origins.yaml
Normal file
256
driver/config/stub/.kratos.webauthn.origins.yaml
Normal file
@@ -0,0 +1,256 @@
|
||||
# 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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
body: /path/to/template.jsonnet
|
||||
profile:
|
||||
hooks:
|
||||
- hook: web_hook
|
||||
config:
|
||||
url: https://test.kratos.ory.sh/after_settings_profile_hook
|
||||
method: POST
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
body: /path/to/template.jsonnet
|
||||
hooks:
|
||||
- hook: web_hook
|
||||
config:
|
||||
url: https://test.kratos.ory.sh/after_settings_global_hook
|
||||
method: POST
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
body: /path/to/template.jsonnet
|
||||
hooks:
|
||||
- hook: web_hook
|
||||
config:
|
||||
url: https://test.kratos.ory.sh/after_registration_global_hook
|
||||
method: POST
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
body: /path/to/template.jsonnet
|
||||
- hook: session
|
||||
254
driver/config/stub/.kratos.yaml
Normal file
254
driver/config/stub/.kratos.yaml
Normal file
@@ -0,0 +1,254 @@
|
||||
# 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
|
||||
bcrypt:
|
||||
cost: 4
|
||||
|
||||
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: example.com
|
||||
display_name: Webauthn
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
body: /path/to/template.jsonnet
|
||||
profile:
|
||||
hooks:
|
||||
- hook: web_hook
|
||||
config:
|
||||
url: https://test.kratos.ory.sh/after_settings_profile_hook
|
||||
method: POST
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
body: /path/to/template.jsonnet
|
||||
hooks:
|
||||
- hook: web_hook
|
||||
config:
|
||||
url: https://test.kratos.ory.sh/after_settings_global_hook
|
||||
method: POST
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
body: /path/to/template.jsonnet
|
||||
hooks:
|
||||
- hook: web_hook
|
||||
config:
|
||||
url: https://test.kratos.ory.sh/after_registration_global_hook
|
||||
method: POST
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
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
|
||||
headers:
|
||||
X-Custom-Header: test
|
||||
body: /path/to/template.jsonnet
|
||||
- hook: session
|
||||
59
driver/factory.go
Normal file
59
driver/factory.go
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/ory/x/servicelocatorx"
|
||||
|
||||
"github.com/ory/kratos/driver/config"
|
||||
"github.com/ory/x/logrusx"
|
||||
)
|
||||
|
||||
func New(ctx context.Context, stdOutOrErr io.Writer, dOpts ...RegistryOption) (*RegistryDefault, error) {
|
||||
r, err := NewWithoutInit(ctx, stdOutOrErr, dOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctxter := r.Contextualizer()
|
||||
if err := r.Init(ctx, ctxter, dOpts...); err != nil {
|
||||
r.Logger().WithError(err).Error("Unable to initialize service registry.")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func NewWithoutInit(ctx context.Context, stdOutOrErr io.Writer, dOpts ...RegistryOption) (*RegistryDefault, error) {
|
||||
opts := newOptions(dOpts)
|
||||
sl := servicelocatorx.NewOptions(opts.serviceLocatorOptions...)
|
||||
|
||||
l := sl.Logger()
|
||||
if l == nil {
|
||||
l = logrusx.New("Ory Kratos", config.Version)
|
||||
}
|
||||
|
||||
c := opts.config
|
||||
if c == nil {
|
||||
var err error
|
||||
c, err = config.New(ctx, l, stdOutOrErr, sl.Contextualizer(), opts.configOptions...)
|
||||
if err != nil {
|
||||
l.WithError(err).Error("Unable to instantiate configuration.")
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
r, err := NewRegistryFromDSN(ctx, c, l)
|
||||
if err != nil {
|
||||
l.WithError(err).Error("Unable to instantiate service registry.")
|
||||
return nil, err
|
||||
}
|
||||
r.slOptions = sl
|
||||
r.SetContextualizer(sl.Contextualizer())
|
||||
|
||||
return r, nil
|
||||
}
|
||||
44
driver/factory_test.go
Normal file
44
driver/factory_test.go
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package driver_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
|
||||
"github.com/ory/x/configx"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/ory/kratos/driver"
|
||||
"github.com/ory/kratos/driver/config"
|
||||
)
|
||||
|
||||
func TestDriverNew(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
r, err := driver.New(
|
||||
context.Background(),
|
||||
os.Stderr,
|
||||
driver.WithConfigOptions(
|
||||
configx.WithValue(config.ViperKeyDSN, config.DefaultSQLiteMemoryDSN),
|
||||
configx.SkipValidation(),
|
||||
))
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.EqualValues(t, config.DefaultSQLiteMemoryDSN, r.Config().DSN(ctx))
|
||||
pingCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||
t.Cleanup(cancel)
|
||||
require.NoError(t, r.Persister().Ping(pingCtx))
|
||||
|
||||
assert.NotEqual(t, uuid.Nil.String(), r.Persister().NetworkID(context.Background()).String())
|
||||
|
||||
n, err := r.Persister().DetermineNetwork(context.Background())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, r.Persister().NetworkID(context.Background()), n.ID)
|
||||
}
|
||||
313
driver/registry.go
Normal file
313
driver/registry.go
Normal file
@@ -0,0 +1,313 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/fs"
|
||||
|
||||
"github.com/gorilla/sessions"
|
||||
|
||||
"github.com/ory/x/httpx"
|
||||
|
||||
"github.com/ory/kratos/cipher"
|
||||
"github.com/ory/kratos/continuity"
|
||||
"github.com/ory/kratos/courier"
|
||||
"github.com/ory/kratos/driver/config"
|
||||
"github.com/ory/kratos/hash"
|
||||
"github.com/ory/kratos/identity"
|
||||
"github.com/ory/kratos/persistence"
|
||||
"github.com/ory/kratos/schema"
|
||||
"github.com/ory/kratos/selfservice/errorx"
|
||||
"github.com/ory/kratos/selfservice/flow/login"
|
||||
"github.com/ory/kratos/selfservice/flow/logout"
|
||||
"github.com/ory/kratos/selfservice/flow/recovery"
|
||||
"github.com/ory/kratos/selfservice/flow/registration"
|
||||
"github.com/ory/kratos/selfservice/flow/settings"
|
||||
"github.com/ory/kratos/selfservice/flow/verification"
|
||||
"github.com/ory/kratos/selfservice/sessiontokenexchange"
|
||||
"github.com/ory/kratos/selfservice/strategy/code"
|
||||
"github.com/ory/kratos/selfservice/strategy/link"
|
||||
password2 "github.com/ory/kratos/selfservice/strategy/password"
|
||||
"github.com/ory/kratos/session"
|
||||
"github.com/ory/kratos/x"
|
||||
"github.com/ory/kratos/x/nosurfx"
|
||||
"github.com/ory/nosurf"
|
||||
"github.com/ory/pop/v6"
|
||||
"github.com/ory/x/clock"
|
||||
"github.com/ory/x/configx"
|
||||
"github.com/ory/x/contextx"
|
||||
"github.com/ory/x/healthx"
|
||||
"github.com/ory/x/httprouterx"
|
||||
"github.com/ory/x/jsonnetsecure"
|
||||
"github.com/ory/x/logrusx"
|
||||
"github.com/ory/x/otelx"
|
||||
"github.com/ory/x/popx"
|
||||
"github.com/ory/x/servicelocatorx"
|
||||
)
|
||||
|
||||
type Registry interface {
|
||||
Init(ctx context.Context, ctxer contextx.Contextualizer, opts ...RegistryOption) error
|
||||
|
||||
SetLogger(l *logrusx.Logger)
|
||||
SetJSONNetVMProvider(jsonnetsecure.VMProvider)
|
||||
|
||||
// Clock returns the time source used for time-dependent behavior such as
|
||||
// flow expiry. Tests can override it via RegistryDefault.SetClock.
|
||||
Clock() clock.Clock
|
||||
|
||||
WithCSRFHandler(c nosurf.Handler)
|
||||
WithCSRFTokenGenerator(cg nosurfx.CSRFToken)
|
||||
|
||||
HealthHandler(ctx context.Context) *healthx.Handler
|
||||
CookieManager(ctx context.Context) sessions.StoreExact
|
||||
ContinuityCookieManager(ctx context.Context) sessions.StoreExact
|
||||
|
||||
RegisterPublicRoutes(ctx context.Context, public *httprouterx.RouterPublic)
|
||||
RegisterAdminRoutes(ctx context.Context, admin *httprouterx.RouterAdmin)
|
||||
Tracer(context.Context) *otelx.Tracer
|
||||
SetTracer(*otelx.Tracer)
|
||||
|
||||
config.Provider
|
||||
CourierConfig() config.CourierConfigs
|
||||
SetConfig(c *config.Config)
|
||||
SetContextualizer(ctxer contextx.Contextualizer)
|
||||
|
||||
nosurfx.CSRFProvider
|
||||
httpx.WriterProvider
|
||||
logrusx.Provider
|
||||
httpx.ClientProvider
|
||||
jsonnetsecure.VMProvider
|
||||
|
||||
continuity.ManagementProvider
|
||||
continuity.PersistenceProvider
|
||||
|
||||
cipher.Provider
|
||||
|
||||
courier.Provider
|
||||
|
||||
persistence.Provider
|
||||
|
||||
errorx.ManagementProvider
|
||||
errorx.HandlerProvider
|
||||
errorx.PersistenceProvider
|
||||
|
||||
hash.HashProvider
|
||||
|
||||
identity.HandlerProvider
|
||||
identity.ValidationProvider
|
||||
identity.PoolProvider
|
||||
identity.PrivilegedPoolProvider
|
||||
identity.ManagementProvider
|
||||
identity.ActiveCredentialsCounterStrategyProvider
|
||||
|
||||
courier.HandlerProvider
|
||||
courier.PersistenceProvider
|
||||
|
||||
schema.HandlerProvider
|
||||
schema.IdentitySchemaProvider
|
||||
|
||||
password2.ValidationProvider
|
||||
|
||||
session.HandlerProvider
|
||||
session.ManagementProvider
|
||||
session.PersistenceProvider
|
||||
session.TokenizerProvider
|
||||
|
||||
settings.HandlerProvider
|
||||
settings.ErrorHandlerProvider
|
||||
settings.FlowPersistenceProvider
|
||||
settings.StrategyProvider
|
||||
|
||||
login.FlowPersistenceProvider
|
||||
login.ErrorHandlerProvider
|
||||
login.HooksProvider
|
||||
login.HookExecutorProvider
|
||||
login.HandlerProvider
|
||||
login.StrategyProvider
|
||||
|
||||
logout.HandlerProvider
|
||||
|
||||
registration.FlowPersistenceProvider
|
||||
registration.ErrorHandlerProvider
|
||||
registration.HooksProvider
|
||||
registration.HookExecutorProvider
|
||||
registration.HandlerProvider
|
||||
registration.StrategyProvider
|
||||
|
||||
verification.FlowPersistenceProvider
|
||||
verification.ErrorHandlerProvider
|
||||
verification.HandlerProvider
|
||||
verification.StrategyProvider
|
||||
|
||||
sessiontokenexchange.PersistenceProvider
|
||||
|
||||
link.SenderProvider
|
||||
link.VerificationTokenPersistenceProvider
|
||||
link.RecoveryTokenPersistenceProvider
|
||||
|
||||
code.SenderProvider
|
||||
code.RecoveryCodePersistenceProvider
|
||||
|
||||
recovery.FlowPersistenceProvider
|
||||
recovery.ErrorHandlerProvider
|
||||
recovery.HandlerProvider
|
||||
recovery.StrategyProvider
|
||||
|
||||
nosurfx.CSRFTokenGeneratorProvider
|
||||
}
|
||||
|
||||
func NewRegistryFromDSN(ctx context.Context, c *config.Config, l *logrusx.Logger) (*RegistryDefault, error) {
|
||||
reg := NewRegistryDefault()
|
||||
|
||||
tracer, err := otelx.New("Ory Kratos", l, c.Tracing(ctx))
|
||||
if err != nil {
|
||||
l.WithError(err).Fatalf("failed to initialize tracer")
|
||||
tracer = otelx.NewNoop()
|
||||
}
|
||||
reg.SetTracer(tracer)
|
||||
reg.SetLogger(l)
|
||||
reg.SetConfig(c)
|
||||
|
||||
return reg, nil
|
||||
}
|
||||
|
||||
type options struct {
|
||||
skipNetworkInit bool
|
||||
config *config.Config
|
||||
configOptions []configx.OptionModifier
|
||||
replaceTracer func(*otelx.Tracer) *otelx.Tracer
|
||||
replaceIdentitySchemaProvider func(Registry) schema.IdentitySchemaProvider
|
||||
inspect func(Registry) error
|
||||
extraMigrations []fs.FS
|
||||
extraGoMigrations popx.Migrations
|
||||
replacementStrategies []NewStrategy
|
||||
extraHooks map[string]NewHookFn
|
||||
extraHashers map[string]NewHasherFn
|
||||
extraHandlers []NewHandler
|
||||
disableMigrationLogging bool
|
||||
jsonnetPool jsonnetsecure.Pool
|
||||
serviceLocatorOptions []servicelocatorx.Option
|
||||
dbOpts []func(details *pop.ConnectionDetails)
|
||||
}
|
||||
|
||||
type RegistryOption func(*options)
|
||||
|
||||
// WithDBOptions adds database connection options that will be applied to the
|
||||
// underlying connection.
|
||||
func WithDBOptions(opts ...func(details *pop.ConnectionDetails)) RegistryOption {
|
||||
return func(o *options) {
|
||||
o.dbOpts = append(o.dbOpts, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
func SkipNetworkInit(o *options) {
|
||||
o.skipNetworkInit = true
|
||||
}
|
||||
|
||||
func WithJsonnetPool(pool jsonnetsecure.Pool) RegistryOption {
|
||||
return func(o *options) {
|
||||
o.jsonnetPool = pool
|
||||
}
|
||||
}
|
||||
|
||||
func WithConfig(config *config.Config) RegistryOption {
|
||||
return func(o *options) {
|
||||
o.config = config
|
||||
}
|
||||
}
|
||||
|
||||
func WithConfigOptions(opts ...configx.OptionModifier) RegistryOption {
|
||||
return func(o *options) {
|
||||
o.configOptions = append(o.configOptions, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
func WithIdentitySchemaProvider(f func(r Registry) schema.IdentitySchemaProvider) RegistryOption {
|
||||
return func(o *options) {
|
||||
o.replaceIdentitySchemaProvider = f
|
||||
}
|
||||
}
|
||||
|
||||
func ReplaceTracer(f func(*otelx.Tracer) *otelx.Tracer) RegistryOption {
|
||||
return func(o *options) {
|
||||
o.replaceTracer = f
|
||||
}
|
||||
}
|
||||
|
||||
type NewStrategy func(deps any) any
|
||||
|
||||
// WithReplaceStrategies adds a strategy to the registry. This is useful if you want to
|
||||
// add a custom strategy to the registry. Default strategies with the same
|
||||
// name/ID will be overwritten.
|
||||
func WithReplaceStrategies(s ...NewStrategy) RegistryOption {
|
||||
return func(o *options) {
|
||||
o.replacementStrategies = append(o.replacementStrategies, s...)
|
||||
}
|
||||
}
|
||||
|
||||
type NewHookFn func(config.SelfServiceHook, Registry) any
|
||||
|
||||
func WithExtraHooks(hooks map[string]NewHookFn) RegistryOption {
|
||||
return func(o *options) {
|
||||
o.extraHooks = hooks
|
||||
}
|
||||
}
|
||||
|
||||
type NewHasherFn func(reg Registry) hash.Hasher
|
||||
|
||||
// WithExtraHashers registers additional password hashers, keyed by the
|
||||
// hashers.algorithm value that selects them. An extra hasher takes precedence
|
||||
// over a built-in hasher with the same name.
|
||||
func WithExtraHashers(hashers map[string]NewHasherFn) RegistryOption {
|
||||
return func(o *options) {
|
||||
o.extraHashers = hashers
|
||||
}
|
||||
}
|
||||
|
||||
type NewHandler func(deps any) x.Handler
|
||||
|
||||
func WithExtraHandlers(handlers ...NewHandler) RegistryOption {
|
||||
return func(o *options) {
|
||||
o.extraHandlers = handlers
|
||||
}
|
||||
}
|
||||
|
||||
func Inspect(f func(reg Registry) error) RegistryOption {
|
||||
return func(o *options) {
|
||||
o.inspect = f
|
||||
}
|
||||
}
|
||||
|
||||
func WithExtraMigrations(m ...fs.FS) RegistryOption {
|
||||
return func(o *options) {
|
||||
o.extraMigrations = append(o.extraMigrations, m...)
|
||||
}
|
||||
}
|
||||
|
||||
func WithExtraGoMigrations(m ...popx.Migration) RegistryOption {
|
||||
return func(o *options) {
|
||||
o.extraGoMigrations = append(o.extraGoMigrations, m...)
|
||||
}
|
||||
}
|
||||
|
||||
func WithDisabledMigrationLogging() RegistryOption {
|
||||
return func(o *options) {
|
||||
o.disableMigrationLogging = true
|
||||
}
|
||||
}
|
||||
|
||||
func WithServiceLocatorOptions(opts ...servicelocatorx.Option) RegistryOption {
|
||||
return func(o *options) {
|
||||
o.serviceLocatorOptions = append(o.serviceLocatorOptions, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
func newOptions(os []RegistryOption) *options {
|
||||
o := new(options)
|
||||
for _, f := range os {
|
||||
f(o)
|
||||
}
|
||||
return o
|
||||
}
|
||||
978
driver/registry_default.go
Normal file
978
driver/registry_default.go
Normal file
@@ -0,0 +1,978 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cenkalti/backoff"
|
||||
"github.com/dgraph-io/ristretto/v2"
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/hashicorp/go-retryablehttp"
|
||||
"github.com/lestrrat-go/jwx/jwk"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/negroni"
|
||||
|
||||
"github.com/ory/herodot"
|
||||
"github.com/ory/kratos/cipher"
|
||||
"github.com/ory/kratos/continuity"
|
||||
"github.com/ory/kratos/courier"
|
||||
"github.com/ory/kratos/driver/config"
|
||||
"github.com/ory/kratos/hash"
|
||||
"github.com/ory/kratos/hydra"
|
||||
"github.com/ory/kratos/identity"
|
||||
"github.com/ory/kratos/persistence"
|
||||
"github.com/ory/kratos/persistence/sql"
|
||||
"github.com/ory/kratos/schema"
|
||||
"github.com/ory/kratos/selfservice/errorx"
|
||||
"github.com/ory/kratos/selfservice/flow"
|
||||
"github.com/ory/kratos/selfservice/flow/login"
|
||||
"github.com/ory/kratos/selfservice/flow/logout"
|
||||
"github.com/ory/kratos/selfservice/flow/recovery"
|
||||
"github.com/ory/kratos/selfservice/flow/registration"
|
||||
"github.com/ory/kratos/selfservice/flow/settings"
|
||||
"github.com/ory/kratos/selfservice/flow/verification"
|
||||
"github.com/ory/kratos/selfservice/hook"
|
||||
"github.com/ory/kratos/selfservice/strategy/code"
|
||||
"github.com/ory/kratos/selfservice/strategy/idfirst"
|
||||
"github.com/ory/kratos/selfservice/strategy/link"
|
||||
"github.com/ory/kratos/selfservice/strategy/lookup"
|
||||
"github.com/ory/kratos/selfservice/strategy/oidc"
|
||||
"github.com/ory/kratos/selfservice/strategy/passkey"
|
||||
"github.com/ory/kratos/selfservice/strategy/password"
|
||||
"github.com/ory/kratos/selfservice/strategy/profile"
|
||||
"github.com/ory/kratos/selfservice/strategy/totp"
|
||||
"github.com/ory/kratos/selfservice/strategy/webauthn"
|
||||
"github.com/ory/kratos/session"
|
||||
"github.com/ory/kratos/x"
|
||||
"github.com/ory/kratos/x/nosurfx"
|
||||
"github.com/ory/kratos/x/transaction"
|
||||
"github.com/ory/kratos/x/webauthnx"
|
||||
"github.com/ory/nosurf"
|
||||
"github.com/ory/pop/v6"
|
||||
"github.com/ory/x/clock"
|
||||
"github.com/ory/x/contextx"
|
||||
"github.com/ory/x/dbal"
|
||||
"github.com/ory/x/healthx"
|
||||
"github.com/ory/x/httprouterx"
|
||||
"github.com/ory/x/httpx"
|
||||
"github.com/ory/x/jsonnetsecure"
|
||||
"github.com/ory/x/jwksx"
|
||||
"github.com/ory/x/logrusx"
|
||||
"github.com/ory/x/otelx"
|
||||
"github.com/ory/x/popx"
|
||||
"github.com/ory/x/prometheusx"
|
||||
"github.com/ory/x/servicelocatorx"
|
||||
"github.com/ory/x/sqlcon"
|
||||
"github.com/ory/x/sqlxx"
|
||||
)
|
||||
|
||||
type RegistryDefault struct {
|
||||
l *logrusx.Logger
|
||||
c *config.Config
|
||||
|
||||
// clock is the time source for time-dependent behavior such as flow expiry.
|
||||
// It is set eagerly in initCheapMembers and replaced in tests via SetClock.
|
||||
clock clock.Clock
|
||||
|
||||
ctxer contextx.Contextualizer
|
||||
|
||||
injectedSelfserviceHooks map[string]NewHookFn
|
||||
extraHandlerFactories []NewHandler
|
||||
extraHandlers []x.Handler
|
||||
slOptions *servicelocatorx.Options
|
||||
|
||||
nosurf nosurf.Handler
|
||||
trc *otelx.Tracer
|
||||
writer herodot.Writer
|
||||
healthxHandler *healthx.Handler
|
||||
|
||||
persister persistence.Persister
|
||||
migrationStatus popx.MigrationStatuses
|
||||
|
||||
hookVerifier *hook.Verifier
|
||||
hookSessionIssuer *hook.SessionIssuer
|
||||
hookSessionDestroyer *hook.SessionDestroyer
|
||||
hookAddressVerifier *hook.AddressVerifier
|
||||
hookShowVerificationUI *hook.ShowVerificationUIHook
|
||||
hookVerifyNewAddress *hook.VerifyNewAddress
|
||||
|
||||
identityHandler *identity.Handler
|
||||
identityValidator *identity.Validator
|
||||
identityManager *identity.Manager
|
||||
identitySchemaProvider schema.IdentitySchemaProvider
|
||||
|
||||
courierHandler *courier.Handler
|
||||
|
||||
continuityManager *continuity.Manager
|
||||
|
||||
schemaHandler *schema.Handler
|
||||
|
||||
sessionHandler *session.Handler
|
||||
sessionManager session.Manager
|
||||
sessionTokenizer initOnce[*session.Tokenizer]
|
||||
|
||||
passwordHasher initOnce[hash.Hasher]
|
||||
extraHashers map[string]NewHasherFn
|
||||
passwordValidator initOnce[password.Validator]
|
||||
|
||||
crypter initOnce[cipher.Cipher]
|
||||
|
||||
errorHandler *errorx.Handler
|
||||
errorManager *errorx.Manager
|
||||
|
||||
selfserviceRegistrationExecutor *registration.HookExecutor
|
||||
selfserviceRegistrationHandler *registration.Handler
|
||||
seflserviceRegistrationErrorHandler *registration.ErrorHandler
|
||||
selfserviceRegistrationRequestErrorHandler *registration.ErrorHandler
|
||||
|
||||
selfserviceLoginExecutor *login.HookExecutor
|
||||
selfserviceLoginHandler *login.Handler
|
||||
selfserviceLoginRequestErrorHandler *login.ErrorHandler
|
||||
|
||||
selfserviceSettingsHandler *settings.Handler
|
||||
selfserviceSettingsErrorHandler *settings.ErrorHandler
|
||||
selfserviceSettingsExecutor *settings.HookExecutor
|
||||
|
||||
selfserviceVerifyErrorHandler *verification.ErrorHandler
|
||||
selfserviceVerifyManager *identity.Manager
|
||||
selfserviceVerifyHandler *verification.Handler
|
||||
selfserviceVerificationExecutor *verification.HookExecutor
|
||||
|
||||
selfserviceLinkSender *link.Sender
|
||||
selfserviceCodeSender *code.Sender
|
||||
|
||||
selfserviceRecoveryErrorHandler *recovery.ErrorHandler
|
||||
selfserviceRecoveryHandler *recovery.Handler
|
||||
selfserviceRecoveryExecutor *recovery.HookExecutor
|
||||
|
||||
selfserviceLogoutHandler *logout.Handler
|
||||
|
||||
selfserviceStrategies []any
|
||||
replacementSelfserviceStrategies []NewStrategy
|
||||
|
||||
hydra initOnce[hydra.Hydra]
|
||||
|
||||
csrfTokenGenerator nosurfx.CSRFToken
|
||||
|
||||
jsonnetVMProvider initOnce[jsonnetsecure.VMProvider]
|
||||
jsonnetPool jsonnetsecure.Pool
|
||||
jwkFetcher initOnce[*jwksx.FetcherNext]
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) JsonnetVM(ctx context.Context) (jsonnetsecure.VM, error) {
|
||||
return m.jsonnetVMProvider.Get(func() jsonnetsecure.VMProvider {
|
||||
return &jsonnetsecure.DefaultProvider{Subcommand: "jsonnet", Pool: m.jsonnetPool}
|
||||
}).JsonnetVM(ctx)
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) Audit() *logrusx.Logger {
|
||||
return m.Logger().WithField("audience", "audit")
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) RegisterPublicRoutes(ctx context.Context, router *httprouterx.RouterPublic) {
|
||||
for _, h := range m.ExtraHandlers() {
|
||||
h.RegisterPublicRoutes(router)
|
||||
}
|
||||
m.LoginHandler().RegisterPublicRoutes(router)
|
||||
m.RegistrationHandler().RegisterPublicRoutes(router)
|
||||
m.LogoutHandler().RegisterPublicRoutes(router)
|
||||
m.SettingsHandler().RegisterPublicRoutes(router)
|
||||
m.IdentityHandler().RegisterPublicRoutes(router)
|
||||
m.CourierHandler().RegisterPublicRoutes(router)
|
||||
m.SessionHandler().RegisterPublicRoutes(router)
|
||||
m.SelfServiceErrorHandler().RegisterPublicRoutes(router)
|
||||
m.SchemaHandler().RegisterPublicRoutes(router)
|
||||
|
||||
m.RecoveryHandler().RegisterPublicRoutes(router)
|
||||
|
||||
m.VerificationHandler().RegisterPublicRoutes(router)
|
||||
|
||||
m.HealthHandler(ctx).SetHealthRoutes(router, false)
|
||||
webauthnx.RegisterWebauthnRoute(router)
|
||||
|
||||
for _, s := range m.selfServiceStrategies() {
|
||||
s, ok := s.(x.PublicHandler)
|
||||
if ok {
|
||||
s.RegisterPublicRoutes(router)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) RegisterAdminRoutes(ctx context.Context, router *httprouterx.RouterAdmin) {
|
||||
for _, h := range m.ExtraHandlers() {
|
||||
h.RegisterAdminRoutes(router)
|
||||
}
|
||||
m.RegistrationHandler().RegisterAdminRoutes(router)
|
||||
m.LoginHandler().RegisterAdminRoutes(router)
|
||||
m.LogoutHandler().RegisterAdminRoutes(router)
|
||||
m.SchemaHandler().RegisterAdminRoutes(router)
|
||||
m.SettingsHandler().RegisterAdminRoutes(router)
|
||||
m.IdentityHandler().RegisterAdminRoutes(router)
|
||||
m.CourierHandler().RegisterAdminRoutes(router)
|
||||
m.SelfServiceErrorHandler().RegisterAdminRoutes(router)
|
||||
|
||||
m.RecoveryHandler().RegisterAdminRoutes(router)
|
||||
m.SessionHandler().RegisterAdminRoutes(router)
|
||||
|
||||
m.VerificationHandler().RegisterAdminRoutes(router)
|
||||
|
||||
m.HealthHandler(ctx).SetHealthRoutes(router, true)
|
||||
m.HealthHandler(ctx).SetVersionRoutes(router)
|
||||
router.GET(prometheusx.MetricsPrometheusPath, prometheusx.Handler().ServeHTTP)
|
||||
config.RegisterConfigHashRoute(m, router)
|
||||
|
||||
for _, s := range m.selfServiceStrategies() {
|
||||
s, ok := s.(x.AdminHandler)
|
||||
if ok {
|
||||
s.RegisterAdminRoutes(router)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) HTTPMiddlewares() []negroni.Handler {
|
||||
return m.slOptions.HTTPMiddlewares()
|
||||
}
|
||||
|
||||
func NewRegistryDefault() *RegistryDefault {
|
||||
r := &RegistryDefault{
|
||||
trc: otelx.NewNoop(),
|
||||
slOptions: &servicelocatorx.Options{},
|
||||
}
|
||||
r.initCheapMembers()
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) SetLogger(l *logrusx.Logger) {
|
||||
m.l = l
|
||||
}
|
||||
|
||||
// Clock returns the registry's time source. It is eagerly initialized in
|
||||
// initCheapMembers, so this getter never lazily initializes.
|
||||
func (m *RegistryDefault) Clock() clock.Clock {
|
||||
return m.clock
|
||||
}
|
||||
|
||||
// SetClock replaces the registry's time source. Intended for tests that need
|
||||
// deterministic control over time-dependent behavior such as flow expiry.
|
||||
func (m *RegistryDefault) SetClock(c clock.Clock) {
|
||||
m.clock = c
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) SetJSONNetVMProvider(p jsonnetsecure.VMProvider) {
|
||||
m.jsonnetVMProvider.Set(p)
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) LogoutHandler() *logout.Handler {
|
||||
if m.selfserviceLogoutHandler == nil {
|
||||
m.selfserviceLogoutHandler = logout.NewHandler(m)
|
||||
}
|
||||
return m.selfserviceLogoutHandler
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) HealthHandler(_ context.Context) *healthx.Handler {
|
||||
if m.healthxHandler == nil {
|
||||
m.healthxHandler = healthx.NewHandler(m.Writer(), config.Version,
|
||||
healthx.ReadyCheckers{
|
||||
"database": func(r *http.Request) error {
|
||||
return m.PingContext(r.Context())
|
||||
},
|
||||
"migrations": func(r *http.Request) error {
|
||||
if m.migrationStatus != nil && !m.migrationStatus.HasPending() {
|
||||
return nil
|
||||
}
|
||||
|
||||
status, err := m.Persister().MigrationStatus(r.Context())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if status.HasPending() {
|
||||
return errors.Errorf("migrations have not yet been fully applied")
|
||||
}
|
||||
|
||||
m.migrationStatus = status
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return m.healthxHandler
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) WithCSRFHandler(c nosurf.Handler) {
|
||||
m.nosurf = c
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) CSRFHandler() nosurf.Handler {
|
||||
if m.nosurf == nil {
|
||||
panic("csrf handler is not set")
|
||||
}
|
||||
return m.nosurf
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) Config() *config.Config {
|
||||
if m.c == nil {
|
||||
panic("configuration not set")
|
||||
}
|
||||
return m.c
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) CourierConfig() config.CourierConfigs {
|
||||
return m.Config()
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) selfServiceStrategies() []any {
|
||||
if len(m.selfserviceStrategies) == 0 {
|
||||
if m.replacementSelfserviceStrategies != nil {
|
||||
// Construct self-service strategies from the replacements
|
||||
for _, newStrategy := range m.replacementSelfserviceStrategies {
|
||||
m.selfserviceStrategies = append(m.selfserviceStrategies, newStrategy(m))
|
||||
}
|
||||
} else {
|
||||
// Construct the default list of strategies
|
||||
m.selfserviceStrategies = []any{
|
||||
profile.NewStrategy(m), // <- should remain first
|
||||
password.NewStrategy(m),
|
||||
oidc.NewStrategy(m),
|
||||
code.NewStrategy(m),
|
||||
link.NewStrategy(m),
|
||||
totp.NewStrategy(m),
|
||||
passkey.NewStrategy(m),
|
||||
webauthn.NewStrategy(m),
|
||||
lookup.NewStrategy(m),
|
||||
idfirst.NewStrategy(m),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m.selfserviceStrategies
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) strategyRegistrationEnabled(ctx context.Context, id string) bool {
|
||||
if id == "profile" {
|
||||
return true
|
||||
}
|
||||
return m.Config().SelfServiceStrategy(ctx, id).Enabled
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) strategyLoginEnabled(ctx context.Context, id string) bool {
|
||||
return m.Config().SelfServiceStrategy(ctx, id).Enabled
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) RegistrationStrategies(ctx context.Context, filters ...registration.StrategyFilter) (registrationStrategies registration.Strategies) {
|
||||
nextStrategy:
|
||||
for _, strategy := range m.selfServiceStrategies() {
|
||||
if s, ok := strategy.(registration.Strategy); ok {
|
||||
for _, filter := range filters {
|
||||
if !filter(s) {
|
||||
continue nextStrategy
|
||||
}
|
||||
}
|
||||
if m.strategyRegistrationEnabled(ctx, s.ID().String()) || supportsOrganizations(strategy) {
|
||||
registrationStrategies = append(registrationStrategies, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) AllRegistrationStrategies() registration.Strategies {
|
||||
var registrationStrategies []registration.Strategy
|
||||
|
||||
for _, strategy := range m.selfServiceStrategies() {
|
||||
if s, ok := strategy.(registration.Strategy); ok {
|
||||
registrationStrategies = append(registrationStrategies, s)
|
||||
}
|
||||
}
|
||||
return registrationStrategies
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) LoginStrategies(ctx context.Context, filters ...login.StrategyFilter) (loginStrategies login.Strategies) {
|
||||
nextStrategy:
|
||||
for _, strategy := range m.selfServiceStrategies() {
|
||||
if s, ok := strategy.(login.Strategy); ok {
|
||||
for _, filter := range filters {
|
||||
if !filter(s) {
|
||||
continue nextStrategy
|
||||
}
|
||||
}
|
||||
|
||||
if m.strategyLoginEnabled(ctx, s.ID().String()) || supportsOrganizations(strategy) {
|
||||
loginStrategies = append(loginStrategies, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// TestStrategy returns the OIDC strategy as a login.TestStrategy for
|
||||
// admin-created test login flows. Only the OIDC strategy implements the
|
||||
// test-mode single-provider UI. Returns nil if the OIDC strategy is not
|
||||
// registered or disabled in config; callers must handle that case as a
|
||||
// misconfiguration rather than crashing the process.
|
||||
//
|
||||
// The strategy list may contain several strategies that implement the test
|
||||
// interface: derivatives of the OIDC strategy registered under a different
|
||||
// credentials type (e.g. SAML or organization sign-in) inherit it through
|
||||
// embedding, but they resolve providers from their own method's config
|
||||
// section. Only the strategy with the OIDC credentials type reads
|
||||
// selfservice.methods.oidc.config.providers, so select by credentials type
|
||||
// rather than returning the first match.
|
||||
func (m *RegistryDefault) TestStrategy(ctx context.Context) login.TestStrategy {
|
||||
type testStrategy interface {
|
||||
login.TestStrategy
|
||||
login.Strategy
|
||||
}
|
||||
for _, strategy := range m.selfServiceStrategies() {
|
||||
if s, ok := strategy.(testStrategy); ok {
|
||||
if s.ID() == identity.CredentialsTypeOIDC && m.strategyLoginEnabled(ctx, s.ID().String()) {
|
||||
return s
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// supportsOrganizations checks if a strategy implements organization-based authentication.
|
||||
// Organization strategies manage their own enablement via provider configuration,
|
||||
// not via the strategy-enabled config flag, so they bypass the strategyLoginEnabled /
|
||||
// strategyRegistrationEnabled check.
|
||||
func supportsOrganizations(s any) bool {
|
||||
o, ok := s.(flow.OrganizationImplementor)
|
||||
return ok && o.SupportsOrganizations()
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) AllLoginStrategies() login.Strategies {
|
||||
var loginStrategies []login.Strategy
|
||||
for _, strategy := range m.selfServiceStrategies() {
|
||||
if s, ok := strategy.(login.Strategy); ok {
|
||||
loginStrategies = append(loginStrategies, s)
|
||||
}
|
||||
}
|
||||
return loginStrategies
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) ActiveCredentialsCounterStrategies(_ context.Context) (activeCredentialsCounterStrategies []identity.ActiveCredentialsCounter) {
|
||||
for _, strategy := range m.selfServiceStrategies() {
|
||||
if s, ok := strategy.(identity.ActiveCredentialsCounter); ok {
|
||||
activeCredentialsCounterStrategies = append(activeCredentialsCounterStrategies, s)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) IdentityValidator() *identity.Validator {
|
||||
return m.identityValidator
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) SetConfig(c *config.Config) {
|
||||
m.c = c
|
||||
}
|
||||
|
||||
// WithSelfserviceStrategies is only available in testing and overrides the
|
||||
// selfservice strategies with the given ones.
|
||||
func (m *RegistryDefault) WithSelfserviceStrategies(t testing.TB, strategies []any) Registry {
|
||||
if t == nil {
|
||||
panic("Passing selfservice strategies is only supported in testing")
|
||||
}
|
||||
m.selfserviceStrategies = strategies
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) Writer() herodot.Writer {
|
||||
if m.writer == nil {
|
||||
h := herodot.NewJSONWriter(m.Logger())
|
||||
m.writer = h
|
||||
}
|
||||
return m.writer
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) Logger() *logrusx.Logger {
|
||||
if m.l == nil {
|
||||
m.l = logrusx.New("Ory Kratos", config.Version)
|
||||
}
|
||||
return m.l
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) IdentityHandler() *identity.Handler {
|
||||
if m.identityHandler == nil {
|
||||
m.identityHandler = identity.NewHandler(m)
|
||||
}
|
||||
return m.identityHandler
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) CourierHandler() *courier.Handler {
|
||||
if m.courierHandler == nil {
|
||||
m.courierHandler = courier.NewHandler(m)
|
||||
}
|
||||
return m.courierHandler
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) SchemaHandler() *schema.Handler {
|
||||
if m.schemaHandler == nil {
|
||||
m.schemaHandler = schema.NewHandler(m)
|
||||
}
|
||||
return m.schemaHandler
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) SessionHandler() *session.Handler {
|
||||
if m.sessionHandler == nil {
|
||||
m.sessionHandler = session.NewHandler(m)
|
||||
}
|
||||
return m.sessionHandler
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) Cipher(ctx context.Context) cipher.Cipher {
|
||||
return m.crypter.Get(func() cipher.Cipher {
|
||||
switch m.c.CipherAlgorithm(ctx) {
|
||||
case "xchacha20-poly1305":
|
||||
return cipher.NewCryptChaCha20(m.Config())
|
||||
case "aes":
|
||||
return cipher.NewCryptAES(m.Config())
|
||||
default:
|
||||
m.l.Logger.Warning("No encryption configuration found. The default algorithm (noop) will be used, resulting in sensitive data being stored in plaintext")
|
||||
return cipher.NewNoop()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// WithHashers registers additional password hashers, keyed by the
|
||||
// hashers.algorithm value that selects them. See WithExtraHashers.
|
||||
func (m *RegistryDefault) WithHashers(hashers map[string]NewHasherFn) {
|
||||
m.extraHashers = hashers
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) Hasher(ctx context.Context) hash.Hasher {
|
||||
return m.passwordHasher.Get(func() hash.Hasher {
|
||||
alg := m.c.HasherPasswordHashingAlgorithm(ctx)
|
||||
if newHasher, ok := m.extraHashers[alg]; ok {
|
||||
return newHasher(m)
|
||||
}
|
||||
if alg == "bcrypt" {
|
||||
return hash.NewHasherBcrypt(m)
|
||||
}
|
||||
return hash.NewHasherArgon2(m)
|
||||
})
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) PasswordValidator() password.Validator {
|
||||
m.passwordValidator.Get(func() password.Validator {
|
||||
val, err := password.NewDefaultPasswordValidatorStrategy(m)
|
||||
if err != nil {
|
||||
m.Logger().WithError(err).Fatal("could not initialize DefaultPasswordValidator")
|
||||
}
|
||||
return val
|
||||
})
|
||||
return m.passwordValidator.value
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) SelfServiceErrorHandler() *errorx.Handler {
|
||||
if m.errorHandler == nil {
|
||||
m.errorHandler = errorx.NewHandler(m)
|
||||
}
|
||||
return m.errorHandler
|
||||
}
|
||||
|
||||
// cookieStoreKeyPairs derives the (hashKey, blockKey) pairs securecookie
|
||||
// expects: each secret signs, and its SHA-256 digest encrypts. This way a
|
||||
// single configured secret yields both signing and encryption, and rotation
|
||||
// rotates both.
|
||||
func cookieStoreKeyPairs(secrets [][]byte) [][]byte {
|
||||
keys := make([][]byte, 0, 2*len(secrets))
|
||||
for _, k := range secrets {
|
||||
encrypt := sha256.Sum256(k)
|
||||
keys = append(keys, k, encrypt[:])
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) CookieManager(ctx context.Context) sessions.StoreExact {
|
||||
cs := sessions.NewCookieStore(cookieStoreKeyPairs(m.Config().SecretsSession(ctx))...)
|
||||
cs.Options.Secure = m.Config().SessionCookieSecure(ctx)
|
||||
cs.Options.HttpOnly = true
|
||||
|
||||
if domain := m.Config().SessionDomain(ctx); domain != "" {
|
||||
cs.Options.Domain = domain
|
||||
}
|
||||
|
||||
if path := m.Config().SessionPath(ctx); path != "" {
|
||||
cs.Options.Path = path
|
||||
}
|
||||
|
||||
if sameSite := m.Config().SessionSameSiteMode(ctx); sameSite != 0 {
|
||||
cs.Options.SameSite = sameSite
|
||||
}
|
||||
|
||||
cs.Options.MaxAge = 0
|
||||
if m.Config().SessionPersistentCookie(ctx) {
|
||||
cs.Options.MaxAge = int(m.Config().SessionLifespan(ctx).Seconds())
|
||||
cs.MaxAge(cs.Options.MaxAge)
|
||||
}
|
||||
return cs
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) ContinuityCookieManager(ctx context.Context) sessions.StoreExact {
|
||||
// To support hot reloading, this can not be instantiated only once.
|
||||
secrets := m.Config().SecretsSession(ctx)
|
||||
// Cookies issued before the derived-block-key fix used the raw secrets as
|
||||
// (hashKey, blockKey) pairs. Appending the raw secrets after the derived
|
||||
// pairs keeps those cookies readable as a decode fallback (encoding always
|
||||
// uses the first pair). Remove once cookies issued by pre-fix versions
|
||||
// have expired.
|
||||
cs := sessions.NewCookieStore(append(cookieStoreKeyPairs(secrets), secrets...)...)
|
||||
cs.Options.Secure = m.Config().CookieSecure(ctx)
|
||||
cs.Options.HttpOnly = true
|
||||
cs.Options.SameSite = http.SameSiteLaxMode
|
||||
return cs
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) Tracer(context.Context) *otelx.Tracer {
|
||||
if m.trc == nil {
|
||||
return otelx.NewNoop()
|
||||
}
|
||||
return m.trc
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) SetTracer(t *otelx.Tracer) {
|
||||
m.trc = t
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) SessionManager() session.Manager {
|
||||
return m.sessionManager
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) Hydra() hydra.Hydra {
|
||||
return m.hydra.Get(func() hydra.Hydra {
|
||||
return hydra.NewDefaultHydra(m)
|
||||
})
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) SetHydra(h hydra.Hydra) {
|
||||
m.hydra.Set(h)
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) SelfServiceErrorManager() *errorx.Manager {
|
||||
return m.errorManager
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) Init(ctx context.Context, ctxer contextx.Contextualizer, opts ...RegistryOption) error {
|
||||
if m.persister != nil {
|
||||
// The DSN connection can not be hot-reloaded!
|
||||
panic("RegistryDefault.Init() must not be called more than once.")
|
||||
}
|
||||
|
||||
o := newOptions(opts)
|
||||
|
||||
m.jsonnetPool = o.jsonnetPool
|
||||
|
||||
if o.replaceTracer != nil {
|
||||
m.trc = o.replaceTracer(m.trc)
|
||||
}
|
||||
|
||||
if o.replacementStrategies != nil {
|
||||
m.replacementSelfserviceStrategies = o.replacementStrategies
|
||||
}
|
||||
|
||||
if o.extraHooks != nil {
|
||||
m.WithHooks(o.extraHooks)
|
||||
}
|
||||
if o.extraHashers != nil {
|
||||
m.WithHashers(o.extraHashers)
|
||||
}
|
||||
if o.extraHandlers != nil {
|
||||
m.WithExtraHandlers(o.extraHandlers)
|
||||
}
|
||||
|
||||
if o.replaceIdentitySchemaProvider != nil {
|
||||
m.identitySchemaProvider = o.replaceIdentitySchemaProvider(m)
|
||||
}
|
||||
|
||||
bc := backoff.NewExponentialBackOff()
|
||||
bc.MaxElapsedTime = time.Minute * 5
|
||||
bc.Reset()
|
||||
err := backoff.Retry(func() error {
|
||||
m.SetContextualizer(ctxer)
|
||||
|
||||
pool, idlePool, connMaxLifetime, connMaxIdleTime, cleanedDSN := sqlcon.ParseConnectionOptions(m.l, m.Config().DSN(ctx))
|
||||
dbOpts := &pop.ConnectionDetails{
|
||||
URL: sqlcon.FinalizeDSN(m.l, cleanedDSN),
|
||||
IdlePool: idlePool,
|
||||
ConnMaxLifetime: connMaxLifetime,
|
||||
ConnMaxIdleTime: connMaxIdleTime,
|
||||
Pool: pool,
|
||||
TracerProvider: m.Tracer(ctx).Provider(),
|
||||
}
|
||||
|
||||
for _, f := range o.dbOpts {
|
||||
f(dbOpts)
|
||||
}
|
||||
|
||||
scheme, _, _ := sqlxx.ExtractSchemeFromDSN(dbOpts.URL)
|
||||
if !dbOpts.AllowMinPool && scheme == "postgres" && strings.Contains(dbOpts.URL, "pool_min_conns=") {
|
||||
err := errors.Errorf("attempting to use the option 'pool_min_conns' with Postgres, but the pgxpool connection pool is disabled, this will be rejected by the database: dsn=%s dbOpts.AllowMinPool=%v", dbOpts.URL, dbOpts.AllowMinPool)
|
||||
return backoff.Permanent(err)
|
||||
}
|
||||
if (scheme == "sqlite" || scheme == "mysql") && strings.Contains(dbOpts.URL, "pool_min_conns=") {
|
||||
err := errors.Errorf("attempting to use the option 'pool_min_conns' with %s, but connection pooling is not supported for this case: dsn=%s", scheme, dbOpts.URL)
|
||||
return backoff.Permanent(err)
|
||||
}
|
||||
|
||||
m.Logger().
|
||||
WithField("pool", pool).
|
||||
WithField("idlePool", idlePool).
|
||||
WithField("connMaxLifetime", connMaxLifetime).
|
||||
Debug("Connecting to SQL Database")
|
||||
c, err := pop.NewConnection(dbOpts)
|
||||
if err != nil {
|
||||
m.Logger().WithError(err).Warnf("Unable to connect to database, retrying.")
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
if err := c.Open(); err != nil {
|
||||
m.Logger().WithError(err).Warnf("Unable to open database, retrying.")
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
p, err := sql.NewPersister(m, c,
|
||||
sql.WithExtraMigrations(o.extraMigrations...),
|
||||
sql.WithExtraGoMigrations(o.extraGoMigrations...),
|
||||
sql.WithDisabledLogging(o.disableMigrationLogging))
|
||||
if err != nil {
|
||||
m.Logger().WithError(err).Warnf("Unable to initialize persister, retrying.")
|
||||
return err
|
||||
}
|
||||
|
||||
pingCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
defer cancel()
|
||||
if err := c.Store.SQLDB().PingContext(pingCtx); err != nil {
|
||||
m.Logger().WithError(err).Warnf("Unable to ping database, retrying.")
|
||||
return err
|
||||
}
|
||||
|
||||
// if dsn is memory we have to run the migrations on every start
|
||||
if dbal.IsMemorySQLite(m.Config().DSN(ctx)) || m.Config().DSN(ctx) == "memory" {
|
||||
m.Logger().Infoln("Ory Kratos is running migrations on every startup as DSN is memory. This means your data is lost when Kratos terminates.")
|
||||
if err := p.MigrateUp(ctx); err != nil {
|
||||
m.Logger().WithError(err).Warnf("Unable to run migrations, retrying.")
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if o.skipNetworkInit {
|
||||
m.persister = p
|
||||
return nil
|
||||
}
|
||||
|
||||
net, err := p.DetermineNetwork(ctx)
|
||||
if err != nil {
|
||||
m.Logger().WithError(err).Warnf("Unable to determine network, retrying.")
|
||||
return err
|
||||
}
|
||||
|
||||
m.persister = p.WithNetworkID(net.ID)
|
||||
return nil
|
||||
}, bc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if o.inspect != nil {
|
||||
if err := o.inspect(m); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) SetPersister(p persistence.Persister) {
|
||||
m.persister = p
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) Courier(ctx context.Context) (courier.Courier, error) {
|
||||
return courier.NewCourier(ctx, m)
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) ContinuityManager() *continuity.Manager {
|
||||
return m.continuityManager
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) Persister() persistence.Persister { return m.persister }
|
||||
func (m *RegistryDefault) ContinuityPersister() continuity.Persister { return m.persister }
|
||||
func (m *RegistryDefault) IdentityPool() identity.Pool { return m.persister }
|
||||
func (m *RegistryDefault) PrivilegedIdentityPool() identity.PrivilegedPool { return m.persister }
|
||||
func (m *RegistryDefault) FlowForTokenExchange() session.FlowForTokenExchange {
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) GetFlowForTokenExchange(ctx context.Context, flowID uuid.UUID) (any, error) {
|
||||
rf, err := m.RegistrationFlowPersister().GetRegistrationFlow(ctx, flowID)
|
||||
if err == nil {
|
||||
return rf, nil
|
||||
}
|
||||
if !errors.Is(err, sqlcon.ErrNoRows()) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lf, err := m.LoginFlowPersister().GetLoginFlow(ctx, flowID)
|
||||
if err == nil {
|
||||
return lf, nil
|
||||
}
|
||||
if !errors.Is(err, sqlcon.ErrNoRows()) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, errors.WithStack(sqlcon.ErrNoRows())
|
||||
}
|
||||
func (m *RegistryDefault) RegistrationFlowPersister() registration.FlowPersister { return m.persister }
|
||||
func (m *RegistryDefault) RecoveryFlowPersister() recovery.FlowPersister { return m.persister }
|
||||
func (m *RegistryDefault) LoginFlowPersister() login.FlowPersister { return m.persister }
|
||||
func (m *RegistryDefault) SettingsFlowPersister() settings.FlowPersister { return m.persister }
|
||||
func (m *RegistryDefault) SelfServiceErrorPersister() errorx.Persister { return m.persister }
|
||||
func (m *RegistryDefault) SessionPersister() session.Persister { return m.persister }
|
||||
func (m *RegistryDefault) CourierPersister() courier.Persister { return m.persister }
|
||||
func (m *RegistryDefault) RecoveryTokenPersister() link.RecoveryTokenPersister { return m.persister }
|
||||
func (m *RegistryDefault) RecoveryCodePersister() code.RecoveryCodePersister { return m.persister }
|
||||
func (m *RegistryDefault) LoginCodePersister() code.LoginCodePersister { return m.persister }
|
||||
func (m *RegistryDefault) VerificationTokenPersister() link.VerificationTokenPersister {
|
||||
return m.persister
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) VerificationCodePersister() code.VerificationCodePersister {
|
||||
return m.persister
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) RegistrationCodePersister() code.RegistrationCodePersister {
|
||||
return m.persister
|
||||
}
|
||||
func (m *RegistryDefault) PendingTraitsChangePersister() identity.PendingTraitsChangePersister {
|
||||
return m.Persister()
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) TransactionalPersisterProvider() transaction.Persister {
|
||||
return m.persister
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) PingContext(ctx context.Context) error {
|
||||
return m.persister.Ping(ctx)
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) Ping() error {
|
||||
return m.persister.Ping(context.Background())
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) WithCSRFTokenGenerator(cg nosurfx.CSRFToken) {
|
||||
m.csrfTokenGenerator = cg
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) GenerateCSRFToken(r *http.Request) string {
|
||||
if m.csrfTokenGenerator == nil {
|
||||
m.csrfTokenGenerator = nosurfx.DefaultCSRFToken
|
||||
}
|
||||
return m.csrfTokenGenerator(r)
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) IdentityManager() *identity.Manager {
|
||||
return m.identityManager
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) HTTPClient(_ context.Context, opts ...httpx.ResilientOptions) *retryablehttp.Client {
|
||||
opts = append([]httpx.ResilientOptions{
|
||||
httpx.ResilientClientWithLogger(m.Logger()),
|
||||
httpx.ResilientClientWithMaxRetry(2),
|
||||
httpx.ResilientClientWithConnectionTimeout(30 * time.Second),
|
||||
}, opts...)
|
||||
|
||||
// One of the few exceptions, this usually should not be hot reloaded.
|
||||
if m.Config().ClientHTTPNoPrivateIPRanges(contextx.RootContext) {
|
||||
opts = append(
|
||||
opts,
|
||||
httpx.ResilientClientDisallowInternalIPs(),
|
||||
// One of the few exceptions, this usually should not be hot reloaded.
|
||||
httpx.ResilientClientAllowInternalIPRequestsTo(m.Config().ClientHTTPPrivateIPExceptionURLs(contextx.RootContext)...),
|
||||
)
|
||||
}
|
||||
return httpx.NewResilientClient(opts...)
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) SetContextualizer(ctxer contextx.Contextualizer) {
|
||||
m.ctxer = ctxer
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) Contextualizer() contextx.Contextualizer {
|
||||
if m.ctxer == nil {
|
||||
panic("registry Contextualizer not set")
|
||||
}
|
||||
return m.ctxer
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) JWKSFetcher() *jwksx.FetcherNext {
|
||||
return m.jwkFetcher.Get(func() *jwksx.FetcherNext {
|
||||
maxItems := int64(10_000_000)
|
||||
cache, _ := ristretto.NewCache(&ristretto.Config[[]byte, jwk.Set]{
|
||||
NumCounters: maxItems * 10,
|
||||
MaxCost: maxItems,
|
||||
BufferItems: 64,
|
||||
Metrics: true,
|
||||
IgnoreInternalCost: true,
|
||||
Cost: func(value jwk.Set) int64 {
|
||||
return 1
|
||||
},
|
||||
})
|
||||
return jwksx.NewFetcherNext(cache)
|
||||
})
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) SessionTokenizer() *session.Tokenizer {
|
||||
return m.sessionTokenizer.Get(func() *session.Tokenizer { return session.NewTokenizer(m) })
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) ExtraHandlers() []x.Handler {
|
||||
if m.extraHandlers == nil {
|
||||
for _, newHandler := range m.extraHandlerFactories {
|
||||
m.extraHandlers = append(m.extraHandlers, newHandler(m))
|
||||
}
|
||||
}
|
||||
return m.extraHandlers
|
||||
}
|
||||
|
||||
// initCheapMembers initializes members that are cheap to initialize.
|
||||
func (m *RegistryDefault) initCheapMembers() {
|
||||
m.clock = clock.New()
|
||||
m.identityValidator = identity.NewValidator(m)
|
||||
m.identitySchemaProvider = schema.NewDefaultIdentityTraitsProvider(m)
|
||||
m.identityManager = identity.NewManager(m)
|
||||
m.sessionManager = session.NewManagerHTTP(m)
|
||||
m.errorManager = errorx.NewManager(m)
|
||||
m.continuityManager = continuity.NewManager(m)
|
||||
}
|
||||
|
||||
type initOnce[T any] struct {
|
||||
value T
|
||||
init sync.Once
|
||||
}
|
||||
|
||||
// Set sets the value of the initOnce, marking it as initialized.
|
||||
func (o *initOnce[T]) Set(val T) {
|
||||
// We need to both set the value and run the init function to mark the value as
|
||||
// initialized.
|
||||
o.init.Do(func() { o.value = val })
|
||||
o.value = val
|
||||
}
|
||||
|
||||
// Get returns the value of the initOnce, initializing it with newT if it has not
|
||||
// been initialized yet. `newT` is only called once, even if Get is called
|
||||
// concurrently from multiple goroutines or with different `newT` functions.
|
||||
func (o *initOnce[T]) Get(newT func() T) T {
|
||||
o.init.Do(func() { o.value = newT() })
|
||||
return o.value
|
||||
}
|
||||
142
driver/registry_default_hooks.go
Normal file
142
driver/registry_default_hooks.go
Normal file
@@ -0,0 +1,142 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/ory/kratos/driver/config"
|
||||
"github.com/ory/kratos/request"
|
||||
"github.com/ory/kratos/selfservice/hook"
|
||||
)
|
||||
|
||||
func (m *RegistryDefault) HookVerifier() *hook.Verifier {
|
||||
if m.hookVerifier == nil {
|
||||
m.hookVerifier = hook.NewVerifier(m)
|
||||
}
|
||||
return m.hookVerifier
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) HookSessionIssuer() *hook.SessionIssuer {
|
||||
if m.hookSessionIssuer == nil {
|
||||
m.hookSessionIssuer = hook.NewSessionIssuer(m)
|
||||
}
|
||||
return m.hookSessionIssuer
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) HookSessionDestroyer() *hook.SessionDestroyer {
|
||||
if m.hookSessionDestroyer == nil {
|
||||
m.hookSessionDestroyer = hook.NewSessionDestroyer(m)
|
||||
}
|
||||
return m.hookSessionDestroyer
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) HookAddressVerifier() *hook.AddressVerifier {
|
||||
if m.hookAddressVerifier == nil {
|
||||
m.hookAddressVerifier = hook.NewAddressVerifier(m)
|
||||
}
|
||||
return m.hookAddressVerifier
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) HookShowVerificationUI() *hook.ShowVerificationUIHook {
|
||||
if m.hookShowVerificationUI == nil {
|
||||
m.hookShowVerificationUI = hook.NewShowVerificationUIHook(m)
|
||||
}
|
||||
return m.hookShowVerificationUI
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) HookVerifyNewAddress() *hook.VerifyNewAddress {
|
||||
if m.hookVerifyNewAddress == nil {
|
||||
m.hookVerifyNewAddress = hook.NewVerifyNewAddress(m)
|
||||
}
|
||||
return m.hookVerifyNewAddress
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) HookNotifyPreviousAddresses(c *hook.NotifyPreviousAddressesConfig) *hook.NotifyPreviousAddresses {
|
||||
return hook.NewNotifyPreviousAddresses(m, c)
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) WithHooks(hooks map[string]NewHookFn) {
|
||||
m.injectedSelfserviceHooks = hooks
|
||||
}
|
||||
func (m *RegistryDefault) WithExtraHandlers(handlers []NewHandler) {
|
||||
m.extraHandlerFactories = handlers
|
||||
}
|
||||
|
||||
func getHooks[T any](m *RegistryDefault, credentialsType string, configs []config.SelfServiceHook) ([]T, error) {
|
||||
hooks := make([]T, 0, len(configs))
|
||||
|
||||
var addSessionIssuer bool
|
||||
allHooksLoop:
|
||||
for _, hookConfig := range configs {
|
||||
switch hookConfig.Name {
|
||||
case hook.KeySessionIssuer:
|
||||
// The session issuer hook always needs to come last.
|
||||
addSessionIssuer = true
|
||||
case hook.KeySessionDestroyer:
|
||||
if h, ok := any(m.HookSessionDestroyer()).(T); ok {
|
||||
hooks = append(hooks, h)
|
||||
}
|
||||
case hook.KeyWebHook:
|
||||
cfg := request.Config{}
|
||||
if err := json.Unmarshal(hookConfig.Config, &cfg); err != nil {
|
||||
m.l.WithError(err).WithField("raw_config", string(hookConfig.Config)).Error("failed to unmarshal hook configuration, ignoring hook")
|
||||
return nil, errors.WithStack(fmt.Errorf("failed to unmarshal webhook configuration for %s: %w", credentialsType, err))
|
||||
}
|
||||
if h, ok := any(hook.NewWebHook(m, &cfg)).(T); ok {
|
||||
hooks = append(hooks, h)
|
||||
}
|
||||
case hook.KeyRequireVerifiedAddress:
|
||||
if h, ok := any(m.HookAddressVerifier()).(T); ok {
|
||||
hooks = append(hooks, h)
|
||||
}
|
||||
case hook.KeyVerificationUI:
|
||||
if h, ok := any(m.HookShowVerificationUI()).(T); ok {
|
||||
hooks = append(hooks, h)
|
||||
}
|
||||
case hook.KeyVerifier:
|
||||
if h, ok := any(m.HookVerifier()).(T); ok {
|
||||
hooks = append(hooks, h)
|
||||
}
|
||||
case hook.KeyVerifyNewAddress:
|
||||
if h, ok := any(m.HookVerifyNewAddress()).(T); ok {
|
||||
hooks = append(hooks, h)
|
||||
}
|
||||
case hook.KeyNotifyPreviousAddresses:
|
||||
cfg := &hook.NotifyPreviousAddressesConfig{}
|
||||
if len(hookConfig.Config) > 0 {
|
||||
if err := json.Unmarshal(hookConfig.Config, cfg); err != nil {
|
||||
m.l.WithError(err).WithField("raw_config", string(hookConfig.Config)).Error("failed to unmarshal hook configuration, ignoring hook")
|
||||
return nil, errors.WithStack(fmt.Errorf("failed to unmarshal notify_previous_addresses configuration for %s: %w", credentialsType, err))
|
||||
}
|
||||
}
|
||||
if h, ok := any(m.HookNotifyPreviousAddresses(cfg)).(T); ok {
|
||||
hooks = append(hooks, h)
|
||||
}
|
||||
default:
|
||||
for name, newHook := range m.injectedSelfserviceHooks {
|
||||
if name == hookConfig.Name {
|
||||
if h, ok := newHook(hookConfig, m).(T); ok {
|
||||
hooks = append(hooks, h)
|
||||
}
|
||||
continue allHooksLoop
|
||||
}
|
||||
}
|
||||
m.l.
|
||||
WithField("for", credentialsType).
|
||||
WithField("hook", hookConfig.Name).
|
||||
Warn("A configuration for a non-existing hook was found and will be ignored.")
|
||||
}
|
||||
}
|
||||
if addSessionIssuer {
|
||||
if h, ok := any(m.HookSessionIssuer()).(T); ok {
|
||||
hooks = append(hooks, h)
|
||||
}
|
||||
}
|
||||
|
||||
return hooks, nil
|
||||
}
|
||||
53
driver/registry_default_login.go
Normal file
53
driver/registry_default_login.go
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ory/kratos/driver/config"
|
||||
"github.com/ory/kratos/identity"
|
||||
"github.com/ory/kratos/selfservice/flow/login"
|
||||
)
|
||||
|
||||
func (m *RegistryDefault) LoginHookExecutor() *login.HookExecutor {
|
||||
if m.selfserviceLoginExecutor == nil {
|
||||
m.selfserviceLoginExecutor = login.NewHookExecutor(m)
|
||||
}
|
||||
return m.selfserviceLoginExecutor
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) PreLoginHooks(ctx context.Context) ([]login.PreHookExecutor, error) {
|
||||
return getHooks[login.PreHookExecutor](m, "", m.Config().SelfServiceFlowLoginBeforeHooks(ctx))
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) PostLoginHooks(ctx context.Context, credentialsType identity.CredentialsType) ([]login.PostHookExecutor, error) {
|
||||
hooks, err := getHooks[login.PostHookExecutor](m, string(credentialsType), m.Config().SelfServiceFlowLoginAfterHooks(ctx, string(credentialsType)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(hooks) > 0 {
|
||||
return hooks, nil
|
||||
}
|
||||
|
||||
// since we don't want merging hooks defined in a specific strategy and global hooks
|
||||
// global hooks are added only if no strategy specific hooks are defined
|
||||
return getHooks[login.PostHookExecutor](m, config.HookGlobal, m.Config().SelfServiceFlowLoginAfterHooks(ctx, config.HookGlobal))
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) LoginHandler() *login.Handler {
|
||||
if m.selfserviceLoginHandler == nil {
|
||||
m.selfserviceLoginHandler = login.NewHandler(m)
|
||||
}
|
||||
|
||||
return m.selfserviceLoginHandler
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) LoginFlowErrorHandler() *login.ErrorHandler {
|
||||
if m.selfserviceLoginRequestErrorHandler == nil {
|
||||
m.selfserviceLoginRequestErrorHandler = login.NewFlowErrorHandler(m)
|
||||
}
|
||||
|
||||
return m.selfserviceLoginRequestErrorHandler
|
||||
}
|
||||
87
driver/registry_default_recovery.go
Normal file
87
driver/registry_default_recovery.go
Normal file
@@ -0,0 +1,87 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/ory/herodot"
|
||||
"github.com/ory/kratos/driver/config"
|
||||
"github.com/ory/kratos/selfservice/flow/recovery"
|
||||
"github.com/ory/kratos/selfservice/strategy/code"
|
||||
)
|
||||
|
||||
func (m *RegistryDefault) RecoveryFlowErrorHandler() *recovery.ErrorHandler {
|
||||
if m.selfserviceRecoveryErrorHandler == nil {
|
||||
m.selfserviceRecoveryErrorHandler = recovery.NewErrorHandler(m)
|
||||
}
|
||||
|
||||
return m.selfserviceRecoveryErrorHandler
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) RecoveryHandler() *recovery.Handler {
|
||||
if m.selfserviceRecoveryHandler == nil {
|
||||
m.selfserviceRecoveryHandler = recovery.NewHandler(m)
|
||||
}
|
||||
|
||||
return m.selfserviceRecoveryHandler
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) RecoveryStrategies(ctx context.Context) (recoveryStrategies recovery.Strategies) {
|
||||
for _, strategy := range m.selfServiceStrategies() {
|
||||
if s, ok := strategy.(recovery.Strategy); ok {
|
||||
if m.Config().SelfServiceStrategy(ctx, s.RecoveryStrategyID()).Enabled {
|
||||
recoveryStrategies = append(recoveryStrategies, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetActiveRecoveryStrategies returns the currently active recovery strategies.
|
||||
// It returns a list of all strategies and the specific primary strategy.
|
||||
// If no primary recovery strategy has been set, an error is returned.
|
||||
func (m *RegistryDefault) GetActiveRecoveryStrategies(ctx context.Context) (active recovery.Strategies, primary recovery.Strategy, err error) {
|
||||
as := m.Config().SelfServiceFlowRecoveryUse(ctx)
|
||||
s, ps, err := m.RecoveryStrategies(ctx).ActiveStrategies(as)
|
||||
if err != nil {
|
||||
return nil, ps, errors.WithStack(herodot.ErrBadRequest().
|
||||
WithReasonf("You attempted recovery using %s, which is not enabled or does not exist. An administrator needs to enable this recovery method.", as))
|
||||
}
|
||||
return s, ps, nil
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) AllRecoveryStrategies() (recoveryStrategies recovery.Strategies) {
|
||||
for _, strategy := range m.selfServiceStrategies() {
|
||||
if s, ok := strategy.(recovery.Strategy); ok {
|
||||
recoveryStrategies = append(recoveryStrategies, s)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) RecoveryExecutor() *recovery.HookExecutor {
|
||||
if m.selfserviceRecoveryExecutor == nil {
|
||||
m.selfserviceRecoveryExecutor = recovery.NewHookExecutor(m)
|
||||
}
|
||||
return m.selfserviceRecoveryExecutor
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) PreRecoveryHooks(ctx context.Context) ([]recovery.PreHookExecutor, error) {
|
||||
return getHooks[recovery.PreHookExecutor](m, "", m.Config().SelfServiceFlowRecoveryBeforeHooks(ctx))
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) PostRecoveryHooks(ctx context.Context) ([]recovery.PostHookExecutor, error) {
|
||||
return getHooks[recovery.PostHookExecutor](m, config.HookGlobal, m.Config().SelfServiceFlowRecoveryAfterHooks(ctx, config.HookGlobal))
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) CodeSender() *code.Sender {
|
||||
if m.selfserviceCodeSender == nil {
|
||||
m.selfserviceCodeSender = code.NewSender(m)
|
||||
}
|
||||
|
||||
return m.selfserviceCodeSender
|
||||
}
|
||||
85
driver/registry_default_registration.go
Normal file
85
driver/registry_default_registration.go
Normal file
@@ -0,0 +1,85 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
|
||||
"github.com/ory/kratos/driver/config"
|
||||
"github.com/ory/kratos/identity"
|
||||
"github.com/ory/kratos/selfservice/flow/registration"
|
||||
)
|
||||
|
||||
func (m *RegistryDefault) PostRegistrationPrePersistHooks(ctx context.Context, credentialsType identity.CredentialsType) ([]registration.PostHookPrePersistExecutor, error) {
|
||||
hooks, err := getHooks[registration.PostHookPrePersistExecutor](m, string(credentialsType), m.Config().SelfServiceFlowRegistrationAfterHooks(ctx, string(credentialsType)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return hooks, nil
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) PostRegistrationPostPersistHooks(ctx context.Context, credentialsType identity.CredentialsType) ([]registration.PostHookPostPersistExecutor, error) {
|
||||
hooks, err := getHooks[registration.PostHookPostPersistExecutor](m, string(credentialsType), m.Config().SelfServiceFlowRegistrationAfterHooks(ctx, string(credentialsType)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(hooks) == 0 {
|
||||
// since we don't want merging hooks defined in a specific strategy and
|
||||
// global hooks are added only if no strategy specific hooks are defined
|
||||
hooks, err = getHooks[registration.PostHookPostPersistExecutor](m, config.HookGlobal, m.Config().SelfServiceFlowRegistrationAfterHooks(ctx, config.HookGlobal))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// WARNING - If you remove this, no verification emails / sms will be sent post-registration.
|
||||
if m.Config().SelfServiceFlowVerificationEnabled(ctx) {
|
||||
hooks = slices.Insert(hooks, 0, registration.PostHookPostPersistExecutor(m.HookVerifier()))
|
||||
}
|
||||
|
||||
return hooks, nil
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) PreRegistrationHooks(ctx context.Context) ([]registration.PreHookExecutor, error) {
|
||||
return getHooks[registration.PreHookExecutor](m, "", m.Config().SelfServiceFlowRegistrationBeforeHooks(ctx))
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) RegistrationExecutor() *registration.HookExecutor {
|
||||
if m.selfserviceRegistrationExecutor == nil {
|
||||
m.selfserviceRegistrationExecutor = registration.NewHookExecutor(m)
|
||||
}
|
||||
return m.selfserviceRegistrationExecutor
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) RegistrationHookExecutor() *registration.HookExecutor {
|
||||
if m.selfserviceRegistrationExecutor == nil {
|
||||
m.selfserviceRegistrationExecutor = registration.NewHookExecutor(m)
|
||||
}
|
||||
return m.selfserviceRegistrationExecutor
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) RegistrationErrorHandler() *registration.ErrorHandler {
|
||||
if m.seflserviceRegistrationErrorHandler == nil {
|
||||
m.seflserviceRegistrationErrorHandler = registration.NewErrorHandler(m)
|
||||
}
|
||||
return m.seflserviceRegistrationErrorHandler
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) RegistrationHandler() *registration.Handler {
|
||||
if m.selfserviceRegistrationHandler == nil {
|
||||
m.selfserviceRegistrationHandler = registration.NewHandler(m)
|
||||
}
|
||||
|
||||
return m.selfserviceRegistrationHandler
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) RegistrationFlowErrorHandler() *registration.ErrorHandler {
|
||||
if m.selfserviceRegistrationRequestErrorHandler == nil {
|
||||
m.selfserviceRegistrationRequestErrorHandler = registration.NewErrorHandler(m)
|
||||
}
|
||||
|
||||
return m.selfserviceRegistrationRequestErrorHandler
|
||||
}
|
||||
17
driver/registry_default_schemas.go
Normal file
17
driver/registry_default_schemas.go
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ory/kratos/schema"
|
||||
)
|
||||
|
||||
// IdentityTraitsSchemas returns the identity traits schemas. The provider is
|
||||
// eagerly initialized in initCheapMembers (or replaced in Init), so this getter
|
||||
// only reads the field and never lazily initializes it.
|
||||
func (m *RegistryDefault) IdentityTraitsSchemas(ctx context.Context) (schema.IdentitySchemaList, error) {
|
||||
return m.identitySchemaProvider.IdentityTraitsSchemas(ctx)
|
||||
}
|
||||
45
driver/registry_default_schemas_test.go
Normal file
45
driver/registry_default_schemas_test.go
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package driver_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/ory/kratos/driver/config"
|
||||
"github.com/ory/kratos/pkg"
|
||||
"github.com/ory/kratos/schema"
|
||||
"github.com/ory/x/urlx"
|
||||
)
|
||||
|
||||
func TestRegistryDefault_IdentityTraitsSchemas(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
conf, reg := pkg.NewFastRegistryWithMocks(t)
|
||||
defaultSchema := schema.Schema{
|
||||
ID: "default",
|
||||
URL: urlx.ParseOrPanic("file://default.schema.json"),
|
||||
RawURL: "file://default.schema.json",
|
||||
}
|
||||
altSchema := schema.Schema{
|
||||
ID: "alt",
|
||||
URL: urlx.ParseOrPanic("file://other.schema.json"),
|
||||
RawURL: "file://other.schema.json",
|
||||
}
|
||||
|
||||
conf.MustSet(ctx, config.ViperKeyIdentitySchemas, []config.Schema{
|
||||
{ID: altSchema.ID, URL: altSchema.RawURL},
|
||||
{ID: defaultSchema.ID, URL: defaultSchema.RawURL},
|
||||
})
|
||||
|
||||
ss, err := reg.IdentityTraitsSchemas(context.Background())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 2, ss.Total())
|
||||
assert.Contains(t, ss, defaultSchema)
|
||||
assert.Contains(t, ss, altSchema)
|
||||
}
|
||||
10
driver/registry_default_sessiontokenexchange.go
Normal file
10
driver/registry_default_sessiontokenexchange.go
Normal file
@@ -0,0 +1,10 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package driver
|
||||
|
||||
import "github.com/ory/kratos/selfservice/sessiontokenexchange"
|
||||
|
||||
func (m *RegistryDefault) SessionTokenExchangePersister() sessiontokenexchange.Persister {
|
||||
return m.Persister()
|
||||
}
|
||||
91
driver/registry_default_settings.go
Normal file
91
driver/registry_default_settings.go
Normal file
@@ -0,0 +1,91 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
|
||||
"github.com/ory/kratos/driver/config"
|
||||
"github.com/ory/kratos/selfservice/flow/settings"
|
||||
)
|
||||
|
||||
func (m *RegistryDefault) PostSettingsPrePersistHooks(ctx context.Context, settingsType string) ([]settings.PostHookPrePersistExecutor, error) {
|
||||
return getHooks[settings.PostHookPrePersistExecutor](m, settingsType, m.Config().SelfServiceFlowSettingsAfterHooks(ctx, settingsType))
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) PreSettingsHooks(ctx context.Context) ([]settings.PreHookExecutor, error) {
|
||||
return getHooks[settings.PreHookExecutor](m, "", m.Config().SelfServiceFlowSettingsBeforeHooks(ctx))
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) PostSettingsPostPersistHooks(ctx context.Context, settingsType string) ([]settings.PostHookPostPersistExecutor, error) {
|
||||
hooks, err := getHooks[settings.PostHookPostPersistExecutor](m, settingsType, m.Config().SelfServiceFlowSettingsAfterHooks(ctx, settingsType))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(hooks) == 0 {
|
||||
// since we don't want merging hooks defined in a specific strategy and
|
||||
// global hooks are added only if no strategy specific hooks are defined
|
||||
hooks, err = getHooks[settings.PostHookPostPersistExecutor](m, config.HookGlobal, m.Config().SelfServiceFlowSettingsAfterHooks(ctx, config.HookGlobal))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if m.Config().SelfServiceFlowVerificationEnabled(ctx) {
|
||||
hooks = slices.Insert(hooks, 0, settings.PostHookPostPersistExecutor(m.HookVerifier()))
|
||||
}
|
||||
|
||||
return hooks, nil
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) SettingsHookExecutor() *settings.HookExecutor {
|
||||
if m.selfserviceSettingsExecutor == nil {
|
||||
m.selfserviceSettingsExecutor = settings.NewHookExecutor(m)
|
||||
}
|
||||
return m.selfserviceSettingsExecutor
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) SettingsHandler() *settings.Handler {
|
||||
if m.selfserviceSettingsHandler == nil {
|
||||
m.selfserviceSettingsHandler = settings.NewHandler(m)
|
||||
}
|
||||
return m.selfserviceSettingsHandler
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) SettingsFlowErrorHandler() *settings.ErrorHandler {
|
||||
if m.selfserviceSettingsErrorHandler == nil {
|
||||
m.selfserviceSettingsErrorHandler = settings.NewErrorHandler(m)
|
||||
}
|
||||
return m.selfserviceSettingsErrorHandler
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) SettingsStrategies(ctx context.Context, filters ...settings.StrategyFilter) (profileStrategies settings.Strategies) {
|
||||
nextStrategy:
|
||||
for _, strategy := range m.selfServiceStrategies() {
|
||||
s, ok := strategy.(settings.Strategy)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for _, filter := range filters {
|
||||
if !filter(s) {
|
||||
continue nextStrategy
|
||||
}
|
||||
}
|
||||
if m.Config().SelfServiceStrategy(ctx, s.SettingsStrategyID()).Enabled || supportsOrganizations(strategy) {
|
||||
profileStrategies = append(profileStrategies, s)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) AllSettingsStrategies() settings.Strategies {
|
||||
var profileStrategies []settings.Strategy
|
||||
for _, strategy := range m.selfServiceStrategies() {
|
||||
if s, ok := strategy.(settings.Strategy); ok {
|
||||
profileStrategies = append(profileStrategies, s)
|
||||
}
|
||||
}
|
||||
return profileStrategies
|
||||
}
|
||||
1101
driver/registry_default_test.go
Normal file
1101
driver/registry_default_test.go
Normal file
File diff suppressed because it is too large
Load Diff
101
driver/registry_default_verification.go
Normal file
101
driver/registry_default_verification.go
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/ory/herodot"
|
||||
"github.com/ory/kratos/driver/config"
|
||||
"github.com/ory/kratos/identity"
|
||||
"github.com/ory/kratos/selfservice/flow/verification"
|
||||
"github.com/ory/kratos/selfservice/strategy/link"
|
||||
)
|
||||
|
||||
func (m *RegistryDefault) VerificationFlowPersister() verification.FlowPersister {
|
||||
return m.persister
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) VerificationFlowErrorHandler() *verification.ErrorHandler {
|
||||
if m.selfserviceVerifyErrorHandler == nil {
|
||||
m.selfserviceVerifyErrorHandler = verification.NewErrorHandler(m)
|
||||
}
|
||||
|
||||
return m.selfserviceVerifyErrorHandler
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) VerificationManager() *identity.Manager {
|
||||
if m.selfserviceVerifyManager == nil {
|
||||
m.selfserviceVerifyManager = identity.NewManager(m)
|
||||
}
|
||||
|
||||
return m.selfserviceVerifyManager
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) VerificationHandler() *verification.Handler {
|
||||
if m.selfserviceVerifyHandler == nil {
|
||||
m.selfserviceVerifyHandler = verification.NewHandler(m)
|
||||
}
|
||||
|
||||
return m.selfserviceVerifyHandler
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) LinkSender() *link.Sender {
|
||||
if m.selfserviceLinkSender == nil {
|
||||
m.selfserviceLinkSender = link.NewSender(m)
|
||||
}
|
||||
|
||||
return m.selfserviceLinkSender
|
||||
}
|
||||
|
||||
// GetActiveVerificationStrategies returns the currently active verification strategies.
|
||||
// It returns a list of all strategies and the specific primary strategy.
|
||||
// If no primary verification strategy has been set, an error is returned.
|
||||
func (m *RegistryDefault) GetActiveVerificationStrategies(ctx context.Context) (active verification.Strategies, primary verification.PrimaryStrategy, err error) {
|
||||
as := m.Config().SelfServiceFlowVerificationUse(ctx)
|
||||
s, ps, err := m.VerificationStrategies(ctx).ActiveStrategies(as)
|
||||
if err != nil {
|
||||
return nil, ps, errors.WithStack(herodot.ErrBadRequest().
|
||||
WithReasonf("The active verification strategy %s is not enabled. Please enable it in the configuration.", as))
|
||||
}
|
||||
return s, ps, nil
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) VerificationStrategies(ctx context.Context) (verificationStrategies verification.Strategies) {
|
||||
for _, strategy := range m.selfServiceStrategies() {
|
||||
if s, ok := strategy.(verification.Strategy); ok {
|
||||
if m.Config().SelfServiceStrategy(ctx, s.VerificationStrategyID()).Enabled {
|
||||
verificationStrategies = append(verificationStrategies, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) AllVerificationStrategies() (verificationStrategies verification.Strategies) {
|
||||
for _, strategy := range m.selfServiceStrategies() {
|
||||
if s, ok := strategy.(verification.Strategy); ok {
|
||||
verificationStrategies = append(verificationStrategies, s)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) VerificationExecutor() *verification.HookExecutor {
|
||||
if m.selfserviceVerificationExecutor == nil {
|
||||
m.selfserviceVerificationExecutor = verification.NewHookExecutor(m)
|
||||
}
|
||||
return m.selfserviceVerificationExecutor
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) PreVerificationHooks(ctx context.Context) ([]verification.PreHookExecutor, error) {
|
||||
return getHooks[verification.PreHookExecutor](m, "", m.Config().SelfServiceFlowVerificationBeforeHooks(ctx))
|
||||
}
|
||||
|
||||
func (m *RegistryDefault) PostVerificationHooks(ctx context.Context) ([]verification.PostHookExecutor, error) {
|
||||
return getHooks[verification.PostHookExecutor](m, config.HookGlobal, m.Config().SelfServiceFlowVerificationAfterHooks(ctx, config.HookGlobal))
|
||||
}
|
||||
Reference in New Issue
Block a user