quick-addition-90714
04/26/2025, 10:17 AMbrief-egg-61061
04/26/2025, 10:17 AMbrief-egg-61061
04/26/2025, 10:17 AMstate: "active"
property in an identity object indicates that the identity (user account) is active and can be used. This is part of the identity's state property which can have two possible values: - `active`: The identity is active and can be used - `inactive`: The identity is inactive According to the API documentation, this value currently has no effect on the system's behavior, meaning it's primarily an informational field rather than one that controls functionality. When you see this in a session response or identity object, it's telling you that the user account associated with that session or identity is in an active state. For example, in session responses, you'll typically see something like: json { "identity": { "id": "c4d24c01-feba-4213-858b-262c8d427f8c", "state": "active", "state_changed_at": "2023-02-03T15:41:22.835918Z", // other identity properties... }, // other session properties... }
If an account is not active yet, users might see an error message with code 4000010: "Account not active yet. Did you forget to verify your email address?" This suggests that account activation might be related to email verification in some implementations, though the state field itself doesn't directly control this behavior. [Kratos API Reference](https://www.ory.sh/docs/kratos/reference/api) shows this state property in various API responses related to identity management.quick-addition-90714
04/26/2025, 11:11 AMbrief-egg-61061
04/26/2025, 11:11 AMbrief-egg-61061
04/26/2025, 11:12 AMtemplate_data
variable. This allows you to access user details in your message templates: jsonnet function(ctx) { recipient: ctx.recipient, template_type: ctx.template_type, name: if "template_data" in ctx && "identity" in ctx.template_data && "name" in ctx.template_data.identity then ctx.template_data.identity.name else null, // other fields... }
As shown in this example, you can access the user's name through ctx.template_data.identity.name
[HTTP based email delivery](https://www.ory.sh/docs/kratos/self-hosted/email-http#configuration). The identity object is available in various message templates, particularly for: - Recovery emails (valid) - Recovery code emails (valid) - Verification emails (valid) - Verification code emails (valid) When creating custom email templates, you can access the identity information directly. For example, in a recovery email template, you could personalize the greeting with the user's first name: Hello {{ upper .Identity.traits.firstName }}, to recover your account, please enter the following code:
This example shows how to access the user's first name from the identity traits [Email templates in self-hosted Ory Kratos](https://www.ory.sh/docs/kratos/self-hosted/mail-courier-templates). The available identity information depends on your identity schema configuration, but typically includes all the traits you've defined in your schema, such as email, name, phone number, etc.quick-addition-90714
04/26/2025, 11:16 AMbrief-egg-61061
04/26/2025, 11:16 AMbrief-egg-61061
04/26/2025, 11:17 AMjsonnet function(ctx) { recipient: ctx.recipient, template_type: ctx.template_type, name: if "template_data" in ctx && "identity" in ctx.template_data && "traits" in ctx.template_data.identity && "name" in ctx.template_data.identity.traits then ctx.template_data.identity.traits.name.first + " " + ctx.template_data.identity.traits.name.last else null, 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, }
Then, in your configuration file, reference this template: yaml courier: delivery_strategy: http http: request_config: url: <https://your-api-endpoint.com> method: POST body: <file://path/to/your/template.jsonnet> headers: Content-Type: application/json
This template specifically combines the first and last name from your identity traits structure to create a single "name" field with the value "Luka Boulpaep" in the HTTP request payload [HTTP based email delivery](https://www.ory.sh/docs/kratos/self-hosted/email-http#configuration). Note that the template checks for the existence of each property in the path to avoid errors if any part of the structure is missing. If you're using email templates directly rather than HTTP delivery, you can also access the combined name in your email templates using: Hello {{ .Identity.traits.name.first }} {{ .Identity.traits.name.last }},
This would render as "Hello Luka Boulpaep," in your email [Email templates in self-hosted Ory Kratos](https://www.ory.sh/docs/kratos/self-hosted/mail-courier-templates).quick-addition-90714
04/26/2025, 11:19 AMjson:"recipient"
TemplateType string json:"template_type"
Name *string json:"name,omitempty"
To *string json:"to,omitempty"
RecoveryCode *string json:"recovery_code,omitempty"
RecoveryURL *string json:"recovery_url,omitempty"
VerificationURL *string json:"verification_url,omitempty"
VerificationCode *string json:"verification_code,omitempty"
}brief-egg-61061
04/26/2025, 11:19 AMbrief-egg-61061
04/26/2025, 11:19 AMRecipient
- The email address of the recipient - TemplateType
- The type of template being used - Name
- The name of the user (which you've customized in previous examples) - To
- The recipient email address (duplicated in template_data) - RecoveryCode
, RecoveryURL
- For recovery flows - VerificationURL
, VerificationCode
- For verification flows However, based on the default Jsonnet template used by Ory Kratos for HTTP delivery, you should also include: go type EmailTemplate struct { Recipient string `json:"recipient"` TemplateType string `json:"template_type"` Name *string `json:"name,omitempty"` To *string `json:"to,omitempty"` RecoveryCode *string `json:"recovery_code,omitempty"` RecoveryURL *string `json:"recovery_url,omitempty"` VerificationURL *string `json:"verification_url,omitempty"` VerificationCode *string `json:"verification_code,omitempty"` LoginCode *string `json:"login_code,omitempty"` RegistrationCode *string `json:"registration_code,omitempty"` Subject *string `json:"subject,omitempty"` Body *string `json:"body,omitempty"` }
The additional fields are: - LoginCode
- For one-time code login flows - RegistrationCode
- For one-time code registration flows - Subject
- The email subject - Body
- The email body These fields are included in the default Jsonnet template as shown in the [Use a custom server to send Ory Identity messages to users](https://www.ory.sh/docs/kratos/emails-sms/sending-emails-smtp#send-emails-using-an-http-server) documentation. If you're only handling recovery and verification flows, your current struct might be sufficient, but including all possible fields will make your code more robust for future use cases. Kapa.ai: I've analyzed your Go struct for parsing Ory Kratos courier email templates. It covers most fields but is missing a few that are in the default template. I've provided the complete struct with all fields you should include for full compatibility.quick-addition-90714
04/26/2025, 11:20 AMquick-addition-90714
04/26/2025, 11:21 AMbrief-egg-61061
04/26/2025, 11:21 AMbrief-egg-61061
04/26/2025, 11:21 AM&
) and URL formatting (<http://template_data.to|template_data.to>
) appear to be incorrectly encoded. Here's the corrected version: jsonnet function(ctx) { recipient: ctx.recipient, template_type: ctx.template_type, name: if "template_data" in ctx && "identity" in ctx.template_data && "traits" in ctx.template_data.identity && "name" in ctx.template_data.identity.traits then ctx.template_data.identity.traits.name.first + " " + ctx.template_data.identity.traits.name.last else null, 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, }
This template will correctly extract the user's first and last name from the identity traits and combine them into a single "name" field. However, as mentioned in my previous response, you might want to consider adding the additional fields that are available in the default template: - login_code
- registration_code
- subject
- body
These fields are included in the default Jsonnet template as shown in the [Use a custom server to send Ory Identity messages to users](https://www.ory.sh/docs/kratos/emails-sms/sending-emails-smtp#send-emails-using-an-http-server) documentation. If you only need to handle the fields you've included, then your template (with the formatting fixes) should work correctly for your use case.quick-addition-90714
04/26/2025, 12:41 PMbrief-egg-61061
04/26/2025, 12:41 PMbrief-egg-61061
04/26/2025, 12:41 PMcsrf_token
parameter - The HTTP header as X-CSRF-Token
2. Or, if you did include a CSRF token, it doesn't match the one in the cookie. ## How to fix this issue: For API-based flows (which you're trying to use), you have a few options: 1. Include the CSRF token in your request body: When submitting the recovery flow, you need to include the csrf_token
field in your request body. This token can be found in the UI nodes of the flow response as a hidden input field named csrf_token
[CSRF troubleshooting](https://www.ory.sh/docs/kratos/debug/csrf). 2. Include the CSRF token in the X-CSRF-Token header: Alternatively, you can include the same token in the X-CSRF-Token
HTTP header. 3. Make sure cookies are properly passed: Ensure that you're passing all cookies from previous requests in your current request. Here's an example of how to properly submit a recovery flow with the CSRF token: curl -X POST \ -H 'Content-Type: application/json' \ -H 'Accept: application/json' \ -b cookies.txt \ -d '{"method":"code","email":"<mailto:example@example.com|example@example.com>","csrf_token":"your-csrf-token"}' \ "<https://your-kratos-domain/self-service/recovery?flow=<your-flow-id>>"
If you're using the admin API, note that even though you're creating a recovery with type "api", the browser-based CSRF protection might still be active if cookies are present in your request [Submit recovery flow](https://www.ory.sh/docs/kratos/bring-your-own-ui/custom-ui-basic-integration#submit-recovery-flow). The maintainer's comment in a similar issue confirms this: "The error in your log clearly indicates that you are not sending the CSRF Token in your request body csrf_token=…
which is needed to verify the token" [CSRF Error during Login Flow](https://github.com/ory/kratos/discussions/4307). To completely avoid CSRF issues with API flows, you might want to ensure you're not sending any cookies with your request, or use a fresh HTTP client for each request that doesn't store cookies between requests.quick-addition-90714
04/26/2025, 12:49 PMbrief-egg-61061
04/26/2025, 12:49 PMbrief-egg-61061
04/26/2025, 12:50 PM/admin/recovery/code
endpoint was successful. The logs show: 1. The request was received at the admin endpoint 2. A recovery code was successfully created for identity ID 9e603962-98a1-47e8-8605-9d1e8f073160
3. The request completed with a 201 Created status This is working correctly because you're using the admin API endpoint, which doesn't require CSRF protection. The admin API is designed for server-to-server communication and bypasses the CSRF checks that were causing your previous error. When you mentioned in your previous message that you were getting CSRF errors, it was likely because you were either: 1. Using a public-facing endpoint instead of the admin endpoint 2. Or mixing cookie-based authentication with API requests The admin endpoints (like /admin/recovery/code
that you're using now) don't require CSRF tokens because they're protected by different authentication mechanisms (typically API keys or other admin credentials). I'll wait for your next message with the logs from your service running in docker-compose to help diagnose any issues you might be having there.quick-addition-90714
04/26/2025, 12:50 PMbrief-egg-61061
04/26/2025, 12:50 PMbrief-egg-61061
04/26/2025, 12:50 PM/admin/recovery/code
endpoint from your service, you're encountering a CSRF error, unlike when you call it from Postman. The key difference appears to be related to cookies. The error message states: > 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). This suggests that your Go HTTP client is sending cookies with your request, but not including the corresponding CSRF token. Here are a few ways to fix this: 1. Include the CSRF token from the cookie in your request: - Add it to the request body as csrf_token
- Or add it as an X-CSRF-Token
header 2. Don't send cookies with your request: - Create a new HTTP client for each request that doesn't store cookies - Or disable cookie jar in your HTTP client Here's how you might modify your Go code to create a client that doesn't use cookies: go client := &http.Client{ Jar: nil, // Explicitly set to nil to disable cookie storage }
According to the Ory maintainer's response to a similar issue: "The token value you send in the body comes from the API response of /self-service/login/flows and is a different value than the one from the cookie" [CSRF Error during Login Flow](https://github.com/ory/kratos/discussions/4307). This suggests that there might be a mismatch between the CSRF token in your cookies and what you're sending (if you're sending one at all). Since the admin API endpoint should work without CSRF protection (as it did in Postman), the most likely issue is that your service is somehow maintaining cookies from previous interactions with Kratos, and those cookies contain CSRF tokens that are triggering the protection mechanism. Try implementing one of the solutions above, particularly disabling cookie storage in your HTTP client, and see if that resolves the issue.quick-addition-90714
04/26/2025, 12:54 PMbrief-egg-61061
04/26/2025, 12:54 PMbrief-egg-61061
04/26/2025, 12:54 PMCookie
header from the client when fetching the self-service flows... Without forwarding the Cookie
HTTP header you can't fetch the flow due to a security error. [CSRF troubleshooting](https://www.ory.sh/docs/troubleshooting/csrf) For your admin API calls, you should either: 1. Create a fresh HTTP client for each request that doesn't use cookies: go client := &http.Client{ Jar: nil, // Explicitly disable cookie storage }
2. Or clear any existing cookies before making the admin API call This should resolve the CSRF error you're encountering when calling the admin API from your service. Would you like me to provide more specific guidance on how to modify your Go HTTP client implementation?quick-addition-90714
04/27/2025, 8:20 PMbrief-egg-61061
04/27/2025, 8:20 PMbrief-egg-61061
04/27/2025, 8:20 PMyaml selfservice: flows: settings: after: default_browser_return_url: <https://your-desired-redirect-url/>
This will redirect users after they complete the settings flow (which includes updating their password after recovery) [Browser redirects and flow completion](https://www.ory.sh/docs/concepts/redirects#redirect-flows). ## Option 2: Use the return_to
parameter You can include a return_to
parameter when initializing the recovery flow: sdk.createBrowserRecoveryFlow({ return_to: "<https://your-desired-redirect-url/>" })
However, there's a known issue with this approach. According to a GitHub issue: "When creating a recovery flow with the return_to
query parameter the url is not respected when the account has two factor authentication" [Recovery flow with Two-Factor does not respect return_to
](https://github.com/ory/network/issues/222). ## Option 3: Manual redirect in your UI Since the recovery flow redirects to the settings page, you can implement a custom redirect in your settings UI by checking if the user came from a recovery flow and then redirecting them after they submit the password change. ## Important note There's an open issue in the Ory Kratos GitHub repository about this exact problem: "Recovery flow redirect after success not working as expected" [GitHub Issue #2371](https://github.com/ory/kratos/issues/2371). According to this issue, the default_browser_return_url
configuration for the recovery flow doesn't work as expected because the recovery flow redirects to the settings flow. A user in the issue comments mentioned: "The only way to reliably achieve this behaviour is to cause a manual overriding redirect INSIDE the settings page - By checking the source redirect that brought you to that page, and checking if that value contains the recovery flow identifier." Would you like me to provide more details on any of these approaches?quick-addition-90714
05/04/2025, 5:08 PMbrief-egg-61061
05/04/2025, 5:08 PMbrief-egg-61061
05/04/2025, 5:08 PMquick-addition-90714
05/09/2025, 10:48 PMbrief-egg-61061
05/09/2025, 10:48 PMbrief-egg-61061
05/09/2025, 10:48 PMquick-addition-90714
05/18/2025, 9:39 AMbrief-egg-61061
05/18/2025, 9:39 AMbrief-egg-61061
05/18/2025, 9:39 AMquick-addition-90714
05/20/2025, 6:07 PMbrief-egg-61061
05/20/2025, 6:07 PMbrief-egg-61061
05/20/2025, 6:07 PMcreateNativeRecoveryFlow
endpoint) while a valid session cookie or session token is present, you will receive a 400 Bad Request
error. The documentation states: > On an existing recovery flow, use the getRecoveryFlow
API endpoint. This means you should retrieve and continue the existing flow using its ID, rather than starting a new one. This approach helps prevent issues such as CSRF attacks and ensures the integrity of the recovery process [Ory API Reference – createNativeRecoveryFlow](https://www.ory.sh/docs/reference/api). If the existing flow has expired, you will need to initiate a new one. Otherwise, always use the current flow until it is completed or expires.quick-addition-90714
05/20/2025, 6:08 PMbrief-egg-61061
05/20/2025, 6:08 PMbrief-egg-61061
05/20/2025, 6:08 PM