<@U04UQ68083H> ory kratos, how can i disable verif...
# ory-copilot
s
@chilly-king-10285 ory kratos, how can i disable verify email? I mean if a user has an email, he needs to verify, if no he does not need to verify
b
A message from kapa.ai
To achieve the behavior where email verification is only required if a user provides an email (and not required if they don't), you need to configure your identity schema and verification settings accordingly. Key points: - Email verification is triggered if the identity schema marks the email trait as verifiable (i.e., includes
"verification": { "via": "email" }
in the schema). - If a user does not provide an email, no verification is triggered for that user. - If you want to allow users to register without an email (e.g., using only a phone number), make sure the
email
field is not required in your schema. - If the
email
field is present and marked as verifiable, Ory will send a verification email after registration, even if the user registered using another method (like phone/SMS) [Phone+email schema: verification email is sent when signed up with SMS code](https://github.com/ory/kratos/issues/4161). How to configure: 1. Make the email trait optional in your identity schema: - Do not include
"email"
in the
required
array of your schema's
traits
object. 2. Mark email as verifiable only if present: - Keep the
"verification": { "via": "email" }
property in the email trait definition. - Ory will only require verification if the user provides an email during registration. Example schema snippet:
Copy code
json {   "properties": {     "traits": {       "type": "object",       "properties": {         "email": {           "type": "string",           "format": "email",           "<http://ory.sh/kratos|ory.sh/kratos>": {             "verification": {               "via": "email"             }           }         },         "phone": {           "type": "string",           "format": "tel"         }       },       "required": ["phone"],  // Only phone is required       "additionalProperties": false     }   } }
With this setup: - If a user registers with a phone only, no email verification is triggered. - If a user provides an email, they will be required to verify it. Note: If you want to completely disable email verification for all users, remove the
"verification": { "via": "email" }
property from the schema. But for your use case (verify only if email is present), the above approach is correct. For more details, see the discussion and schema examples in [Phone+email schema: verification email is sent when signed up with SMS code](https://github.com/ory/kratos/issues/4161).
s
@chilly-king-10285 ory kratos, I am using Google authenticator, but I want some users must enable totp and some user not need to enable totp. how can i do?
b
A message from kapa.ai
Ory Kratos does not natively support enforcing TOTP (Time-based One-Time Password, e.g., Google Authenticator) for only a subset of users based on user-specific criteria directly in its configuration. The enforcement of multi-factor authentication (MFA) is typically set at the flow or project level, not per user. You can configure the required authentication assurance level (AAL) for flows such as login or settings, but this applies to all users equally—users who have a second factor configured will be prompted, and those who do not will not be required to provide it. There is no built-in way to require TOTP for only some users and not others purely through configuration. How it works: - If you set
required_aal: highest_available
for a flow (e.g., settings or login), users who have set up TOTP (or another second factor) will be required to use it. Users who have not set up a second factor will only need their primary factor (e.g., password) [Configure multi-factor authentication in Ory Kratos](https://www.ory.sh/docs/kratos/self-hosted/mfa), [Step-up authentication](https://www.ory.sh/docs/kratos/mfa/step-up-authentication). - There is no documented method to enforce TOTP setup for only a specific group of users (e.g., based on a user trait or role) at registration or login time. Possible approaches: - You could implement custom logic in your application layer: After user registration or login, check if the user matches your criteria for requiring TOTP. If so, redirect them to the settings flow and prompt them to enroll TOTP before allowing further access. - Alternatively, you could use traits in your identity schema to flag users who must have TOTP, and enforce this requirement in your application's business logic, but this is not handled automatically by Kratos itself. Summary: Ory Kratos enforces MFA requirements at the flow level, not per user. To require TOTP for only some users, you must implement this logic in your application, as there is no built-in configuration for per-user TOTP enforcement in the current Ory Kratos documentation and features. If you need more granular, per-user enforcement, you will need to handle this outside of Kratos using your own application logic after checking user traits or roles [Step-up authentication](https://www.ory.sh/docs/kratos/mfa/step-up-authentication), [Configure multi-factor authentication in Ory Kratos](https://www.ory.sh/docs/kratos/self-hosted/mfa). I'm sorry, but the knowledge sources do not describe a built-in way to enforce TOTP for only some users directly in Ory Kratos configuration.
s
@chilly-king-10285 ory kratos, what is usecase of
passwordless_enabled
?
b
A message from kapa.ai
The use case of the
passwordless_enabled
setting in Ory Kratos is to allow users to authenticate without needing a traditional password. When
passwordless_enabled
is set to
true
for the
code
method, users can log in using a one-time code sent to their email or phone (via SMS), instead of entering a password. This is particularly useful for applications that want to simplify the login process and improve user experience by removing the need for password management. Typical scenarios include: - Frictionless onboarding: Users can sign up and log in with just their email or phone number, receiving a one-time code for authentication. - Enhanced security: Reduces risks associated with password reuse and phishing, as users do not need to remember or enter passwords. - Modern authentication flows: Supports use cases like "magic link" or "OTP" (one-time password) authentication, which are popular in consumer apps. To enable passwordless login with one-time codes, you set
passwordless_enabled: true
in your configuration for the
code
method:
Copy code
yaml selfservice:   methods:     code:       passwordless_enabled: true
This can be configured via the Ory Console or CLI as well. When enabled, users will receive a code via email or SMS and use it to authenticate, bypassing the need for a password entirely [Enable one-time codes](https://www.ory.sh/docs/identities/get-started/passwordless), [Email and SMS one-time-code authentication](https://www.ory.sh/docs/kratos/passwordless/one-time-code).
s
@chilly-king-10285 But i get this error if user do not use password to login
Copy code
{
  "error": {
    "id": "session_aal1_required",
    "code": 401,
    "status": "Unauthorized",
    "request": "0d89e5c4eb4bb958d03e9b75e5314924",
    "reason": "You can not requested a higher AAL (AAL2/AAL3) without an active session.",
    "message": "aal2 and aal3 can only be requested if a session exists already"
  }
}
b
A message from kapa.ai
The error message you are seeing:
Copy code
json {   "error": {     "id": "session_aal1_required",     "code": 401,     "status": "Unauthorized",     "reason": "You can not requested a higher AAL (AAL2/AAL3) without an active session.",     "message": "aal2 and aal3 can only be requested if a session exists already"   } }
means that you are trying to request a higher Authenticator Assurance Level (AAL2 or AAL3, which require multi-factor authentication) without having an active session at AAL1. In Ory Kratos, passwordless login (using a one-time code) is considered a single-factor authentication and only grants AAL1. To request AAL2 (for example, to access a protected resource or perform a sensitive operation), the user must first have an active session at AAL1, and then "step up" to AAL2 by completing a second factor (like TOTP). Key points from the knowledge sources: - Passwordless login with a one-time code only provides AAL1, as it is a single-factor authentication method. - To access resources or flows that require AAL2, the user must already have an active session (AAL1) and then complete a second factor to upgrade the session to AAL2. - If you try to initiate an AAL2 flow (e.g., by visiting a URL with
?aal=aal2
) without an existing session, you will get this error. The correct flow is: first authenticate (AAL1), then step up to AAL2 if required by the application or endpoint [[Step-up authentication](https://www.ory.sh/docs/kratos/mfa/step-up-authentication)]. Summary: You cannot request AAL2 directly with passwordless login. The user must first log in (AAL1), and only then can you prompt them for a second factor to upgrade to AAL2. This is by design in Ory Kratos to ensure that multi-factor authentication is always a two-step process: establish a session, then step up if needed. If you need to enforce AAL2, make sure your users have a primary session (AAL1) before requiring the second factor [[Step-up authentication](https://www.ory.sh/docs/kratos/mfa/step-up-authentication)].
s
@chilly-king-10285 this means i will use
Copy code
curl --request GET \
  --url '{{host}}/kratos/self-service/login/browser?aal=aal1' \
  --header 'accept: application/json'
b
A message from kapa.ai
Yes, to initiate a login flow that only requires single-factor authentication (AAL1), you should use the following endpoint:
Copy code
GET /self-service/login/browser?aal=aal1
This will start a login flow where only the first authentication factor (such as password or passwordless one-time code) is required. This is the correct approach if you want to allow users to log in without requiring a second factor (AAL2) [[createBrowserLoginFlow](https://www.ory.sh/docs/kratos/reference/api)]. Your example cURL command is correct for this use case:
Copy code
bash curl --request GET \   --url '{{host}}/kratos/self-service/login/browser?aal=aal1' \   --header 'accept: application/json'
This will ensure the login flow is for AAL1, and users will not be prompted for a second factor unless you later initiate a step-up to AAL2 [[Step-up authentication](https://www.ory.sh/docs/kratos/mfa/step-up-authentication)].
s
@chilly-king-10285 how can i login after get flow
Copy code
curl --request GET \
  --url '{{host}}/kratos/self-service/login/browser?aal=aal1' \
  --header 'accept: application/json'
b
A message from kapa.ai
After you initiate the login flow with:
Copy code
bash curl --request GET \   --url '{{host}}/kratos/self-service/login/browser?aal=aal1' \   --header 'accept: application/json'
you will receive a response containing a
flow id
and a
ui.action
URL. The next step is to submit the user's credentials (such as identifier and password, or a one-time code if using passwordless) to the
ui.action
URL using a POST request. Example for password-based login: 1. Extract the flow ID and CSRF token from the response. 2. Submit the login form (replace placeholders with actual values):
Copy code
bash curl -X POST \   -H 'Content-Type: application/json' \   -H 'Accept: application/json' \   -d '{"method":"password","csrf_token":"<csrf_token>","identifier":"<user-identifier>","password":"<user-password>"}' \   -b cookies.txt \   -c cookies.txt \   "{{host}}/kratos/self-service/login?flow=<flow-id>"
- The
csrf_token
is required and can be found in the flow response under
ui.nodes
. - Use the
-b
and
-c
flags to handle cookies for browser flows. If you are using passwordless (one-time code) login, the payload will differ (e.g., you will send the code instead of a password). For more details and examples, see the [Submit login flow](https://www.ory.sh/docs/kratos/bring-your-own-ui/custom-ui-basic-integration#submit-login-flow) documentation. Summary of steps: 1. Start the login flow (GET). 2. Parse the response for
flow id
,
ui.action
, and
csrf_token
. 3. Submit credentials to the
ui.action
URL (POST) with the required fields and cookies. This is the standard way to complete a login after retrieving the flow in Ory Kratos [[Submit login flow](https://www.ory.sh/docs/kratos/bring-your-own-ui/custom-ui-basic-integration#submit-login-flow)].
s
@chilly-king-10285 please help me how to login with one-time code. I call
Copy code
curl --request POST \
  --url '{{host}}/kratos/self-service/login?flow=530f4a51-19eb-4570-8ebc-068dfbc6f402' \
  --header 'content-type: application/json' \
  --data '{
  "csrf_token": "{{totpFlowCsrf}}",
  "method": "totp",
  "totp_code": "558929"
}'
but i get error
Copy code
"messages": [
      {
        "id": 4010002,
        "text": "Could not find a strategy to log you in with. Did you fill out the form correctly?",
        "type": "error"
      }
    ]
b
A message from kapa.ai
The error message:
Copy code
"Could not find a strategy to log you in with. Did you fill out the form correctly?" (4010002)
means that the login method you specified (
"method": "totp"
) is not available or enabled for this login flow. If you want to log in using a one-time code (passwordless), you should use the
code
method, not
totp
. The
totp
method is for Time-based One-Time Passwords (like Google Authenticator), while the
code
method is for codes sent via email or SMS. How to log in with a one-time code: 1. Start the login flow (as you did). 2. Submit the code using the
code
method. Your POST request should look like this:
Copy code
bash curl --request POST \   --url '{{host}}/kratos/self-service/login?flow=530f4a51-19eb-4570-8ebc-068dfbc6f402' \   --header 'content-type: application/json' \   --data '{     "csrf_token": "{{csrf_token}}",     "method": "code",     "identifier": "<mailto:user@example.com|user@example.com>",     "code": "558929" }'
- Replace
{{csrf_token}}
with the CSRF token from the flow. - Replace
<mailto:user@example.com|user@example.com>
with the identifier (email or phone) used to receive the code. - Replace
558929
with the actual code received by the user. Key points: - The
method
must be
"code"
for passwordless one-time code login. - The
identifier
field is required to specify which user is logging in. - The
code
field is the one-time code sent to the user. For more details, see the [Ory Kratos API reference for the code method](https://www.ory.sh/docs/kratos/reference/api) and the [one-time code documentation](https://www.ory.sh/docs/kratos/passwordless/one-time-code). If you use the wrong method (like
totp
for a code flow), you will get the 4010002 error as described above [UI message codes](https://www.ory.sh/docs/kratos/concepts/ui-user-interface#could-not-find-a-strategy-to-log-you-in-with-did-you-fill-out-the-form-correctly-4010002).
s
@chilly-king-10285 i use user as an identify
b
A message from kapa.ai
If you want to use a username (user) as the identifier for login in Ory Kratos—including for passwordless one-time code login—you need to configure your identity schema so that the username field is marked as the identifier for the relevant authentication methods. For passwordless one-time code login, your schema should look like this:
Copy code
json {   "properties": {     "traits": {       "type": "object",       "properties": {         "user": {           "type": "string",           "<http://ory.sh/kratos|ory.sh/kratos>": {             "credentials": {               "code": {                 "identifier": true               }             }           }         }       }     }   } }
- The important part is
"credentials": { "code": { "identifier": true } }
under your
user
field. - This tells Ory Kratos to use the
user
trait as the identifier for the one-time code login flow. When you submit the login request, use the
user
value as the `identifier`:
Copy code
json {   "csrf_token": "<csrf_token>",   "method": "code",   "identifier": "<user>",   "code": "<one-time-code>" }
Note: The knowledge sources provide examples for using
email
,
username
, or
phone
as identifiers, and the same approach applies to any custom field name like
user
as long as you mark it as an identifier for the relevant method in your schema. For more details, see the [custom identity schema for one-time code](https://www.ory.sh/docs/kratos/passwordless/one-time-code#custom-identity-schema) and [identity schema examples](https://www.ory.sh/docs/kratos/manage-identities/customize-identity-schema#examples). If you encounter issues, double-check that your schema is correctly configured and that the field you use as the identifier is not required to be an email or phone unless you want it to be validated as such.
s
@chilly-king-10285 I get error
Copy code
"messages": [
      {
        "id": 4000035,
        "text": "This account does not exist or has not setup sign in with code.",
        "type": "error"
      }
    ]
b
A message from kapa.ai
The error message:
Copy code
{
  "id": 4000035,
  "text": "This account does not exist or has not setup sign in with code.",
  "type": "error"
}
means that either: 1. The identifier you provided (e.g., username, email, or phone) does not match any existing account, or 2. The account exists, but the identity schema for that account does not have the one-time code (
code
) login method enabled for the identifier field you are using. To resolve this: - Ensure the account exists with the identifier you are using. - Check your identity schema: The field you use as the identifier (e.g.,
user
,
username
,
email
, etc.) must be marked with the following extension for the
code
method:
Copy code
json   "<http://ory.sh/kratos|ory.sh/kratos>": {     "credentials": {       "code": {         "identifier": true       }     }   }
For example, if you use
user
as the identifier:
Copy code
json   {     "properties": {       "traits": {         "type": "object",         "properties": {           "user": {             "type": "string",             "<http://ory.sh/kratos|ory.sh/kratos>": {               "credentials": {                 "code": {                   "identifier": true                 }               }             }           }         }       }     }   }
- If you are using email or phone for code delivery, also specify the
via
property (e.g.,
"via": "email"
or
"via": "sms"
) if needed. See the documentation for more details and schema examples: [Passwordless one-time code login identifier](https://www.ory.sh/docs/kratos/manage-identities/customize-identity-schema#passwordless-one-time-code-login-identifier), [Custom identity schema for one-time code](https://www.ory.sh/docs/kratos/passwordless/one-time-code#custom-identity-schema). This error is documented in the Ory Kratos UI messages: [This account does not exist or has not setup sign in with code. (4000035)](https://www.ory.sh/docs/kratos/concepts/ui-user-interface#this-account-does-not-exist-or-has-not-setup-sign-in-with-code-4000035). Summary: You must ensure both that the account exists and that the identifier field is properly configured for code-based login in your identity schema. If either is missing, you will get this error.
s
@chilly-king-10285 currently my config is
Copy code
{
  "$id": "kratos/email-password/identity.schema.json",
  "$schema": "<http://json-schema.org/draft-07/schema#>",
  "title": "Person",
  "type": "object",
  "properties": {
    "traits": {
      "type": "object",
      "properties": {
        "email": {
          "type": "string",
          "format": "email",
          "title": "E-Mail",
          "minLength": 8,
          "maxLength": 50,
          "<http://ory.sh/kratos|ory.sh/kratos>": {
            "credentials": {
              "password": {
                "identifier": false
              },
              "code": {
                "identifier": true,
                "via": "email"
              }
            },
            "verification": {
              "via": "email"
            },
            "recovery": {
              "via": "email"
            }
          }
        },
        "username": {
          "type": "string",
          "format": "username",
          "title": "User name",
          "pattern": "^[a-zA-Z0-9][a-zA-Z0-9@_.-]{7,49}$",
          "minLength": 8,
          "maxLength": 50,
          "<http://ory.sh/kratos|ory.sh/kratos>": {
            "credentials": {
              "password": {
                "identifier": true
              },
              "totp": {
                "account_name": true
              }
            }
          }
        }
      },
      "required": [
        "username"
      ],
      "additionalProperties": false
    }
  }
}
how can i change?
b
A message from kapa.ai
To enable passwordless one-time code login using the username (instead of email) as the identifier, you need to update your identity schema so that the
username
field is marked as the identifier for the
code
method. Currently, your schema only allows the
email
field to be used for code-based login (
"code": { "identifier": true, "via": "email" }
), while
username
is only set up for password and TOTP. How to change your schema: 1. Add the
code
credential with
"identifier": true
to the
username
field. 2. If you want to use the username as the identifier for code-based login, you do not need the
"via": "email"
property under
username
. Example update:
Copy code
json {   "$id": "kratos/email-password/identity.schema.json",   "$schema": "<http://json-schema.org/draft-07/schema#>",   "title": "Person",   "type": "object",   "properties": {     "traits": {       "type": "object",       "properties": {         "email": {           "type": "string",           "format": "email",           "title": "E-Mail",           "minLength": 8,           "maxLength": 50,           "<http://ory.sh/kratos|ory.sh/kratos>": {             "credentials": {               "password": {                 "identifier": false               },               "code": {                 "identifier": false,   // Set to false or remove if not using email for code login                 "via": "email"               }             },             "verification": {               "via": "email"             },             "recovery": {               "via": "email"             }           }         },         "username": {           "type": "string",           "title": "User name",           "pattern": "^[a-zA-Z0-9][a-zA-Z0-9@_.-]{7,49}$",           "minLength": 8,           "maxLength": 50,           "<http://ory.sh/kratos|ory.sh/kratos>": {             "credentials": {               "password": {                 "identifier": true               },               "totp": {                 "account_name": true               },               "code": {                 "identifier": true               }             }           }         }       },       "required": ["username"],       "additionalProperties": false     }   } }
Key points: - The
"code": { "identifier": true }
under
username
enables passwordless one-time code login using the username as the identifier. - If you want to disable code login via email, set
"identifier": false
or remove the
code
credential from the
email
field. - Make sure your application sends the username as the
identifier
when performing the code login flow. For more details, see the [passwordless one-time code login identifier documentation](https://www.ory.sh/docs/kratos/manage-identities/customize-identity-schema#passwordless-one-time-code-login-identifier) and [custom identity schema for one-time code](https://www.ory.sh/docs/kratos/passwordless/one-time-code#custom-identity-schema). If you follow this update, users will be able to log in with a one-time code using their username as the identifier.
s
@chilly-king-10285 ory kratos using email to recovery I call
Copy code
curl --request POST \
  --url '{{host}}kratos/self-service/recovery?flow=fdae3164-6602-4921-961d-2be6ae915323' \
  --header 'accept: application/json' \
  --header 'content-type: application/json' \
  --header 'cookie: {{recoveryFlowCookie}}' \
  --cookie '{{recoveryFlowCookie}}' \
  --data '{
  "csrf_token": "{{recoveryFlowCsrf}}",
  "method": "code",
  "code": "273228"
}'
I get error
Copy code
{
  "error": {
    "id": "browser_location_change_required",
    "code": 422,
    "status": "Unprocessable Entity",
    "reason": "In order to complete this flow please redirect the browser to: <https://www.ory.sh/kratos/docs/fallback/settings?flow=415c3bbb-dc57-49d1-aba3-9b6cc4ea2cd4>",
    "message": "browser location change required"
  },
  "redirect_browser_to": "<https://www.ory.sh/kratos/docs/fallback/settings?flow=415c3bbb-dc57-49d1-aba3-9b6cc4ea2cd4>"
}
b
A message from kapa.ai
The error you are seeing:
Copy code
json {   "error": {     "id": "browser_location_change_required",     "code": 422,     "status": "Unprocessable Entity",     "reason": "In order to complete this flow please redirect the browser to: <https://www.ory.sh/kratos/docs/fallback/settings?flow=415c3bbb-dc57-49d1-aba3-9b6cc4ea2cd4>",     "message": "browser location change required"   },   "redirect_browser_to": "<https://www.ory.sh/kratos/docs/fallback/settings?flow=415c3bbb-dc57-49d1-aba3-9b6cc4ea2cd4>" }
means that Ory Kratos requires the browser to be redirected to a new location to continue or complete the recovery flow. This is a standard behavior for browser-based flows when a location change is necessary, such as after a successful recovery or when the flow state changes (for example, after submitting a valid recovery code). What to do: - When you receive this error with
id: "browser_location_change_required"
and a
redirect_browser_to
URL, your application should redirect the user's browser to the provided URL. This is how Kratos signals that the next step in the flow must be handled in the browser, not via an API call. - This is especially relevant for SPAs or custom UIs, where you need to programmatically handle the redirect in your frontend code. This behavior is documented in the Ory Kratos API and UI integration guides, where a 422 error with this ID indicates that a browser redirect is required to continue the flow. The response includes the URL you should redirect to, which will allow the user to proceed with the recovery or settings process in the browser interface [SPAs and the '422' error](https://www.ory.sh/docs/kratos/bring-your-own-ui/custom-ui-advanced-integration#spas-and-the-422-error). Summary: You should redirect the browser to the URL provided in the
redirect_browser_to
field to continue the recovery process. This is expected behavior for browser flows in Ory Kratos when a location change is required to complete the flow.
s
@chilly-king-10285 i am using ajax, so the next step is?
b
A message from kapa.ai
When using AJAX (for example, in a Single Page Application), if you receive a 422 error with
id: "browser_location_change_required"
and a
redirect_browser_to
URL, the correct next step is to programmatically redirect the browser to the URL provided in the
redirect_browser_to
field. This is how Ory Kratos signals that the flow must continue in the browser at a new location. In practice: - Your frontend should detect this specific error in the AJAX response. - Then, use
window.location.href = response.redirect_browser_to
(or similar) to redirect the user. This is the recommended approach for handling this scenario in SPAs, as described in the documentation: > A response code
422
indicates that the browser needs to be redirected with a newly created flow. Since this is an SPA, the new flow ID can be extracted from the payload and the response can be retrieved in the background instead of a redirect. > Example: >
Copy code
json > { >   error: { >     id: "browser_location_change_required", >     ... >   }, >   redirect_browser_to: "/ui/login?flow=ad574ad7-1a3c-4b52-9f54-ef9e866f3cec" > } >
> [SPAs and the '422' error](https://www.ory.sh/docs/kratos/bring-your-own-ui/custom-ui-advanced-integration#spas-and-the-422-error) Summary: When you get this error in your AJAX response, redirect the browser to the URL in
redirect_browser_to
to continue the flow.
s
@chilly-king-10285 i get error
Copy code
{
  "error": {
    "id": "security_identity_mismatch",
    "code": 403,
    "status": "Forbidden",
    "request": "19e48c5090c27e5df2b0af63c10d8598",
    "reason": "The request was initiated by someone else and has been blocked for security reasons. Please go back and try again.",
    "message": "The requested action was forbidden"
  }
}
b
A message from kapa.ai
The error you are seeing:
Copy code
json {   "error": {     "id": "security_identity_mismatch",     "code": 403,     "status": "Forbidden",     "reason": "The request was initiated by someone else and has been blocked for security reasons. Please go back and try again.",     "message": "The requested action was forbidden"   } }
means that the flow you are trying to complete was initiated by a different identity (user) than the one currently making the request. This is a security feature in Ory Kratos to prevent one user from completing a flow that was started by another user. Common causes: - The session cookie or authentication context has changed between starting and completing the flow. - The flow was started in one browser or device, but the completion attempt is happening in another. - The flow is being completed by a different user than the one who initiated it. How to resolve: - Make sure the same user and session are used for both starting and completing the flow. - Do not share flow URLs or tokens between users or devices. - If you see this error, restart the flow from the beginning to ensure the session context matches. This behavior is described in the Ory Kratos API documentation, where a
security_identity_mismatch
error indicates that the requested
?return_to
address or flow is not allowed to be used by the current identity, and the flow was interrupted for security reasons. Adjust your application to ensure flows are only completed by the initiating user and session [[updateSettingsFlow](https://www.ory.sh/docs/kratos/reference/api)]. If you continue to see this error, double-check your session and cookie handling, especially in SPAs or when using AJAX, to ensure the correct session is maintained throughout the flow.
s
@chilly-king-10285 Hi all I am following these steps to reset password via email 1. Get recovery flow
Copy code
curl --request GET \
  --url '<http://127.0.0.1:4455/kratos/self-service/recovery/browser?refresh=true>' \
  --header 'accept: application/json' \
  --header 'content-type: application/json'
2. Send code to email
Copy code
curl --request POST \
  --url '<http://127.0.0.1:4455/kratos/self-service/recovery?flow={{recoveryFlowId}}>' \
  --header 'accept: application/json' \
  --header 'content-type: application/json' \
  --header 'cookie: {{recoveryFlowCookie}}' \
  --cookie '{{recoveryFlowCookie}}' \
  --data '{
  "csrf_token": "{{recoveryFlowCsrf}}",
  "method": "code",
  "email": "<mailto:example@gmail.com|example@gmail.com>"
}'
3. Get setting flow
Copy code
curl --request POST \
  --url '<http://127.0.0.1:4455/kratos/self-service/recovery?flow={{recoveryFlowId}}>' \
  --header 'accept: application/json' \
  --header 'content-type: application/json' \
  --header 'cookie: {{recoveryFlowCookie}}' \
  --cookie '{{recoveryFlowCookie}}' \
  --data '{
  "csrf_token": "{{recoveryFlowCsrf}}",
  "method": "code",
  "code": "268155"
}'
4. Change password
Copy code
curl --request POST \
  --url '<http://127.0.0.1:4455/kratos/self-service/settings?flow={{settingFlowId}}>' \
  --header 'accept: application/json' \
  --header 'content-type: application/json' \
  --header 'cookie: {{oryKratosSession}};{{settingFlowCookie}}' \
  --cookie '{{oryKratosSession}};{{settingFlowCookie}}' \
  --data '{
  "csrf_token": "{{settingFlowCsrf}}",
  "method": "password",
  "password": "123SupperPassword2025$"
}'
All steps work well in my local machine (docker compose) But when I deploy on k9s, step 3 gets the response is
Copy code
{
  "error": {
    "id": "browser_location_change_required",
    "code": 422,
    "status": "Unprocessable Entity",
    "reason": "In order to complete this flow please redirect the browser to: <https://www.ory.sh/kratos/docs/fallback/settings?flow=d596e88c-f173-426a-86b5-79ff07e85e27>",
    "message": "browser location change required"
  },
  "redirect_browser_to": "<https://www.ory.sh/kratos/docs/fallback/settings?flow=d596e88c-f173-426a-86b5-79ff07e85e27>"
}
please suggest me how to fix
b
A message from kapa.ai
The behavior you're seeing—receiving a 422 error with
id: "browser_location_change_required"
and a
redirect_browser_to
URL after submitting the recovery code—is expected in Ory Kratos when using browser flows and AJAX (such as in SPAs or custom UIs). This response means Kratos requires the browser to be redirected to a new location (in this case, the settings flow) to continue the process. Why does this happen? - In browser flows, after a successful recovery code submission, Kratos transitions the user to a settings flow to allow them to set a new password. - Kratos signals this transition by returning a 422 error with a
redirect_browser_to
field, instructing your frontend to redirect the browser to the provided URL to continue the flow [[SPAs and the '422' error](https://www.ory.sh/docs/kratos/bring-your-own-ui/custom-ui-advanced-integration#spas-and-the-422-error)]. How to handle this: - In your frontend, detect this specific error in your AJAX response. - Programmatically redirect the browser to the URL in the
redirect_browser_to
field. For example, in JavaScript:
Copy code
js   if (response.error && response.error.id === "browser_location_change_required") {     window.location.href = response.redirect_browser_to;   }
- This will allow the user to continue the password reset process in the correct flow context. Summary: This is not a misconfiguration—it's the designed behavior for browser flows in Ory Kratos. You need to handle the 422 response by redirecting the browser to the provided URL to continue the recovery and settings process [[SPAs and the '422' error](https://www.ory.sh/docs/kratos/bring-your-own-ui/custom-ui-advanced-integration#spas-and-the-422-error)]. If you need a fully API-driven (non-browser) flow, you would need to use the API flow endpoints and handle sessions differently, but for browser flows, this redirect is required.
s
@chilly-king-10285 how can i call the next step
redirect_browser_to
using ajax?
b
A message from kapa.ai
When you receive a response from Ory Kratos with a
422
error and a
redirect_browser_to
field while using AJAX, it means Kratos expects the browser to be redirected to the provided URL to continue the flow. In a Single Page Application (SPA) or AJAX context, you should programmatically redirect the browser to that URL. **You cannot "call" the next step purely via AJAX**—the flow is designed to be continued in the browser context. The correct approach is to set
window.location.href
(or similar) to the value of
redirect_browser_to
in your frontend code. This will navigate the user to the next step in the flow as required by Kratos. Example (JavaScript):
Copy code
js if (response.error && response.error.id === "browser_location_change_required") {   window.location.href = response.redirect_browser_to; }
This is the recommended way to handle the 422 error in SPAs, as described in the Ory documentation: > A response code
422
indicates that the browser needs to be redirected with a newly created flow. Since this is an SPA, the new flow ID can be extracted from the payload and the response can be retrieved in the background instead of a redirect. > [SPAs and the '422' error](https://www.ory.sh/docs/kratos/bring-your-own-ui/custom-ui-advanced-integration#spas-and-the-422-error) Summary: You must redirect the browser to the
redirect_browser_to
URL. The next step cannot be completed via AJAX alone; a browser navigation is required to continue the flow.
s
@chilly-king-10285
Copy code
curl --request POST \
  --url '{{host}}/self-service/settings?flow=2a2a701a-7a45-4df1-a710-816cc4f9efc' \
  --header 'accept: application/json' \
  --header 'content-type: application/json' \
  --header 'cookie: ory_kratos_session=MTc0OTAyODM3N3xncTJXMGdUQjIyb2JVbnNnaUx6U2FNWFc3dV9mRDAyZTQ1VFF4VmNsNDY2X1N4Xy1GS1M1WkVBblZnOE5DT0R2Q0xtVzlOLV9CRXlDVUZTel9FdEl4aENjMGV6WV9oNEhkMVdWNEM4UXJHaENneHF1Z3NYUnU0aFNlT01aTm84bjI1Z2t5d1pOaDJHTE5KS1p5SEMzbS1nRkxfQllqYTl5VUZmeGcya2dxRjdVVjRJdlF3WFk4ekVVVjJKRGxmQlQ2U254b1JHZU1wVzlPNHB3bDBqdGRDUml3Y0NRcHNZRjREa2wxNmlQS3BvWmdpOEwxRlBxeVFSWXJVNWVpcll4YUZ0VW96Qm5vM01oN0RGUF8xMjZ8_zfeN1RlmMIoDP6V9RszmlOwtZn3OwCCNgjTjO4wE88=;csrf_token_308f747c083a9186054ac556e82c244ceb52f8a0e6159140ddb89100318a5e54=lq4sSeHxUIl9gpC8wT9tNwoAvi0jrumMDZeSkB/OU7A=; Path=/; Max-Age=31536000; HttpOnly; Secure; SameSite=Strict' \
  --cookie 'ory_kratos_session=MTc0OTAyODM3N3xncTJXMGdUQjIyb2JVbnNnaUx6U2FNWFc3dV9mRDAyZTQ1VFF4VmNsNDY2X1N4Xy1GS1M1WkVBblZnOE5DT0R2Q0xtVzlOLV9CRXlDVUZTel9FdEl4aENjMGV6WV9oNEhkMVdWNEM4UXJHaENneHF1Z3NYUnU0aFNlT01aTm84bjI1Z2t5d1pOaDJHTE5KS1p5SEMzbS1nRkxfQllqYTl5VUZmeGcya2dxRjdVVjRJdlF3WFk4ekVVVjJKRGxmQlQ2U254b1JHZU1wVzlPNHB3bDBqdGRDUml3Y0NRcHNZRjREa2wxNmlQS3BvWmdpOEwxRlBxeVFSWXJVNWVpcll4YUZ0VW96Qm5vM01oN0RGUF8xMjZ8_zfeN1RlmMIoDP6V9RszmlOwtZn3OwCCNgjTjO4wE88=;csrf_token_308f747c083a9186054ac556e82c244ceb52f8a0e6159140ddb89100318a5e54=lq4sSeHxUIl9gpC8wT9tNwoAvi0jrumMDZeSkB/OU7A=; Path=/; Max-Age=31536000; HttpOnly; Secure; SameSite=Strict' \
  --data '{
  "csrf_token": "{{recoveryFlowCsrf}}",
  "method": "password",
  "password": "123SupperPassword2025$"
}'
I get error
Copy code
{
  "error": {
    "code": 400,
    "status": "Bad Request",
    "request": "9b7fc1550022bdf333b0a27e4401ee8b",
    "reason": "The flow query parameter is missing or malformed.",
    "message": "The request was malformed or contained invalid parameters"
  }
}
b
A message from kapa.ai
The error message:
Copy code
"The flow query parameter is missing or malformed."
means that the
flow
query parameter is either not present or not correctly formatted in your request URL. What’s wrong? Your request URL is:
Copy code
'{{host}}/self-service/settings?flow=2a2a701a-7a45-4df1-a710-816cc4f9efc'
This is correct in structure, but make sure: - The
flow
parameter is present and contains a valid flow ID. - The flow ID is not expired or invalid. - The URL is not being altered by your shell or environment (e.g., extra spaces, wrong variable interpolation). Checklist: 1. Double-check that
{{host}}
is replaced with your actual host (e.g., `http://127.0.0.1:4455`). 2. Ensure the flow ID (
2a2a701a-7a45-4df1-a710-816cc4f9efc
) is valid and not expired. 3. The request must be a
POST
to
/self-service/settings?flow=<flow-id>
with the correct flow ID as a query parameter. Example (with placeholders replaced):
Copy code
bash curl --request POST \   --url '<http://127.0.0.1:4455/self-service/settings?flow=2a2a701a-7a45-4df1-a710-816cc4f9efc>' \   --header 'accept: application/json' \   --header 'content-type: application/json' \   --cookie 'ory_kratos_session=...;csrf_token_...=...' \   --data '{     "csrf_token": "{{recoveryFlowCsrf}}",     "method": "password",     "password": "123SupperPassword2025$" }'
If you still get this error: - The flow may have expired. You need to start a new settings flow and use the new flow ID [[updateSettingsFlow](https://www.ory.sh/docs/kratos/reference/api)]. - Make sure you are not missing the
flow
parameter or using an incorrect one. Summary: This error is caused by a missing or invalid
flow
query parameter. Always ensure you use a valid, non-expired flow ID in your request URL as shown in the documentation [[updateSettingsFlow](https://www.ory.sh/docs/kratos/reference/api)].