boundless-ambulance-56979
07/29/2025, 9:21 PMdsn: <cockroach://root@cockroach:26257/kratos_db?sslmode=disable>
serve:
public:
base_url: <http://127.0.0.1:4433/>
cors:
enabled: true
allowed_origins:
- <http://localhost:5173>
- <http://localhost:5174>
- <http://localhost:3000>
- <http://localhost:4455>
allowed_methods:
- POST
- GET
- PUT
- PATCH
- DELETE
- OPTIONS
allowed_headers:
- Authorization
- Content-Type
- Cookie
exposed_headers:
- Content-Type
- Set-Cookie
allow_credentials: true
admin:
base_url: <http://127.0.0.1:4434/>
selfservice:
default_browser_return_url: <http://localhost:5173/enrollment>
flows:
login:
ui_url: <http://localhost:5173/login>
registration:
ui_url: <http://localhost:5173/registration>
enabled: true
after:
default_browser_return_url: <http://localhost:5173/enrollment>
password:
hooks:
- hook: show_verification_ui
- hook: show_recovery_ui
settings:
ui_url: <http://127.0.0.1:4455/settings>
recovery:
ui_url: <http://127.0.0.1:4455/recovery>
verification:
ui_url: <http://127.0.0.1:4455/verification>
methods:
password:
enabled: true
identity:
default_schema_id: default
schemas:
- id: default
url: file:///etc/config/kratos/identity-schemas/tpp.schema.json
courier:
templates:
verification:
valid:
email:
body:
html: file:///etc/config/kratos/email-templates/verification/body.html.gotmpl
plaintext: file:///etc/config/kratos/email-templates/verification/body.plaintext.gotmpl
subject: file:///etc/config/kratos/email-templates/verification/subject.gotmpl
delivery_strategy: smtp
smtp:
connection_uri: <smtps://sandbox-3>:***@smtp.devmail.email:2525/
from_address: <mailto:noreply@fapi-gateway.com|noreply@fapi-gateway.com>
from_name: FAPI Gateway
boundless-ambulance-56979
07/29/2025, 9:21 PMbrief-egg-61061
07/29/2025, 9:21 PMbrief-egg-61061
07/29/2025, 9:21 PMboundless-ambulance-56979
07/29/2025, 9:21 PMdsn: <cockroach://root@cockroach:26257/kratos_db?sslmode=disable>
serve:
public:
base_url: <http://127.0.0.1:4433/>
cors:
enabled: true
allowed_origins:
- <http://localhost:5173>
- <http://localhost:5174>
- <http://localhost:3000>
- <http://localhost:4455>
allowed_methods:
- POST
- GET
- PUT
- PATCH
- DELETE
- OPTIONS
allowed_headers:
- Authorization
- Content-Type
- Cookie
exposed_headers:
- Content-Type
- Set-Cookie
allow_credentials: true
admin:
base_url: <http://127.0.0.1:4434/>
selfservice:
default_browser_return_url: <http://localhost:5173/enrollment>
flows:
login:
ui_url: <http://localhost:5173/login>
registration:
ui_url: <http://localhost:5173/registration>
enabled: true
after:
default_browser_return_url: <http://localhost:5173/enrollment>
password:
hooks:
- hook: show_verification_ui
- hook: show_recovery_ui
settings:
ui_url: <http://127.0.0.1:4455/settings>
recovery:
ui_url: <http://127.0.0.1:4455/recovery>
verification:
ui_url: <http://127.0.0.1:4455/verification>
methods:
password:
enabled: true
identity:
default_schema_id: default
schemas:
- id: default
url: file:///etc/config/kratos/identity-schemas/tpp.schema.json
courier:
templates:
verification:
valid:
email:
body:
html: file:///etc/config/kratos/email-templates/verification/body.html.gotmpl
plaintext: file:///etc/config/kratos/email-templates/verification/body.plaintext.gotmpl
subject: file:///etc/config/kratos/email-templates/verification/subject.gotmpl
delivery_strategy: smtp
smtp:
connection_uri: <smtps://sandbox-3>:***@smtp.devmail.email:2525/
from_address: <mailto:noreply@fapi-gateway.com|noreply@fapi-gateway.com>
from_name: FAPI Gateway
brief-egg-61061
07/29/2025, 9:21 PMbrief-egg-61061
07/29/2025, 9:22 PMselfservice.flows.verification
section. In your config, you have: yaml selfservice: flows: verification: ui_url: <http://127.0.0.1:4455/verification>
However, you are missing the enabled: true
and the use: code
(or link
) fields. According to the documentation, it should look like: yaml selfservice: flows: verification: enabled: true use: code # or 'link' ui_url: <http://127.0.0.1:4455/verification>
[Address verification](https://www.ory.sh/docs/kratos/self-service/flows/verify-email-account-activation) ### 2. Identity Schema Must Mark Email as Verifiable Your identity schema (referenced as tpp.schema.json
) must mark the email trait as verifiable. For example: json "email": { "type": "string", "format": "email", "<http://ory.sh/kratos|ory.sh/kratos>": { "credentials": { "password": { "identifier": true } }, "verification": { "via": "email" } } }
[Address verification](https://www.ory.sh/docs/kratos/self-service/flows/verify-email-account-activation) ### 3. Registration Flow and Hooks You have the show_verification_ui
hook enabled after password registration, which is correct if you want to show the verification screen after registration. This is optional for sending the email, but required if you want to force users to verify before getting a session. By default, Ory will send the verification email if verification is enabled and the schema is correct, even without this hook. [Verification on sign up](https://www.ory.sh/docs/actions/require-verified-address#verification-on-sign-up) ### 4. Courier Configuration Your courier configuration looks correct, assuming your SMTP credentials and template paths are valid. ### 5. Common Pitfalls - If you do not see emails being sent, check the Kratos logs for errors related to the courier or SMTP delivery. - Make sure your SMTP server is reachable and credentials are correct. - Ensure your identity schema is loaded correctly and the verification
property is present for the email trait. --- Summary of what you are missing: You need to add enabled: true
and use: code
(or link
) to your selfservice.flows.verification
section. Also, double-check your identity schema to ensure the email trait is marked as verifiable. If you make these changes and still do not receive verification emails, check the logs for courier or SMTP errors, and verify that your SMTP configuration is correct. For more details, see the [Ory Kratos Address Verification documentation](https://www.ory.sh/docs/kratos/self-service/flows/verify-email-account-activation).boundless-ambulance-56979
07/30/2025, 6:13 PMbrief-egg-61061
07/30/2025, 6:13 PMbrief-egg-61061
07/30/2025, 6:13 PMcourier
section. This config can be used in your YAML configuration file: yaml courier: delivery_strategy: http http: request_config: url: <https://mail-sender.example.com> method: POST body: base64://... # Base64-encoded Jsonnet template for the payload (see below) headers: Content-Type: application/json auth: type: basic_auth # or api_key config: user: my-username password: my-password # For api_key, use: # name: my-api-name # value: my-api-key-value # in: header # or cookie
Notes: - The body
field should contain a Base64-encoded Jsonnet template that defines the payload sent to your HTTP email provider. If omitted, a default template is used. - The auth
section is optional and depends on your provider's requirements. Default Jsonnet template for the payload: jsonnet function(ctx) { recipient: ctx.recipient, template_type: ctx.template_type, to: if "template_data" in ctx && "to" in ctx.template_data then <http://ctx.template_data.to|ctx.template_data.to> else null, recovery_code: if "template_data" in ctx && "recovery_code" in ctx.template_data then ctx.template_data.recovery_code else null, recovery_url: if "template_data" in ctx && "recovery_url" in ctx.template_data then ctx.template_data.recovery_url else null, verification_url: if "template_data" in ctx && "verification_url" in ctx.template_data then ctx.template_data.verification_url else null, verification_code: if "template_data" in ctx && "verification_code" in ctx.template_data then ctx.template_data.verification_code else null, login_code: if "template_data" in ctx && "login_code" in ctx.template_data then ctx.template_data.login_code else null, registration_code: if "template_data" in ctx && "registration_code" in ctx.template_data then ctx.template_data.registration_code else null, subject: if "template_data" in ctx && "subject" in ctx.template_data then ctx.template_data.subject else null, body: if "template_data" in ctx && "body" in ctx.template_data then ctx.template_data.body else null }
You can use this template as-is or customize it for your provider, then Base64-encode it and reference it in the body
field. For more details and examples, see the official documentation: [Send emails using an HTTP server](https://www.ory.sh/docs/kratos/emails-sms/sending-emails-smtp#send-emails-using-an-http-server) and [HTTP based email delivery (self-hosted)](https://www.ory.sh/docs/kratos/self-hosted/email-http#configuration).boundless-ambulance-56979
07/30/2025, 6:15 PMbrief-egg-61061
07/30/2025, 6:15 PMbrief-egg-61061
07/30/2025, 6:15 PMyaml courier: delivery_strategy: http http: request_config: url: <https://api.your-email-provider.com/send> method: POST body: file:///etc/config/kratos/mail.api.request.jsonnet # or use <base64://ENCODED_JSONNET> headers: "Content-Type": "application/json" auth: type: api_key config: name: Authorization # The header or cookie name for the API key value: Bearer <API_KEY> # The value of your API key (prefix with 'Bearer ' if required by your provider) in: header # Use 'header' or 'cookie' as required by your provider
Key points: - Replace url
with your provider’s endpoint. - The body
can be a file path or a base64-encoded Jsonnet template. If omitted, the default template is used. - Set the name
, value
, and in
fields in the auth.config
section according to your provider’s requirements. For example, for Sendgrid, you would use: yaml auth: type: api_key config: name: Authorization value: Bearer <API_KEY> in: header
This configuration is directly supported and documented in the Ory Kratos docs for HTTP-based email delivery with API key authentication [HTTP based email delivery](https://www.ory.sh/docs/kratos/self-hosted/email-http#configuration) and [Send emails using an HTTP server](https://www.ory.sh/docs/kratos/emails-sms/sending-emails-smtp#send-emails-using-an-http-server). If you need a sample Jsonnet template for the body, let me know!boundless-ambulance-56979
07/30/2025, 6:30 PMbrief-egg-61061
07/30/2025, 6:30 PMbrief-egg-61061
07/30/2025, 6:30 PMbody
parameter in your HTTP email delivery configuration, you provide a Jsonnet template that defines the payload sent to your email provider. This template can be referenced as a file (e.g., `file://path/to/template.jsonnet`) or as a base64-encoded string (e.g., <base64://ENCODED_JSONNET>
). Ory Kratos will pass a ctx
object to your Jsonnet function, containing relevant data for the email. Example Jsonnet template (mail.api.request.jsonnet
): jsonnet function(ctx) { recipient: ctx.recipient, template_type: ctx.template_type, to: if "template_data" in ctx && "to" in ctx.template_data then <http://ctx.template_data.to|ctx.template_data.to> else null, recovery_code: if "template_data" in ctx && "recovery_code" in ctx.template_data then ctx.template_data.recovery_code else null, recovery_url: if "template_data" in ctx && "recovery_url" in ctx.template_data then ctx.template_data.recovery_url else null, verification_url: if "template_data" in ctx && "verification_url" in ctx.template_data then ctx.template_data.verification_url else null, verification_code: if "template_data" in ctx && "verification_code" in ctx.template_data then ctx.template_data.verification_code else null }
How to reference it in your config: yaml courier: delivery_strategy: http http: request_config: url: <https://api.your-email-provider.com/send> method: POST body: file:///etc/config/kratos/mail.api.request.jsonnet headers: "Content-Type": "application/json" auth: type: api_key config: name: Authorization value: Bearer <API_KEY> in: header
Alternatively, you can base64-encode your Jsonnet file and use: yaml body: base64://<BASE64_ENCODED_JSONNET>
What fields are available in ctx
? - `recipient`: The email address of the recipient. - `template_type`: The type of template (e.g., verification_valid
). - `template_data`: An object with template-specific data (e.g., verification_url
, recovery_code
, etc.). For more details and a list of available fields, see the [official documentation](https://www.ory.sh/docs/kratos/self-hosted/email-http#configuration) and [Jsonnet reference](https://www.ory.sh/docs/kratos/reference/jsonnet).boundless-ambulance-56979
07/31/2025, 12:45 PMbrief-egg-61061
07/31/2025, 12:45 PMbrief-egg-61061
07/31/2025, 12:45 PMyaml selfservice: methods: totp: config: # The "issuer" is the name shown in the TOTP app (e.g., Google Authenticator) issuer: <http://ExampleIssuer.com|ExampleIssuer.com> enabled: true
Key points: - The issuer
value will be displayed in the authenticator app. - Make sure enabled: true
is set. This configuration enables TOTP as a second-factor authentication method for your users. After enabling, users can pair their account with a TOTP app (like Google Authenticator) via the Ory Account Experience or your custom UI. For more details, see the official documentation: [Time-based one-time passwords (TOTP)](https://www.ory.sh/docs/kratos/mfa/totp) and [Self-hosted MFA configuration](https://www.ory.sh/docs/kratos/self-hosted/mfa).boundless-ambulance-56979
07/31/2025, 1:26 PMbrief-egg-61061
07/31/2025, 1:26 PMbrief-egg-61061
07/31/2025, 1:26 PMyaml selfservice: methods: totp: config: issuer: <http://ExampleIssuer.com|ExampleIssuer.com> enabled: true
This enables TOTP as a second factor and sets the issuer name that appears in authenticator apps [Time-based one-time passwords (TOTP)](https://www.ory.sh/docs/kratos/mfa/totp). ### 2. Enforce MFA after login To require users to complete TOTP after logging in, set the required Authenticator Assurance Level (AAL) for sessions and/or sensitive flows. For example, to require the highest available AAL (which includes TOTP if configured) for accessing account settings: yaml selfservice: flows: settings: required_aal: highest_available session: whoami: required_aal: highest_available
With this configuration, after a user logs in with their password, they will be prompted for TOTP if they have it configured. If not, they can proceed with just their password. If you want to require TOTP for all users who have it set up, this is the recommended approach [Configure multi-factor authentication in Ory Kratos](https://www.ory.sh/docs/kratos/self-hosted/mfa). ### 3. How it works in practice - User logs in with their first factor (e.g., password). - If the session or flow requires aal2
(second factor), and the user has TOTP configured, Ory will prompt for the TOTP code. - Upon successful TOTP entry, the session is upgraded to aal2
. For more on step-up authentication and enforcing TOTP after login, see [Step-up authentication](https://www.ory.sh/docs/kratos/mfa/step-up-authentication). --- Summary: Enable TOTP in selfservice.methods
, and set required_aal: highest_available
for the relevant flows or session. This will prompt users for TOTP after a successful login if they have TOTP configured.boundless-ambulance-56979
07/31/2025, 1:27 PMboundless-ambulance-56979
07/31/2025, 1:27 PMbrief-egg-61061
07/31/2025, 1:27 PMbrief-egg-61061
07/31/2025, 1:27 PMyaml selfservice: methods: totp: config: # This is the name that will appear in Google Authenticator issuer: <http://ExampleIssuer.com|ExampleIssuer.com> enabled: true flows: settings: required_aal: highest_available session: whoami: required_aal: highest_available
How it works: - After a user logs in with their password, if they have TOTP (e.g., Google Authenticator) configured, Ory will prompt them to enter the code from their app. - The issuer
field is what users will see in Google Authenticator when they pair their account. - The required_aal: highest_available
setting ensures that users must complete the second factor (TOTP) for sensitive actions or to upgrade their session to AAL2. This setup is directly supported and described in the Ory documentation for TOTP and step-up authentication [Time-based one-time passwords (TOTP)](https://www.ory.sh/docs/kratos/mfa/totp) [Step-up authentication](https://www.ory.sh/docs/kratos/mfa/step-up-authentication). If you want TOTP to be required immediately after login for all users who have it configured, this is the recommended approach. If a user does not have TOTP set up, they will not be prompted for it until they do so. If you need to customize which flows require TOTP, adjust the required_aal
setting under the relevant flow (e.g., login
, settings
, etc.) as shown above.boundless-ambulance-56979
07/31/2025, 6:39 PMbrief-egg-61061
07/31/2025, 6:39 PMbrief-egg-61061
07/31/2025, 6:39 PMdeleteIdentityCredentials
method, which requires authentication with an Ory access token. This operation is typically performed via the admin API and is not a self-service flow exposed to end users by default. Here’s what the knowledge sources state: > To perform this operation, you must be authenticated by means of one of the following methods: oryAccessToken [Kratos API Reference](https://raw.githubusercontent.com/ory/kratos/master/spec/api.json) The documentation does not provide a full example of the API call, but the process generally involves: - Authenticating as an admin or with appropriate permissions. - Calling the relevant admin API endpoint to delete the identity. If you need to delete an account via the Ory Console or CLI, you would typically use the admin interface or CLI commands to manage identities, but the knowledge sources do not provide explicit step-by-step instructions for this process. Summary: Account deletion is performed via the admin API using an authenticated request. The knowledge sources do not provide a detailed example, but you must use an Ory access token and the appropriate API endpoint to delete an identity.boundless-ambulance-56979
08/02/2025, 6:13 AMbrief-egg-61061
08/02/2025, 6:13 AMbrief-egg-61061
08/02/2025, 6:13 AMyaml selfservice: methods: totp: config: issuer: <http://ExampleIssuer.com|ExampleIssuer.com> # This is the name shown in Google Authenticator enabled: true
This enables TOTP (Google Authenticator) for your project and sets the issuer name that appears in the authenticator app [Time-based one-time passwords (TOTP)](https://www.ory.sh/docs/kratos/mfa/totp). 2. Enforce MFA after login: Set the required Authenticator Assurance Level (AAL) to require the highest available factor (which includes TOTP if configured): yaml session: whoami: required_aal: highest_available
With this configuration, after a user logs in with their password, Ory Kratos will check if the user has TOTP configured. If so, the user will be prompted for their TOTP code (e.g., from Google Authenticator) before the session is fully established at AAL2. If the user does not have TOTP set up, they will not be prompted for it. How it works: - User enters their username and password (normal login). - If TOTP is enabled and configured for the user, Ory will prompt for the TOTP code after the password is verified. - Upon successful TOTP entry, the user gains access with an AAL2 session. This approach is described in the official documentation for step-up authentication and TOTP configuration [Step-up authentication](https://www.ory.sh/docs/kratos/mfa/step-up-authentication) [Time-based one-time passwords (TOTP)](https://www.ory.sh/docs/kratos/mfa/totp). If you want to require TOTP only for specific flows (e.g., only for settings changes), adjust the required_aal
setting under the relevant flow (such as selfservice.flows.settings.required_aal
). Note: The knowledge sources do not mention a way to force TOTP for all users regardless of whether they have it configured, nor do they describe a way to force TOTP enrollment immediately after registration. Users must enable TOTP themselves in their account settings after registration [Time-based one-time passwords (TOTP)](https://www.ory.sh/docs/kratos/mfa/totp). --- Summary: Enable TOTP and set session.whoami.required_aal: highest_available
to prompt for a Google Authenticator challenge after normal login if the user has TOTP configured.boundless-ambulance-56979
08/02/2025, 6:34 AMbrief-egg-61061
08/02/2025, 6:34 AMbrief-egg-61061
08/02/2025, 6:34 AM