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 Gatewayboundless-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 Gatewaybrief-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 AMboundless-ambulance-56979
10/12/2025, 8:22 AM{
"error": {
"id": "security_csrf_violation",
"code": 403,
"status": "Forbidden",
"reason": "Please retry the flow and optionally clear your cookies. The request was rejected to protect you from Cross-Site-Request-Forgery (CSRF) which could cause account takeover, leaking personal information, and other serious security issues.",
"details": {
"docs": "<https://www.ory.sh/kratos/docs/debug/csrf>",
"hint": "The anti-CSRF cookie was found but the CSRF token was not included in the HTTP request body (csrf_token) nor in the HTTP Header (X-CSRF-Token).",
"reject_reason": "The HTTP Cookie Header was set and a CSRF token was sent but they do not match. We recommend deleting all cookies for this domain and retrying the flow."
},
"message": "the request was rejected to protect you from Cross-Site-Request-Forgery"
}
}
after redirecting to my app to check verification state and process with onboardingchilly-king-10285
10/12/2025, 8:22 AMchilly-king-10285
10/12/2025, 8:22 AM"error": { "id": "security_csrf_violation", ... "reason": "Please retry the flow and optionally clear your cookies. The request was rejected to protect you from Cross-Site-Request-Forgery (CSRF)...", "details": { ... "hint": "The anti-CSRF cookie was found but the CSRF token was not included in the HTTP request body (csrf_token) nor in the HTTP Header (X-CSRF-Token).", "reject_reason": "The HTTP Cookie Header was set and a CSRF token was sent but they do not match. We recommend deleting all cookies for this domain and retrying the flow." } } indicates a CSRF protection failure. This typically happens when the CSRF token in the request does not match the anti-CSRF cookie, or one of them is missing. Common causes and solutions based on the knowledge sources: 1. Cookies and CSRF Token Mismatch: This can occur if the verification link is opened in a different browser, incognito window, or if cookies were cleared or not sent with the request. Ory Kratos expects the CSRF cookie and the CSRF token (from the form or header) to match. If they do not, the request is rejected for security reasons [CSRF troubleshooting](https://www.ory.sh/docs/troubleshooting/csrf). 2. Public Suffix Domains: If you are using a domain that is on the [public suffix list](https://publicsuffix.org/), cookies may not be set correctly, leading to CSRF errors. Use a subdomain that is not on the PSL, such as <http://app.myftp.org|app.myftp.org> instead of <http://myftp.org|myftp.org> [CSRF troubleshooting](https://www.ory.sh/docs/troubleshooting/csrf). 3. Mixing Domains or Inconsistent URLs: Make sure you are not mixing localhost and 127.0.0.1, or using different subdomains, as cookies are domain-specific. Use the same domain consistently across your app and Ory Kratos [CSRF debug](https://www.ory.sh/docs/kratos/debug/csrf). 4. Flow Handling: When handling verification flows, ensure you are forwarding the Cookie header from the client when fetching the flow, especially in server-side applications. Without forwarding the Cookie header, you can't fetch the flow due to a security error [CSRF troubleshooting](https://www.ory.sh/docs/troubleshooting/csrf). 5. How to Fix: - Ask the user to retry the flow and clear cookies for the domain if necessary. - Ensure the verification link is opened in the same browser and context where the registration was performed. - Double-check your domain and cookie settings in the Kratos config. - If you are using a custom UI, make sure to include the CSRF token from the flow in your form submissions. For more details, see the [Ory Kratos CSRF troubleshooting guide](https://www.ory.sh/kratos/docs/debug/csrf). --- Summary: This error is caused by a mismatch or absence of the CSRF token and cookie. Ensure the verification link is opened in the same browser session, cookies are not blocked or cleared, and your domain configuration is correct. If the problem persists, clear cookies and retry the flow [CSRF troubleshooting](https://www.ory.sh/docs/troubleshooting/csrf).boundless-ambulance-56979
10/16/2025, 8:01 PMchilly-king-10285
10/16/2025, 8:01 PMchilly-king-10285
10/16/2025, 8:02 PMAccess-Control-Allow-Origin header for Ory Kratos, you need to configure the CORS settings in your Kratos configuration file under the serve.public.cors.allowed_origins section. This determines which origins are allowed to make cross-origin requests to your Kratos public API. Here is an example configuration: yaml serve: public: cors: enabled: true allowed_origins: - <https://example.org> - https://*.<http://example.org|example.org> allowed_methods: - POST - GET - PUT - PATCH - DELETE allowed_headers: - Authorization - Cookie - Content-Type exposed_headers: - Content-Type - Set-Cookie In this example, the allowed_origins list sets the values for the Access-Control-Allow-Origin header. You can specify exact origins or use wildcards for subdomains (e.g., https://*.<http://example.org|example.org>). For more details, see the official documentation: [Cross-origin resource sharing (CORS) settings](https://www.ory.com/docs/kratos/guides/setting-up-cors) and [Configure cross-origin resource sharing (CORS)](https://www.ory.com/docs/hydra/guides/cors).boundless-ambulance-56979
10/16/2025, 8:16 PMchilly-king-10285
10/16/2025, 8:16 PMchilly-king-10285
10/16/2025, 8:16 PM/self-service/logout/browser endpoint to generate a logout URL associated with the current session cookie. 2. Complete the Logout: Redirect the user to the generated logout URL (which points to /self-service/logout?token=...). This will invalidate the session and remove the session cookie. You can also specify a return_to parameter to redirect the user after logout. Example (Express.js): js // Create logout route app.get("/logout", async (req, res) => { try { // Create a logout flow const { logout_url } = await ory.createBrowserLogoutFlow({ cookie: req.header("cookie"), }) // Redirect to logout URL res.redirect(logout_url) } catch (err) { res.redirect("/") } }) After successful logout, the user is redirected to the specified return URL, the session is invalidated, and the session cookie is removed [Sign out](https://www.ory.com/docs/identities/get-started/sign-out) [Logout flow](https://www.ory.com/docs/kratos/bring-your-own-ui/custom-ui-basic-integration#logout-flow). --- ### 2. Native/API Logout Flow (Ory Kratos) For native or API clients (such as mobile apps), use the session token to log out: - Call the /self-service/logout/api endpoint with the session token in the request body. Example (TypeScript): ts await frontend.performNativeLogout({ performNativeLogoutBody: { session_token: token, }, }) This revokes the session token and logs out the user [Native API applications](https://www.ory.com/docs/kratos/self-service/flows/user-logout#native-api-applications). --- ### 3. OpenID Connect/OAuth2 Logout (Ory Hydra) For OIDC/OAuth2, Ory supports: - Front-Channel Logout: Redirects the browser to a registered frontchannel_logout_uri after logout. - Back-Channel Logout: Sends a POST request with a logout_token to a registered backchannel_logout_uri when the user logs out. To initiate logout, call the /oauth2/sessions/logout endpoint. You can use parameters like post_logout_redirect_uri, state, and id_token_hint to control the redirect and state after logout [OpenID Connect logout](https://www.ory.com/docs/oauth2-oidc/oidc-logout#redirect-after-logout). --- ### Summary Table | Application Type | Endpoint | Method | Notes | |------------------|------------------------------------------|----------|-----------------------------------------------------------------------| | Browser | /self-service/logout/browser | GET | Generates logout URL, then redirect user to it | | Browser | /self-service/logout | GET | Completes logout with token from previous step | | Native/API | /self-service/logout/api | DELETE | Send session token in body | | OIDC/OAuth2 | /oauth2/sessions/logout | GET | Initiates OIDC/OAuth2 logout, supports redirect and state parameters | --- For more details and code samples, see the [Ory Kratos Logout documentation](https://www.ory.com/docs/kratos/self-service/flows/user-logout) and [Ory OAuth2 & OpenID Connect logout documentation](https://www.ory.com/docs/oauth2-oidc/oidc-logout).boundless-ambulance-56979
10/18/2025, 2:53 PMchilly-king-10285
10/18/2025, 2:53 PMchilly-king-10285
10/18/2025, 2:53 PMafter verification flow in your Kratos configuration. This webhook will be called when a user successfully verifies their account. Example configuration: yaml selfservice: flows: verification: enabled: true use: code # or 'link' after: hooks: - hook: web_hook config: url: <https://your-backend.com/webhooks/verification-success> method: POST body: <base64://ENCODED_JSONNET> # Optional: customize the payload auth: type: api_key # Optional: if your backend requires authentication config: name: Authorization value: Bearer YOUR_API_KEY in: header ### 2. Customize the Webhook Payload (Optional) You can use a Jsonnet template to customize the data sent to your backend. For example: verification-webhook.jsonnet: jsonnet function(ctx) { user_id: ctx.identity.id, email: ctx.identity.verifiable_addresses[0].value, verified: ctx.identity.verifiable_addresses[0].verified, verification_status: ctx.identity.verifiable_addresses[0].status } Base64-encode this file and reference it in the body field: bash cat verification-webhook.jsonnet | base64 | pbcopy Then update your config: yaml body: <base64://ENCODED_JSONNET> ### 3. Handle the Webhook in Your Backend Your backend should listen for POST requests at the configured endpoint (e.g., /webhooks/verification-success) and process the verification event. The webhook payload will include the identity data, including the verified status. Example payload received by your backend: json { "user_id": "abc123", "email": "[email protected]", "verified": true, "verification_status": "completed" } ### 4. Apply the Configuration Update your Ory Identities configuration using the Ory CLI: bash ory update identity-config --project <project-id> --workspace <workspace-id> --file updated_config.yaml --- ### Alternative: Use Live Event Streams If you need real-time notifications for verification events, you can also use Ory Live Event Streams. The VerificationSucceeded event is emitted when a user successfully verifies their account [Event names](https://www.ory.com/docs/actions/live-events#event-names). --- ### Summary Configure a webhook in the after verification flow to notify your backend when a user verifies their account. Use Jsonnet to customize the payload if needed, and handle the webhook in your backend to process the verification event. For more details, see: - [Trigger custom logic with webhooks](https://www.ory.com/docs/guides/integrate-with-ory-cloud-through-webhooks) - [Configure hooks](https://www.ory.com/docs/kratos/hooks/configure-hooks) - [Live event streams](https://www.ory.com/docs/actions/live-events)boundless-ambulance-56979
10/18/2025, 11:15 PMchilly-king-10285
10/18/2025, 11:15 PMchilly-king-10285
10/18/2025, 11:15 PMafter configuration at the wrong level in your selfservice.flows section. Specifically, you have: yaml selfservice: flows: after: default_browser_return_url: <http://localhost:3000/main/overview/> This is not allowed. The after configuration should be nested inside specific flows (like registration, verification, etc.), not at the top level of selfservice.flows. ### How to Fix Remove the top-level after configuration and place it inside the appropriate flow. For example, if you want to set a default redirect after registration, it should be: yaml selfservice: flows: registration: after: default_browser_return_url: <http://localhost:3000/main/overview/> ### Corrected Configuration Structure Here's the corrected structure based on your config: yaml selfservice: flows: error: ui_url: <https://www.ory.sh/kratos/docs/fallback/error> login: lifespan: 1h ui_url: <http://localhost:3000/auth/login> recovery: enabled: false lifespan: 1h notify_unknown_recipients: false ui_url: <http://localhost:3000/auth/recovery> use: code registration: enabled: true lifespan: 1h login_hints: false ui_url: <http://localhost:3000/auth/register> after: default_browser_return_url: <http://localhost:3000/main/overview/> # Move here if needed code: hooks: - hook: session settings: lifespan: 1h privileged_session_max_age: 1h required_aal: highest_available ui_url: <http://localhost:3000/auth/settings> verification: enabled: true lifespan: 10m notify_unknown_recipients: false ui_url: <http://localhost:3000/account/verify> use: link after: default_browser_return_url: <http://localhost:3000/onboarding> hooks: - hook: web_hook config: url: <http://localhost:8080/api/v1/account/webhook/email-verification> method: POST body: file:///etc/config/kratos/hooks/verification.jsonnet ### Key Points - The after configuration must be inside a specific flow (e.g., registration, verification), not at the top level of selfservice.flows. - Each flow can have its own after section with hooks and redirect URLs. For more details on configuring hooks and flows, see the [Ory Kratos hooks documentation](https://www.ory.com/docs/kratos/hooks/configure-hooks).boundless-ambulance-56979
10/18/2025, 11:24 PMdsn: <cockroach://root@cockroach:26257/defaultdb?sslmode=disable>
serve:
public:
base_url: <http://localhost:4433/>
cors:
enabled: true
allowed_origins:
- <http://localhost:3000>
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://localhost:4434/>
selfservice:
default_browser_return_url: <http://localhost:3000/main/overview>
flows:
login:
ui_url: <http://localhost:3000/auth/login>
after:
default_browser_return_url: <http://localhost:3000/main/overview>
registration:
enabled: true
ui_url: <http://localhost:3000/auth/register>
after:
code:
hooks:
- hook: session
settings:
ui_url: <http://localhost:3000/auth/settings>
recovery:
ui_url: <http://localhost:3000/auth/recovery>
verification:
enabled: true
ui_url: <http://localhost:3000/account/verify>
lifespan: 10m
use: link
after:
default_browser_return_url: <http://localhost:3000/onboarding>
hooks:
- hook: web_hook
config:
url: <http://localhost:8080/api/v1/account/webhook/email-verification>
method: POST
body: file:///etc/config/kratos/hooks/verification.jsonnet
methods:
password:
enabled: true
link:
enabled: true
identity:
default_schema_id: default
schemas:
- id: default
url: file:///etc/config/kratos/identity-schemas/user.schema.json
courier:
delivery_strategy: smtp
smtp:
connection_uri: "<smtps://resend:re_3RVyNtRU_77gr1dB2kLghPow8WTrV6Los@smtp.resend.com:465>"
from_address: "onboarding@resend.dev"
template_override_path: /etc/config/kratos/email-templates
templates:
verification:
valid:
email:
body:
html: file:///etc/config/kratos/email-templates/verification/body.html.gotmplboundless-ambulance-56979
10/18/2025, 11:24 PMdsn: <cockroach://root@cockroach:26257/defaultdb?sslmode=disable>
serve:
public:
base_url: <http://localhost:4433/>
cors:
enabled: true
allowed_origins:
- <http://localhost:3000>
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://localhost:4434/>
selfservice:
default_browser_return_url: <http://localhost:3000/main/overview>
flows:
login:
ui_url: <http://localhost:3000/auth/login>
after:
default_browser_return_url: <http://localhost:3000/main/overview>
registration:
enabled: true
ui_url: <http://localhost:3000/auth/register>
after:
code:
hooks:
- hook: session
settings:
ui_url: <http://localhost:3000/auth/settings>
recovery:
ui_url: <http://localhost:3000/auth/recovery>
verification:
enabled: true
ui_url: <http://localhost:3000/account/verify>
lifespan: 10m
use: link
after:
default_browser_return_url: <http://localhost:3000/onboarding>
hooks:
- hook: web_hook
config:
url: <http://localhost:8080/api/v1/account/webhook/email-verification>
method: POST
body: file:///etc/config/kratos/hooks/verification.jsonnet
methods:
password:
enabled: true
link:
enabled: true
identity:
default_schema_id: default
schemas:
- id: default
url: file:///etc/config/kratos/identity-schemas/user.schema.json
courier:
delivery_strategy: smtp
smtp:
connection_uri: "<smtps://resend:re_3RVyNtRU_77gr1dB2kLghPow8WTrV6Los@smtp.resend.com:465>"
from_address: "onboarding@resend.dev"
template_override_path: /etc/config/kratos/email-templates
templates:
verification:
valid:
email:
body:
html: file:///etc/config/kratos/email-templates/verification/body.html.gotmplchilly-king-10285
10/18/2025, 11:24 PMchilly-king-10285
10/18/2025, 11:25 PMafter configuration at the wrong level in your selfservice.flows section. Looking at your config, you have: yaml selfservice: flows: login: ui_url: <http://localhost:3000/auth/login> after: default_browser_return_url: <http://localhost:3000/main/overview> This is not allowed. The after configuration cannot be a direct child of selfservice.flows. It must be nested inside specific flows (like login, registration, etc.). ### How to Fix Remove the standalone after block and place it inside the login flow (or whichever flow you want to configure). Here's the corrected configuration: yaml dsn: <cockroach://root@cockroach:26257/defaultdb?sslmode=disable> serve: public: base_url: <http://localhost:4433/> cors: enabled: true allowed_origins: - <http://localhost:3000> 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://localhost:4434/> selfservice: default_browser_return_url: <http://localhost:3000/main/overview> flows: login: ui_url: <http://localhost:3000/auth/login> after: default_browser_return_url: <http://localhost:3000/main/overview> registration: enabled: true ui_url: <http://localhost:3000/auth/register> after: code: hooks: - hook: session settings: ui_url: <http://localhost:3000/auth/settings> recovery: ui_url: <http://localhost:3000/auth/recovery> verification: enabled: true ui_url: <http://localhost:3000/account/verify> lifespan: 10m use: link after: default_browser_return_url: <http://localhost:3000/onboarding> hooks: - hook: web_hook config: url: <http://localhost:8080/api/v1/account/webhook/email-verification> method: POST body: file:///etc/config/kratos/hooks/verification.jsonnet methods: password: enabled: true link: enabled: true identity: default_schema_id: default schemas: - id: default url: file:///etc/config/kratos/identity-schemas/user.schema.json courier: delivery_strategy: smtp smtp: connection_uri: "<smtps://resend:re_3RVyNtRU_77gr1dB2kLghPow8WTrV6Los@smtp.resend.com:465>" from_address: "onboarding@resend.dev" template_override_path: /etc/config/kratos/email-templates templates: verification: valid: email: body: html: file:///etc/config/kratos/email-templates/verification/body.html.gotmpl ### Key Changes - Moved the after block from being a direct child of selfservice.flows to inside the login flow. - Each flow (login, registration, verification, etc.) can have its own after section with hooks and redirect URLs. This should resolve the validation error. For more details on configuring flows and redirects, see the [Ory Kratos browser redirect documentation](https://www.ory.com/docs/kratos/concepts/browser-redirect-flow-completion).