<@U04UQ68083H> I running the command ```docker run...
# ory-copilot
q
@chilly-king-10285 I running the command
Copy code
docker run --rm -it -e ORY_PROJECT_API_KEY=<project_key> -e ORY_PROJECT=<projectID> oryd/ory tunnel --dev <http://localhost:5173>
But it still asks me to do a browser login
b
A message from kapa.ai
Based on the information provided in the knowledge sources, it appears that you're encountering an issue with the Ory Tunnel command. The Ory Tunnel is designed to allow your application and Ory to run on the same domain during local development. However, the command you're using seems to be slightly different from the recommended format. To address your issue, I suggest trying the following command instead:
Copy code
ory tunnel --project <project-id-or-slug> --dev <http://localhost:5173>
This command format is consistent with the examples provided in the [Ory Tunnel documentation](https://www.ory.sh/docs/cli/ory-tunnel). If you want to use API keys for authentication in automated environments (like CI/CD pipelines) to avoid browser login, you should set the API keys as environment variables. Here's how you can do it:
Copy code
export ORY_PROJECT_API_KEY=<project-api-key> ory tunnel --project <project-id-or-slug> --dev --quiet <http://localhost:5173>
The
--quiet
flag prevents the browser window from opening, as mentioned in the [Ory Tunnel documentation](https://www.ory.sh/docs/cli/ory-tunnel#connecting-in-automated-environments). If you're still experiencing issues after trying these suggestions, it might be helpful to check if you're using the latest version of the Ory CLI and ensure that your project ID and API key are correct.
q
@chilly-king-10285 I want a function to be called on successful logins from the Experience UI
b
A message from kapa.ai
To call a function (such as a webhook or custom logic) on successful logins from the Ory Account Experience UI, you should use Ory Actions (also referred to as "hooks" in some documentation). Ory Actions allow you to trigger external logic or webhooks in response to events like user login, regardless of whether the login happens via the Experience UI or a custom UI. How to trigger a function on successful login: 1. Configure an "after login" action using the Ory Console or the Ory CLI. - The most flexible action is the
web_hook
, which lets you call any external service or function you want. 2. Set up your webhook endpoint to receive and process the event. Example: Add a webhook to be called after login You can add a webhook using the Ory CLI like this:
Copy code
bash ory patch identity-config <project_id> \   --add '/selfservice/flows/login/after/hooks=[{"hook": "web_hook", "config": {"url": "<https://your-webhook-endpoint>"}}]'
This will call your function (the webhook) every time a user logs in successfully, including logins from the Experience UI. Where to configure: - In the Ory Console: Go to AuthenticationActions and add an "after login" action with the type "webhook" and your endpoint URL. - Or use the CLI as shown above. References: - [Ory Actions overview and configuration](https://www.ory.sh/docs/kratos/hooks/configure-hooks#available-actions) - [Customize login and registration behavior](https://www.ory.sh/docs/identities/sign-in/actions#customize-login-and-registration-behavior) If you need to trigger more complex logic, your webhook endpoint can execute any function you want when it receives the login event. Note: - The Experience UI is fully compatible with Ory Actions/hooks, so this approach works regardless of which UI is used. - If you need to trigger the function only for specific login methods (e.g., password, OIDC), you can further customize the hook configuration as described in the documentation. Let me know if you need an example webhook payload or more details!
q
@chilly-king-10285 is it possible to deactivate a user, and potenatially reactivate it?
b
A message from kapa.ai
Yes, it is possible to deactivate a user (identity) in Ory, and you can also reactivate them later. Ory supports two main identity states: - active: The identity can use self-service flows such as sign-in. - inactive: The identity cannot use self-service flows. When an identity is set to
inactive
, they are prevented from logging in. You can change the state back to
active
to allow the user to log in again. This can be done using the Ory SDKs or API by patching the identity's state. Here is an example using the JavaScript SDK:
Copy code
js import { Configuration, IdentityApi } from "@ory/client" import { JsonPatchOpEnum } from "@ory/client/api"  const identity = new IdentityApi(   new Configuration({     basePath: `https://${process.env.ORY_PROJECT_SLUG}.<http://projects.oryapis.com|projects.oryapis.com>`,     accessToken: process.env.ORY_API_KEY,   }), )  export async function setState(   identityId: string,   state: "active" | "inactive", ) {   return await identity     .patchIdentity({       id: identityId,       jsonPatch: [         {           op: JsonPatchOpEnum.Replace,           value: state,           path: "/state",         },       ],     })     .then(({ data }) => data) }
You can use a similar approach with other SDKs or directly via the API. This allows you to both deactivate and reactivate users as needed [Identity state](https://www.ory.sh/docs/identities/model/activate-deactivate-user-login-state/) [Disable User and Revoke all sessions](https://github.com/ory/network/issues/415).
q
@chilly-king-10285 I create users with
Copy code
async def create_user(self, email: str, user_id: str, company: Company) -> OryUser:
        request_body = {
            "schema_id": "<preset://email>",
            "traits": {
                "email": email
            },
            "metadata_public": {
                "userId": user_id,
                "tenantId": company.tenant_name
            }
        }
        return await <http://self.httpClient.post|self.httpClient.post>(
            f"{self.ory_base_uri}/admin/identities",
            data=request_body,
            headers={'Authorization': f"Bearer {self.config.ory_api_key}", 'Content-Type': 'application/json'},
            map_to=OryUser
        )
how do I get it to send an invite link via email to the user in question
b
A message from kapa.ai
To send an invite link via email to a user after creating them, you need to: 1. Create the user (as you are already doing). 2. Generate a recovery link for that user using the Admin API. 3. Manually send the recovery link to the user's email address. Currently, Ory does not automatically send the invite/recovery link via email when you create a user or generate a recovery link through the Admin API. You must handle the email sending yourself after obtaining the link [Invite users](https://www.ory.sh/docs/kratos/manage-identities/invite-users/) [Magic links](https://www.ory.sh/docs/kratos/manage-identities/account-recovery/#magic-links). Example flow: 1. Create the user (as in your code). 2. Generate the recovery link:
Copy code
python    response = await <http://self.httpClient.post|self.httpClient.post>(        f"{self.ory_base_uri}/admin/recovery/link",        data={            "identity_id": created_user.id,            "expires_in": "12h"        },        headers={            'Authorization': f"Bearer {self.config.ory_api_key}",            'Content-Type': 'application/json'        }    )    recovery_link = response['recovery_link']
3. Send the recovery link to the user's email using your own email service. > It is currently not possible to send the recovery link directly to a user's email, this feature is tracked as [#595](https://github.com/ory/kratos/issues/595) [Invite users](https://www.ory.sh/docs/kratos/manage-identities/invite-users/). Summary: You must send the invite/recovery link yourself after generating it with the Admin API. Ory does not send this email automatically.
q
@chilly-king-10285 can I filter a user by trait?
b
A message from kapa.ai
I'm sorry, but the knowledge sources do not explicitly mention support for filtering users (identities) by trait (such as email or custom fields) using the Ory Admin API. The available documentation and a related GitHub issue indicate that while you can list identities and filter by credential type (like username or email), there is currently no built-in way to filter identities by arbitrary traits directly via the API. Workarounds suggested include fetching all identities and filtering on the application side, or making parallel requests for known IDs, but these are not ideal for large datasets [Retrieve subset of identities through admin API](https://github.com/ory/network/issues/305).
q
@chilly-king-10285 how do I change a user's password via the API
b
A message from kapa.ai
To change a user's password via the API in Ory, you should use the Settings Flow with the
password
method. This is a self-service flow designed for end-users to update their own passwords. The flow can be initiated for both browser-based and API clients. For API clients (e.g., mobile apps, backend services): 1. Initialize the settings flow (authenticated as the user whose password you want to change). 2. Submit the new password using the flow's action URL and the
password
method. Example API call:
Copy code
bash curl -s -X POST -H "Accept: application/json" -H "Content-Type: application/json" \     -H "Authorization: bearer $sessionToken" \     -d '{"password": "newPassword123", "method": "password"}' \     "$actionUrl"
-
$sessionToken
is the user's session token. -
$actionUrl
is obtained from the initialized settings flow. - The payload must include the new password and set
"method": "password"
. Note: - This flow is intended for users to change their own passwords. There is no documented admin API endpoint to directly set or change another user's password after creation; password changes are handled through the self-service settings flow [Settings and profile updates](https://www.ory.sh/docs/kratos/self-service/flows/user-settings/) [Update password](https://www.ory.sh/docs/kratos/self-service/flows/user-settings/#update-password-1). If you need to reset a user's password as an admin (for example, if they forgot it), you should use the account recovery flow instead. If you need to import or set a password during identity creation or update, you can do so by providing the password in the credentials field, but this is not intended for regular password changes [Importing credentials](https://www.ory.sh/docs/kratos/manage-identities/import-user-accounts-identities/#importing-credentials).
q
@chilly-king-10285 how would I initiate this flow with
Copy code
export const ory = new FrontendApi(
  new Configuration({
    basePath: Config.getAuthBasePath(),
    baseOptions: {
      withCredentials: true,
    },
  }),
);
b
A message from kapa.ai
To initiate a settings flow (for example, to change a user's password) using the Ory JavaScript SDK and your
FrontendApi
instance, you should use the
createBrowserSettingsFlow
(for browser-based apps) or
createNativeSettingsFlow
(for native/mobile apps) method. These methods are the updated way to start a settings flow, as described in the SDK v1 upgrade guide [SDK V1 upgrade guide](https://www.ory.sh/docs/guides/upgrade/sdk-v1/#frontend-apis). Example for a browser-based app:
Copy code
js const flow = await ory.frontend.createBrowserSettingsFlow()   .then(({ data }) => data)
Example for a native app:
Copy code
js const flow = await ory.frontend.createNativeSettingsFlow()   .then(({ data }) => data)
After initializing the flow, you will receive a flow object containing the flow ID and the action URL. You can then use this information to submit the new password as described previously. References: - The method names and usage are confirmed in the [SDK V1 upgrade guide](https://www.ory.sh/docs/guides/upgrade/sdk-v1/#frontend-apis). - The flow for updating settings (including password) is described in the [settings flow documentation](https://www.ory.sh/docs/kratos/self-service/flows/user-settings/#user-and-profile-settings-for-server-side-browser-clients). If you need to fetch an existing flow (for example, after a redirect), use:
Copy code
js const flow = await ory.frontend.getSettingsFlow({ id: flowId })   .then(({ data }) => data)
This approach is fully supported by the Ory SDK and aligns with the documented flows.
q
@chilly-king-10285 I find the docs hard to follow. I created a settings flow with
Copy code
const flow = await ory.createBrowserSettingsFlow()
I get two nodes as a result of password group
Copy code
{
                "type": "input",
                "group": "password",
                "attributes": {
                    "name": "password",
                    "type": "password",
                    "required": true,
                    "autocomplete": "new-password",
                    "disabled": false,
                    "node_type": "input"
                },
                "messages": [],
                "meta": {
                    "label": {
                        "id": 1070001,
                        "text": "Password",
                        "type": "info"
                    }
                }
            },
            {
                "type": "input",
                "group": "password",
                "attributes": {
                    "name": "method",
                    "type": "submit",
                    "value": "password",
                    "disabled": false,
                    "node_type": "input"
                },
                "messages": [],
                "meta": {
                    "label": {
                        "id": 1070003,
                        "text": "Save",
                        "type": "info"
                    }
                }
            }
How do I reset the password now?
b
A message from kapa.ai
To reset the password after creating the settings flow and receiving the password nodes, you need to submit the form data to the
action
URL provided in the flow's
ui
object. The payload should include the new password and the method, as specified by the nodes. Here's how you can do it: 1. Extract the action URL and method from the flow: -
flow.ui.action
(the URL to POST to) -
flow.ui.method
(should be "POST") 2. Build the payload using the node attributes: - `"password"`: the new password you want to set - `"method"`: must be
"password"
3. Send the POST request:
Copy code
js await ory.updateSettingsFlow({   flow: flow.id,   updateSettingsFlowBody: {     password: "your-new-password",     method: "password"   } })
Or, if you are submitting directly to the action URL (for example, from a form):
Copy code
js fetch(flow.ui.action, {   method: flow.ui.method,   credentials: "include",   headers: {     "Content-Type": "application/json"   },   body: JSON.stringify({     password: "your-new-password",     method: "password"   }) })
Summary: - Use the
action
URL from the flow. - POST the new password and
"method": "password"
as the payload. This process is described in the [settings flow payloads documentation](https://www.ory.sh/docs/kratos/self-service/flows/user-settings/#settings-flow-payloads) and the [update password section](https://www.ory.sh/docs/kratos/self-service/flows/user-settings/#update-password-1). If you encounter validation errors (e.g., password too short), they will be returned in the flow's response, attached to the relevant node as messages [Update password](https://www.ory.sh/docs/kratos/self-service/flows/user-settings/#update-password-1).
q
@chilly-king-10285 I tried what you suggested and got this error back:
Copy code
{
  "error": {
    "id": "security_csrf_violation",
    "code": 403,
    "status": "Forbidden",
    "request": "8d739fa2-d7e8-96e2-9c74-91e84e9f2318",
    "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"
  }
}
b
A message from kapa.ai
The error message you received indicates a CSRF (Cross-Site Request Forgery) violation. According to the knowledge sources, this happens when the anti-CSRF cookie is present, but the CSRF token is either missing from the request body or does not match the cookie value. Ory requires both the CSRF cookie and the CSRF token to be sent and to match for security reasons. How to fix this: 1. Include the CSRF token in your request body. - The CSRF token is provided as a hidden input field in the flow's UI nodes, typically named
csrf_token
. - You must extract this value from the flow and include it in your payload when submitting the password change. 2. Example:
Copy code
js    await ory.updateSettingsFlow({      flow: flow.id,      updateSettingsFlowBody: {        password: "your-new-password",        method: "password",        csrf_token: csrfTokenFromUiNode // <-- this must be set!      }    })
Where
csrfTokenFromUiNode
is the value from the node with
name: "csrf_token"
in
flow.ui.nodes
. 3. Why this is necessary: Ory uses the synchronizer token pattern for CSRF protection. The value in the hidden input (
csrf_token
) must match the anti-CSRF cookie sent by the browser. If they do not match, or if the token is missing, you will get a 403 error [Defenses against cross-site request forgery](https://www.ory.sh/docs/kratos/concepts/security/#defenses-against-cross-site-request-forgery) [Custom UI CSRF handling](https://www.ory.sh/docs/kratos/bring-your-own-ui/custom-ui-basic-integration/#debug). 4. If you continue to get this error: - Try clearing your cookies for the domain and retrying the flow, as mismatched or stale cookies can also cause this error. - Make sure you are sending all cookies and the CSRF token together in the same request. References: - [Ory Kratos CSRF troubleshooting](https://www.ory.sh/docs/kratos/debug/csrf) - [Bring-your-own-UI CSRF handling](https://www.ory.sh/docs/kratos/bring-your-own-ui/custom-ui-basic-integration/#debug) - [Security concepts: CSRF](https://www.ory.sh/docs/kratos/concepts/security/#defenses-against-cross-site-request-forgery) Summary: You must extract the
csrf_token
from the flow's UI nodes and include it in your request body when submitting the password change. This is required for CSRF protection in Ory.
q
@chilly-king-10285 my fetch looks like this
Copy code
await fetch(data.ui.action, {
      method: data.ui.method,
      credentials: "include",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        password: newPassword,
        method: "password",
        csrf_token: csrfNode.attributes.node_type === 'input' && csrfNode.attributes.value,
      })
    })
but I get a 403
b
A message from kapa.ai
Your fetch code is almost correct, but the 403 CSRF error suggests that either the CSRF token is missing/incorrect, or the cookies are not being sent or do not match the token. Here are the key points to check, based on the knowledge sources: 1. CSRF Token Extraction: Make sure you are extracting the CSRF token from the correct node. The CSRF token is found in a node with
attributes.name === "csrf_token"
and
attributes.type === "hidden"
. Double-check that
csrfNode
is the correct node and that
csrfNode.attributes.value
is the actual token value. 2. Cookies: The request must include the session and CSRF cookies. Using
credentials: "include"
is correct for browser fetch, but ensure that the cookies are actually present in the browser for the domain you are calling. If you are running on localhost with Ory Tunnel, make sure the tunnel is set up correctly and both your app and Ory are on the same (sub)domain, as cookies are domain-specific [CSRF troubleshooting](https://www.ory.sh/docs/troubleshooting/csrf/). 3. Payload: The payload must include: - `password`: the new password - `method`: "password" - `csrf_token`: the value from the CSRF node Example:
Copy code
js    {      password: newPassword,      method: "password",      csrf_token: csrfNode.attributes.value    }
4. Clear Cookies and Retry: If you see the error "The HTTP Cookie Header was set and a CSRF token was sent but they do not match," clear your cookies for the domain and retry the flow, as stale or mismatched cookies can cause this [CSRF troubleshooting](https://www.ory.sh/docs/troubleshooting/csrf/). 5. Check Domain and Tunnel: If you are using Ory Tunnel, ensure your frontend and Ory are on the same domain (e.g., via the tunnel URL), as CORS and cookie issues can otherwise occur [Bring-your-own-ui CSRF debug](https://www.ory.sh/docs/kratos/bring-your-own-ui/custom-ui-basic-integration/#debug). Summary of what to check: - The CSRF token is correctly extracted and sent. - Cookies are present and sent with the request. - The frontend and Ory are on the same domain (especially in local dev). - If you get a mismatch error, clear cookies and retry the flow. If all of the above are correct and you still get a 403, it is likely a cookie or domain issue. Double-check your tunnel and browser cookie state. References: - [CSRF troubleshooting](https://www.ory.sh/docs/troubleshooting/csrf/) - [Bring-your-own-ui CSRF debug](https://www.ory.sh/docs/kratos/bring-your-own-ui/custom-ui-basic-integration/#debug)
q
@chilly-king-10285 how wouldl I use the ory client to setup 2FA?
b
A message from kapa.ai
To set up 2FA (two-factor authentication) using the Ory client, you need to enable and configure a second-factor method (such as TOTP, WebAuthn, SMS, or Lookup Secrets) in your Ory project, and then use the Ory client to initiate and complete the relevant self-service flows. General steps: 1. Enable 2FA methods in your Ory project configuration For example, to enable TOTP (Time-based One-Time Passwords), update your configuration:
Copy code
yaml    selfservice:      methods:        totp:          config:            issuer: <http://ExampleIssuer.com|ExampleIssuer.com>          enabled: true
You can do this via the Ory Console or CLI [Time-based one-time passwords (TOTP)](https://www.ory.sh/docs/kratos/mfa/totp/). 2. Initiate the settings flow using the Ory client In your application, use the Ory client to create a settings flow for the authenticated user:
Copy code
js    const flow = await ory.createBrowserSettingsFlow();
This flow will include nodes for enabling 2FA methods (e.g., TOTP setup) if they are enabled in your config. 3. Present the 2FA setup UI to the user For TOTP, the flow will include a QR code and a field to enter the code from the authenticator app. For WebAuthn, the flow will prompt for device registration. The UI nodes for these are included in the flow response [Settings and profile updates](https://www.ory.sh/docs/kratos/self-service/flows/user-settings/). 4. Submit the 2FA setup data using the Ory client When the user completes the 2FA setup (e.g., scans the QR code and enters the code), submit the data back to Ory using the flow’s action URL or the client’s update method:
Copy code
js    await ory.updateSettingsFlow({      flow: flow.id,      updateSettingsFlowBody: {        totp_code: "123456", // or the relevant field for your 2FA method        method: "totp"      }    });
Make sure to include the CSRF token if required. Supported 2FA methods: - TOTP (Authenticator apps) - WebAuthn (FIDO2, YubiKey, biometrics) - SMS/Email one-time codes - Lookup Secrets (backup codes) References: - [2FA Overview](https://www.ory.sh/docs/kratos/mfa/overview/) - [TOTP Setup](https://www.ory.sh/docs/kratos/mfa/totp/) - [WebAuthn Setup](https://www.ory.sh/docs/kratos/mfa/webauthn-fido-yubikey/) - [Settings Flow](https://www.ory.sh/docs/kratos/self-service/flows/user-settings/) If you need a code example for a specific 2FA method, let me know which one!
q
How do I 1. Enable 2FA methods in your Ory project configuration
@chilly-king-10285 how do I 1. Enable 2FA methods in your Ory project configuration
b
A message from kapa.ai
To enable 2FA (multi-factor authentication) methods in your Ory project configuration, you can use either the Ory Console or the Ory CLI. Here’s how you can do it for common 2FA methods: --- ### Using the Ory Console 1. Log in to the [Ory Console](https://console.ory.sh/). 2. Select your workspace and project. 3. Navigate to the Authentication tab. 4. Click on Two-factor auth in the sidebar. 5. Enable the desired 2FA methods (such as TOTP, WebAuthn, One-Time Codes, or Lookup Secrets) by toggling their respective switches and saving your changes. --- ### Using the Ory CLI 1. Download your current identity configuration:
Copy code
bash     ory get identity-config --project <project-id> --workspace <workspace-id> --format yaml > identity-config.yaml
2. Edit the configuration file to enable the desired 2FA methods. For example, to enable TOTP and Lookup Secrets:
Copy code
yaml     selfservice:       methods:         totp:           config:             issuer: <http://ExampleIssuer.com|ExampleIssuer.com>           enabled: true         lookup_secret:           enabled: true
3. Update your configuration:
Copy code
bash     ory update identity-config --project <project-id> --workspace <workspace-id> --file identity-config.yaml
--- You can enable other methods (like WebAuthn or One-Time Codes) in a similar way by setting their
enabled
property to
true
in the configuration file or toggling them in the Console. For more details and method-specific options, refer to the relevant sections in the Ory documentation [Multi-factor authentication](https://www.ory.sh/docs/identities/get-started/mfa/) [Time-based one-time passwords (TOTP)](https://www.ory.sh/docs/kratos/mfa/totp/) [WebAuthn and FIDO2 (YubiKey)](https://www.ory.sh/docs/kratos/mfa/webauthn-fido-yubikey/) [Lookup Secrets](https://www.ory.sh/docs/kratos/mfa/lookup-secrets/).
q
@chilly-king-10285 I would like to enable SMS/Email one-time codes so that users can optionally choose to have this extra layer of authentication. When I enable it in Authentication -> two factor auth -> one-time codes, it enforces the email code. How do I make it optional and let the user choose whether they want it and where do they want the code to be sent?
b
A message from kapa.ai
Based on the knowledge sources, when you enable SMS/Email one-time codes for multi-factor authentication (MFA) in Ory, the enforcement behavior depends on your project’s configuration—specifically, the
required_aal
(Authentication Assurance Level) setting for flows like settings or login. If you set
required_aal: highest_available
for a flow (such as the settings flow), Ory will require users who have a second factor configured to use it, but will not force users without a second factor to enroll. This means MFA is optional: users can choose to set up a second factor (like SMS/Email one-time codes) in their account settings, and only those who have set it up will be required to use it for higher-assurance actions. Users who have not set up a second factor can continue with just their primary authentication method. How to make one-time code MFA optional: 1. Enable one-time code MFA in the Ory Console under Authentication → Two-factor auth → One-time codes. 2. Set the flow’s
required_aal
to
highest_available
(not
aal2
), for example in the settings flow:
Copy code
yaml    selfservice:      flows:        settings:          required_aal: highest_available
This ensures that only users who have enrolled a second factor will be prompted for it, while others are not forced to enroll or use it [Account recovery and password reset configuration](https://www.ory.sh/docs/kratos/self-service/flows/account-recovery-password-reset/#configuration). 3. Let users enroll their preferred second factor (SMS or Email) in their account settings. The method (SMS or Email) is determined by your identity schema and which traits (email, phone) are available and configured for the user [SMS and Email 2FA](https://www.ory.sh/docs/kratos/mfa/mfa-via-sms/). Where is the code sent? - The code is sent to the trait (email or phone) that the user has configured and that is marked as an identifier for the
code
method in your identity schema. Users can only receive codes via channels (email or SMS) that are enabled and present in their identity. Summary: - Set
required_aal: highest_available
to make MFA optional. - Users can choose to enroll in SMS/Email one-time code MFA in their settings. - The code is sent to the email or phone number configured in the user’s identity schema. If you want users to choose between SMS or Email, ensure both are present and properly configured in your identity schema. The user will then be able to enroll the method they prefer [SMS and Email 2FA](https://www.ory.sh/docs/kratos/mfa/mfa-via-sms/). If you need more granular control (such as letting users pick between multiple available channels at login), the knowledge sources do not provide explicit details on customizing this selection UI or logic.
q
@chilly-king-10285 how do I change 2. Set the flow’s
required_aal
to
highest_available
(not
aal2
), for example in the settings flow:
b
A message from kapa.ai
To change the flow’s
required_aal
to
highest_available
(instead of
aal2
), you need to update your Ory project’s configuration for the relevant self-service flow (such as the settings flow). You can do this either via the Ory Console or the Ory CLI. Using the Ory Console: 1. Go to the [Ory Console](https://console.ory.sh/). 2. Select your project. 3. Navigate to AuthenticationSessions or the specific flow you want to configure (e.g., Settings). 4. Find the Authenticator Assurance Level (AAL) setting and set it to
highest_available
. 5. Save your changes. Using the Ory CLI: 1. Download your current configuration:
Copy code
bash    ory get identity-config --project <project-id> --workspace <workspace-id> --format yaml > identity-config.yaml
2. Edit the configuration file and set the desired flow’s
required_aal
to
highest_available
. For example:
Copy code
yaml    selfservice:      flows:        settings:          required_aal: highest_available
3. Upload the updated configuration:
Copy code
bash    ory update identity-config --project <project-id> --workspace <workspace-id> --file identity-config.yaml
This configuration ensures that only users who have set up a second factor will be prompted for it, making MFA optional for others [Step-up authentication](https://www.ory.sh/docs/kratos/mfa/step-up-authentication/) [Account recovery and password reset configuration](https://www.ory.sh/docs/kratos/self-service/flows/account-recovery-password-reset/#configuration).
q
@chilly-king-10285 I get this
Copy code
ory get identity-config 
The requested action was forbidden
I have the right ORY_PROJECT_API_KEY and ORY_SDK_URL configured
b
A message from kapa.ai
If you are receiving
The requested action was forbidden
when running
ory get identity-config
, even though you have set the correct
ORY_PROJECT_API_KEY
and
ORY_SDK_URL
, it likely means that your API key does not have the required permissions for this operation. According to the knowledge sources, there are two types of API keys in Ory Network: - Project API Keys: Used to manage project data (like identities). - Workspace API Keys: Used to manage project configuration (such as identity config). To get or update the identity configuration, you need a Workspace API Key, not a Project API Key. The Project API Key does not have sufficient permissions for configuration management operations like
ory get identity-config
 [Authorizing Ory Network Workspace Admin APIs](https://www.ory.sh/docs/concepts/personal-access-token/#authorizing-ory-network-workspace-admin-apis). What you should do: 1. Create a Workspace API Key in the Ory Console under Workspace settings → API Keys. 2. Set the environment variable:
Copy code
bash    export ORY_WORKSPACE_API_KEY=<your-workspace-api-key>
3. Run your command again (you do not need to set
ORY_SDK_URL
for this operation). Summary: You are getting this error because a Project API Key cannot be used to fetch or update project configuration. Use a Workspace API Key instead [Authorizing Ory Network Workspace Admin APIs](https://www.ory.sh/docs/concepts/personal-access-token/#authorizing-ory-network-workspace-admin-apis).
q
@chilly-king-10285 what are the possible values for required_aal and what do they mean?
b
A message from kapa.ai
The possible values for
required_aal
are: - aal1: Requires only one authentication factor (e.g., password). This is the basic level of authentication. - aal2: Requires two authentication factors (e.g., password + TOTP or another second factor). This enforces multi-factor authentication. - aal3: Represents an even higher level of assurance, typically involving hardware-backed authenticators or similar advanced methods. - highest_available: Enforces the highest Authenticator Assurance Level (AAL) that the user has configured. If the user has set up a second factor, it will be required; if not, only the first factor is required. This is the default in Ory Network for strict multi-factor authentication enforcement. A higher number means it is harder for an attacker to compromise the account. For more details, see the [Ory documentation on credentials and AAL](https://www.ory.sh/kratos/docs/concepts/credentials) and [step-up authentication](https://www.ory.sh/docs/kratos/mfa/step-up-authentication/) [Step-up authentication](https://www.ory.sh/docs/kratos/mfa/step-up-authentication/).
q
@chilly-king-10285 if I set it to aal1, can users decide wether they should login with password of password + TOTP?
b
A message from kapa.ai
If you set
required_aal
to
aal1
, users will only be required to authenticate with a single factor (such as a password or OIDC). Even if a user has configured a second factor (like TOTP), the system will not require them to use it for login or the relevant flow. The user will not be prompted for the second factor, and login with just the password will be sufficient. In other words, with
aal1
, users cannot choose to use both password and TOTP for a higher level of assurance during login—the system will only enforce the first factor. If you want users who have set up a second factor to be required to use it, you should use
highest_available
or
aal2
as the value for
required_aal
 [Step-up authentication](https://www.ory.sh/docs/kratos/mfa/step-up-authentication/) [Check AAL](https://www.ory.sh/docs/identities/get-started/mfa/#check-aal). Summary: - `aal1`: Only one factor is required, even if the user has set up a second factor. - Users cannot opt-in to use both password and TOTP at login if
aal1
is set.
q
@chilly-king-10285 I have required_aal: highest_available. If I enable One-Time Codes it forces users to login with email code after password authentication, why is that? Are all my users setup to have email 2fa? and how do I check that?
b
A message from kapa.ai
When you set
required_aal: highest_available
and enable One-Time Codes (email or SMS) for MFA, Ory will require users who have a second factor configured to use it. However, if you notice that all users are being forced to use an email code after password authentication—even those who have not explicitly enrolled in 2FA—this is likely due to how your identity schema and credential configuration are set up. Why is this happening? - If your identity schema marks the email trait as an identifier for the
code
credential (e.g.,
"credentials": { "code": { "identifier": true, "via": "email" } }
), then every user with an email address is considered to have the code credential available for MFA. - With
required_aal: highest_available
, Ory will prompt for the second factor (the email code) for all users who have this credential available, not just those who have explicitly enrolled in 2FA. Are all my users set up to have email 2FA? - If your schema is configured as above, then yes—all users with an email address are effectively set up to use email as a second factor, even if they did not explicitly enroll. This is because the system treats the presence of the email trait and the credential configuration as "MFA available" for those users [SMS and Email 2FA](https://www.ory.sh/docs/kratos/mfa/mfa-via-sms/). How do I check which users have email 2FA? - The knowledge sources do not provide a direct API or method to list which users have 2FA enabled for email codes. However, if your identity schema is set up to always provide the code credential via email, then all users with an email address are considered to have email 2FA available. - If you want only some users to have email 2FA, you need to adjust your schema so that the code credential is not always available, or use a different trait for the code credential that is only set when a user enrolls in 2FA. Summary: With your current configuration, all users with an email address are treated as having email 2FA available, which is why Ory enforces the second factor for everyone when
required_aal: highest_available
is set [SMS and Email 2FA](https://www.ory.sh/docs/kratos/mfa/mfa-via-sms/). If you want 2FA to be optional, you need to adjust your identity schema and credential configuration accordingly.
q
@chilly-king-10285 this is what my config looks like
Copy code
clients:
  web_hook:
    header_allowlist:
    - Accept
    - Accept-Encoding
    - Accept-Language
    - Content-Length
    - Content-Type
    - Origin
    - Priority
    - Referer
    - Sec-Ch-Ua
    - Sec-Ch-Ua-Mobile
    - Sec-Ch-Ua-Platform
    - Sec-Fetch-Dest
    - Sec-Fetch-Mode
    - Sec-Fetch-Site
    - Sec-Fetch-User
    - True-Client-Ip
    - User-Agent
    - X-Forwarded-Host
    - Ory-Base-Url-Rewrite
    - Ory-Base-Url-Rewrite-Token
    - X-Ory-Original-Host
    - Ory-No-Custom-Domain-Redirect
cookies:
  domain: <redacted>
  path: /
  same_site: Lax
courier:
  delivery_strategy: smtp
  smtp:
    connection_uri: <redacted>
    from_address: <redacted>
    from_name: <redacted>
    headers: {}
  templates:
    login_code:
      valid:
        email:
          body: {}
        sms:
          body: {}
    recovery:
      invalid:
        email:
          body: {}
      valid:
        email:
          body: {}
    recovery_code:
      invalid:
        email:
          body: {}
      valid:
        email:
          body: {}
    registration_code:
      valid:
        email:
          body: {}
        sms:
          body: {}
    verification:
      invalid:
        email:
          body: {}
      valid:
        email:
          body: {}
    verification_code:
      invalid:
        email:
          body: {}
      valid:
        email:
          body: {}
        sms:
          body: {}
feature_flags:
  cacheable_sessions: false
  cacheable_sessions_max_age: 2m30s
  password_profile_registration_node_group: password
identity:
  default_schema_id: <redacted>
  schemas: <redacted>
oauth2_provider:
  override_return_to: true
preview:
  default_read_consistency_level: strong
security:
  account_enumeration:
    mitigate: false
selfservice:
  allowed_return_urls: <redacted>
  default_browser_return_url: /ui/welcome
  flows:
    error:
      ui_url: <redacted>
    login:
      after:
        code:
          hooks: []
        default_browser_return_url: <redacted>
        hooks: []
        lookup_secret:
          hooks: []
        oidc:
          hooks: []
        passkey:
          hooks: []
        password:
          hooks: []
        saml:
          hooks: []
        totp:
          hooks: []
        webauthn:
          hooks: []
      before:
        hooks: []
      style: unified
      ui_url: <redacted>
    logout:
      after:
        default_browser_return_url: <redacted>
    recovery:
      after:
        default_browser_return_url: <redacted>
        hooks: []
      before:
        hooks: []
      enabled: true
      notify_unknown_recipients: false
      ui_url: <redacted>
      use: code
    registration:
      after:
        code:
          hooks:
          - hook: session
        default_browser_return_url: <redacted>
        hooks: []
        oidc:
          hooks:
          - hook: session
        passkey:
          hooks:
          - hook: session
        password:
          hooks:
          - hook: session
        saml:
          hooks:
          - hook: session
        webauthn:
          hooks:
          - hook: session
      before:
        hooks: []
      enable_legacy_one_step: true
      enabled: false
      login_hints: true
      style: unified
      ui_url: <redacted>
    settings:
      after:
        default_browser_return_url: <redacted>
        hooks: []
        lookup_secret:
          hooks: []
        oidc:
          hooks: []
        passkey:
          hooks: []
        password:
          hooks: []
        profile:
          hooks: []
        saml:
          hooks: []
        totp:
          hooks: []
        webauthn:
          hooks: []
      before:
        hooks: []
      privileged_session_max_age: 15m0s
      required_aal: highest_available
      ui_url: <redacted>
    verification:
      after:
        default_browser_return_url: <redacted>
        hooks: []
      before:
        hooks: []
      enabled: true
      notify_unknown_recipients: false
      ui_url: <redacted>
      use: code
  methods:
    b2b:
      config:
        organizations: []
    captcha:
      config:
        provider: cf-turnstile
      enabled: false
    code:
      config:
        missing_credential_fallback_enabled: true
      mfa_enabled: false
    link:
      config:
        base_url: <redacted>
      enabled: true
    lookup_secret: {}
    oidc:
      config:
        providers: []
      enabled: false
    passkey:
      config:
        rp:
          display_name: <redacted>
          id: <redacted>
          origins:
          - <redacted>
    password:
      config: {}
      enabled: true
    profile: {}
    totp:
      config:
        issuer: <redacted>
      enabled: true
    webauthn:
      config:
        passwordless: false
        rp:
          display_name: <redacted>
          id: <redacted>
          origins:
          - <redacted>
serve:
  admin:
    base_url: <redacted>
    request_log:
      disable_for_health: true
  public:
    base_url: <redacted>
    cors:
      enabled: false
    request_log:
      disable_for_health: true
session:
  cookie:
    domain: <redacted>
    name: <redacted>
    path: /
    same_site: Lax
  lifespan: 72h0m0s
  whoami:
    required_aal: highest_available
    tokenizer:
      templates: {}
I dont see "credentials": { "code": { "identifier": true, "via": "email" } }, so not sure why all users are enforced to login with email code. In the ory console, there's this warning in the on-time codes toggle
Copy code
Your configuration requires users to have a specific AAL level after logging in or when accessing self service settings. Enabling Enable one-time code MFA will force users to solve the MFA challenge before they are completely logged in or can access the self service settings.
b
A message from kapa.ai
Based on your configuration and the information from the knowledge sources, here’s what’s happening: - You have
required_aal: highest_available
set for both the settings flow and the session (
session.whoami.required_aal
). - In your
selfservice.methods.code
section, you have
mfa_enabled: false
, which should mean one-time code MFA is not enforced. However, you mentioned that in the Ory Console, you enabled "Enable one-time code MFA," and the warning appears. Key points from the knowledge sources: - When you enable one-time code MFA and set
required_aal: highest_available
, Ory will require users who have a second factor available to use it. If the system considers all users to have a second factor (for example, if the identity schema or configuration makes the code credential available to all users), then all users will be forced to use the code as MFA [SMS and Email 2FA](https://www.ory.sh/docs/kratos/mfa/mfa-via-sms/). - The warning in the Ory Console is expected: "Your configuration requires users to have a specific AAL level after logging in or when accessing self service settings. Enabling Enable one-time code MFA will force users to solve the MFA challenge before they are completely logged in or can access the self service settings." This means that, with your current settings, enabling one-time code MFA will enforce the MFA challenge for all users. Why is this happening even though you don’t see
credentials: { code: ... }
in your config?
- The knowledge sources indicate that if the code method is enabled and the required AAL is set to
highest_available
, Ory may treat all users as having the second factor available, depending on how the identity schema and code method are set up. If the code method is globally enabled, and the system can send a code to the user (e.g., via their email trait), it may consider the second factor available for all users [Github Issue #409](https://github.com/ory/network/issues/409). How to make one-time code MFA optional: - Set
mfa_enabled: false
for the code method (which you have already done). - If you want users to opt-in to MFA, you may need to adjust your identity schema or the way the code method is configured so that not all users are considered to have the second factor available. The knowledge sources do not provide a detailed step-by-step for this, but they do mention that the presence of the code credential (e.g., via email) can make Ory treat all users as MFA-enabled [Github Issue #409](https://github.com/ory/network/issues/409). Summary: With your current configuration and the Console toggle enabled, Ory enforces the MFA challenge for all users because it considers the second factor available to everyone. This is expected behavior given the warning in the Console and the way Ory handles the code method and AAL settings. If you want to make MFA optional, you may need to further adjust your schema or code method configuration, but the knowledge sources do not provide explicit instructions for this scenario.
q
@chilly-king-10285 I enabled totp and now my nodes look like this when calling
ory.createBrowserSettingsFlow()
Copy code
[
  {
    "type": "input",
    "group": "default",
    "attributes": {
      "name": "csrf_token",
      "type": "hidden",
      "value": "Dpu46kKZDJ/Vm+yXz0gZHgRYoF9/J2YvfeFN8X0WW6+MbUtEpL67E4d4Wey67lzH7BUZKqwoYkAn/YsUHCARxw==",
      "required": true,
      "disabled": false,
      "node_type": "input"
    },
    "messages": [],
    "meta": {}
  },
  {
    "type": "input",
    "group": "profile",
    "attributes": {
      "name": "traits.email",
      "type": "email",
      "value": "<mailto:paco@afternoon.co.uk|paco@afternoon.co.uk>",
      "required": true,
      "autocomplete": "email",
      "disabled": false,
      "node_type": "input"
    },
    "messages": [],
    "meta": {
      "label": {
        "id": 1070002,
        "text": "E-Mail",
        "type": "info",
        "context": {
          "title": "E-Mail"
        }
      }
    }
  },
  {
    "type": "input",
    "group": "profile",
    "attributes": {
      "name": "method",
      "type": "submit",
      "value": "profile",
      "disabled": false,
      "node_type": "input"
    },
    "messages": [],
    "meta": {
      "label": {
        "id": 1070003,
        "text": "Save",
        "type": "info"
      }
    }
  },
  {
    "type": "input",
    "group": "password",
    "attributes": {
      "name": "password",
      "type": "password",
      "required": true,
      "autocomplete": "new-password",
      "disabled": false,
      "node_type": "input"
    },
    "messages": [],
    "meta": {
      "label": {
        "id": 1070001,
        "text": "Password",
        "type": "info"
      }
    }
  },
  {
    "type": "input",
    "group": "password",
    "attributes": {
      "name": "method",
      "type": "submit",
      "value": "password",
      "disabled": false,
      "node_type": "input"
    },
    "messages": [],
    "meta": {
      "label": {
        "id": 1070003,
        "text": "Save",
        "type": "info"
      }
    }
  },
  {
    "type": "input",
    "group": "lookup_secret",
    "attributes": {
      "name": "lookup_secret_regenerate",
      "type": "submit",
      "value": "true",
      "disabled": false,
      "node_type": "input"
    },
    "messages": [],
    "meta": {
      "label": {
        "id": 1050008,
        "text": "Generate new backup recovery codes",
        "type": "info"
      }
    }
  },
  {
    "type": "img",
    "group": "totp",
    "attributes": {
      "src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAEAAAAAApiSv5AAAHMklEQVR4nOydwY7jOA8G//4x7//Ks7dODgRNhZ+dXVTVaTCxZHVSEAhKov78/fs/AfP/bw9AvosCwFEAOAoA58/rnz8/iQ6roPLVc//peX/nY8mQHvP0W8v/Rs4AcBQAjgLAUQA4f6r/PA+ezkOc855fvZwHRedhYx+49m3P33Ee3KV+I2cAOAoARwHgKACcMgh8sQnuztv2wV0flvVj6Xs+H8s0kKsC1/695+HgLgB3BoCjAHAUAI4CwLkIAu9js9jZt82Eb32L/rl+zNO2z+zWdAaAowBwFACOAsD5WhD4Ypqb65m2yOyqm4ah5zx9UMcZAI4CwFEAOAoA5yIIzIQkmxzZNLSa7h087+XF5vhG33YTQO5+I2cAOAoARwHgKACcMgjMZMv6nqf78DL/dz6W/rnNgvTmuerTHc4AcBQAjgLAUQA4b0Hg9ysGZvbNpU/z9vThW//eJ84EX+EMAEcB4CgAHAWA83OeyepJZ9+mb0tX1Ztm3+5bIs7k/zwdLC0KAEcB4CgAnIsg8O3B4yCm4rzn+xZ3p+Ob9vKttlUv8z2GzgBwFACOAsBRADhlEPjiieBkGgT2PfdjydzIkT6BfB6Ab84i1y2cAeAoABwFgKMAcH7SYd74xYv83+bT8xFMx7c5LDIdQc8nOwadAeAoABwFgKMAcMq7g6e3b/Rtz/NXT1TaO78xpGq7Wa6u3jG9dyQTmr7jDABHAeAoABwFgDMuFn0eGG56Se/wy9Qi7FtsKhVmjsl8gjMAHAWAowBwFADOajk4vdcvk8NLL7emA7RMjjGTgXQGwKMAcBQAjgLAucgEni8Rn2fVnjg2sunlRZ/rq57r39b30vc3fVv/f84AeBQAjgLAUQA4F3sC71um3JR+zhRKSVfuSwdyU3b1BJ0B4CgAHAWAowBwViViNpm7TdW/+04qp3OM/dsyLXahrjMAHAWAowBwFADOxbVx0+MM54FI+iTw9B3ni6f3hbpT7vxOnQHgKAAcBYCjAHDGmcD7rky77y6SKff95dP3bsLpflRXOAPAUQA4CgBHAeB8cDBkk4PKhH73nde97xhK36JiU3JmHpA6A8BRADgKAEcB4FxkAit2xYnbwSyyYP34zskEpD3pO0aqnvvnnAHwKAAcBYCjAHAu6gSehyQ9mWXUiidGes5918tNuQrPnQHgKAAcBYCjAHDKEjEvNveEZDKL5/2d91y9I7OkW/V8PqrNSeqrXpwB4CgAHAWAowBwyj2B6YXcTImYzTGUzZgzvfTh5X2lc8wESosCwFEAOAoAZ1wipmcTNk772xyF2OzmS4902kv6OTOBUqAAcBQAjgLAKfcEZi5Zq0jf5lGR2V+XLjmdPtFcYbFoOUYB4CgAHAWAc3Ew5O3BcKmWTKCUPtvcv23TX8WmmHVmAdkZAI8CwFEAOAoA5+JgSMWmdMmUzKVtmfCyf25T8Hn6TWbKadc4A8BRADgKAEcB4JR7Aqchyaa8zKYAckU6i5gpf92T2eXYH525whkAjgLAUQA4CgBnfG3cW5NIiegncnjP/kX9+J4o/fzJ8rIzABwFgKMAcBQAzsW1cT2bEOc815fJfU17yZRqOV+4nvYyDQyvfhlnADgKAEcB4CgAnPiNIZmbMe47m5vOqlW9bArrbA7guBwsxygAHAWAowBwPjgdnD4PW31acV8w1vdS8UTtwE0+cT4CZwA4CgBHAeAoAJzx6eDzDF+aTYmYzW7DzDsyC+bVcz1XgbAzABwFgKMAcBQAzsWewPMbKjIlUyo2RaD7PXfnbftdek8UhvF0sERQADgKAEcB4HxwOvitcWQ3X99f1fN9d4J860xwz51FuZ0B4CgAHAWAowBwxqeDM1X6ptnBdKGZ/tPpou19ZbL7gHT6XX2yUO8MAEcB4CgAHAWAc3F3cLpK3/S5TfHk87H0LTLVC6eks35X73AGgKMAcBQAjgLAuQgCK+5cnPz3jGVT5qUawdNFoKfPOQPAUQA4CgBHAeBc7Al8kcl9ZYqd9GzycNVYpu+4LzuYxiBQflEAOAoARwHgjOsEftD1l5Z50yeQ+7FU3FcJcNrLHGcAOAoARwHgKACccZ3AKX3BkswiZiaLmFmqPef8irj+ub7nCjOB8osCwFEAOAoApzwdnFmC3Zxp7Z/rR5pZ4J4GY+dt79sD+UkO1BkAjgLAUQA4CgCn3BOYuSMjs5BbDvqBHXnnBzS+v4vwk2/XGQCOAsBRADgKAGdcJzBD5gbdF5s84fS9m0/7CoTToPJ8sfiFxaKlRQHgKAAcBYDzSBC4CV2q56bh0Sa32ZMuKr0pnb3725wB4CgAHAWAowBwQncH923Pd9VNg7tpf/2oMkFWNZbzYx5PFJo2Eyi/KAAcBYCjAHDKIDBzTvi+07eZkKkaS798mx7fZrm64pOg0hkAjgLAUQA4CgDnxjqB8l/AGQCOAsBRADgKAEcB4PwTAAD//66no/ZJijN4AAAAAElFTkSuQmCC",
      "id": "totp_qr",
      "width": 256,
      "height": 256,
      "node_type": "img"
    },
    "messages": [],
    "meta": {
      "label": {
        "id": 1050005,
        "text": "Authenticator app QR code",
        "type": "info"
      }
    }
  },
  {
    "type": "text",
    "group": "totp",
    "attributes": {
      "text": {
        "id": 1050006,
        "text": "HWQDQP5QZQJQ4ZLG6FOMBX4SPMZBCWGG",
        "type": "info",
        "context": {
          "secret": "HWQDQP5QZQJQ4ZLG6FOMBX4SPMZBCWGG"
        }
      },
      "id": "totp_secret_key",
      "node_type": "text"
    },
    "messages": [],
    "meta": {
      "label": {
        "id": 1050017,
        "text": "This is your authenticator app secret. Use it if you can not scan the QR code.",
        "type": "info"
      }
    }
  },
  {
    "type": "input",
    "group": "totp",
    "attributes": {
      "name": "totp_code",
      "type": "text",
      "required": true,
      "disabled": false,
      "node_type": "input"
    },
    "messages": [],
    "meta": {
      "label": {
        "id": 1070006,
        "text": "Verify code",
        "type": "info"
      }
    }
  },
  {
    "type": "input",
    "group": "totp",
    "attributes": {
      "name": "method",
      "type": "submit",
      "value": "totp",
      "disabled": false,
      "node_type": "input"
    },
    "messages": [],
    "meta": {
      "label": {
        "id": 1070003,
        "text": "Save",
        "type": "info"
      }
    }
  }
]
Given that, how do I configure sms otp for this user
b
A message from kapa.ai
To configure SMS OTP (one-time code) for a user, you need to ensure two things: 1. Your identity schema must support SMS as a credential for the code method. 2. The user must have a phone number trait in their identity. ### 1. Identity Schema Configuration Your identity schema should include a phone number trait with the correct configuration for SMS OTP. Here’s an example from the knowledge sources:
Copy code
json {   "traits": {     "phone": {       "type": "string",       "format": "tel",       "<http://ory.sh/kratos|ory.sh/kratos>": {         "credentials": {           "code": {             "identifier": true,             "via": "sms"           }         },         "recovery": {           "via": "sms"         },         "verification": {           "via": "sms"         }       }     }   } }
This configuration ensures that the phone number can be used for SMS OTP, recovery, and verification flows ([Phone number and password](https://www.ory.sh/docs/kratos/manage-identities/customize-identity-schema/#phone-number-and-password)). ### 2. Enable SMS OTP in Ory - In the Ory Console, go to Authentication → Two-factor auth → One-time codes and enable it. - Make sure you have configured an SMS delivery provider under Authentication → SMS configuration ([Send SMS to your users](https://www.ory.sh/docs/kratos/emails-sms/sending-sms/)). ### 3. User Experience Once the above is set up: - When the user goes to their account settings (using the Experience UI or your custom UI), they should see an option to enroll SMS OTP if their identity has a phone number trait. - The UI nodes for SMS OTP will appear similarly to how TOTP nodes appear, but for the
code
method and referencing the phone number. ### 4. If you do not see SMS OTP nodes If you do not see the SMS OTP nodes in the settings flow: - Double-check that the user’s identity has a valid phone number trait. - Ensure your identity schema is configured as shown above. - Make sure the SMS channel is properly configured in your Ory project. Note: The knowledge sources do not provide a step-by-step UI screenshot for SMS OTP enrollment, but the process is analogous to TOTP: the user will be prompted to enter a code sent to their phone when enrolling or using SMS OTP ([Enable SMS one-time-code (OTP)](https://www.ory.sh/docs/kratos/passwordless/one-time-code/#enable-sms-one-time-code-otp)). --- Summary: - Update your identity schema to support SMS OTP. - Ensure the user has a phone number trait. - Enable and configure SMS OTP and an SMS provider in Ory. - The user will then be able to enroll SMS OTP via the settings flow. If you have done all of the above and still do not see the SMS OTP option, the knowledge sources do not provide further troubleshooting steps.
q
@chilly-king-10285 given the schema I shared with you, what kind of 2fa can I setup for the user?
b
A message from kapa.ai
Based on the configuration you shared, the following 2FA (two-factor authentication) methods are available for your users: - TOTP (Time-based One-Time Passwords): Your config has TOTP enabled (
totp.enabled: true
), and the settings flow nodes you shared include the TOTP setup (QR code, secret, and code input). This means users can enroll and use TOTP as a second factor [Time-based one-time passwords (TOTP)](https://www.ory.sh/docs/kratos/mfa/totp/). - Lookup Secrets (Backup Codes): The settings flow nodes include an option to generate backup recovery codes, which means users can set up and use lookup secrets as a 2FA fail-safe [Lookup Secrets - a MFA fail-safe](https://www.ory.sh/docs/kratos/mfa/lookup-secrets/). - Password: While not a second factor, password authentication is enabled and present in your flow. What is not available based on your config and nodes: - SMS/Email One-Time Codes: Although your config has the code method present,
mfa_enabled
is set to
false
for the code method, and your settings flow nodes do not show any UI for SMS or email one-time codes. Additionally, your identity schema (as shown in your config) does not include a phone number trait or code credential via SMS/email, so users cannot enroll in SMS or email OTP as a second factor [SMS and Email 2FA](https://www.ory.sh/docs/kratos/mfa/mfa-via-sms/). - WebAuthn (Passkeys, Security Keys): Your config has WebAuthn enabled, but your settings flow nodes do not show any WebAuthn enrollment options. This may be due to the identity schema or other project settings, but based on the nodes you provided, WebAuthn is not currently available for this user. Summary: With your current configuration and schema, users can set up TOTP and lookup secrets as 2FA methods. SMS/Email OTP and WebAuthn are not available for enrollment based on the nodes and schema you provided. If you want to enable additional 2FA methods, you will need to update your identity schema and configuration accordingly.
q
@chilly-king-10285 can I define different themes for UI ory experience and show a specific one depending on the subdomain?
b
A message from kapa.ai
Yes, you can define different themes and UI base URLs for the Ory Account Experience or your custom UI depending on the subdomain, using the Multibrand feature in Ory Network. With Multibrand, you can add multiple custom domains to your Ory project and assign a different custom UI base URL (and thus a different theme or branding) to each domain. This allows you to serve a unique user experience per subdomain or brand. For example, you can have: -
<http://ory.mufflers.com|ory.mufflers.com>
with its own theme and UI base URL -
<http://ory.carseats.com|ory.carseats.com>
with a different theme and UI base URL -
<http://ory.wipers.com|ory.wipers.com>
with yet another theme and UI base URL Each domain can have its own cookie domain and custom UI base URL, so users visiting different subdomains will see the corresponding theme and UI. You can configure this in the Ory Console under BrandingTheming and BrandingUI URLs for each custom domain [Configure Ory to use your UI: Multiple custom domains](https://www.ory.sh/docs/kratos/bring-your-own-ui/configure-ory-to-use-your-ui#multiple-custom-domains). > "With the Multibrand feature enabled for your workspace, you can add multiple custom domains to each Ory Network project. You can add a different custom UI base URL of each of the custom domains registered in the project. This allows for a high degree of flexibility, where each of the domains serves its own set of UI views that have a common path makeup but different base URL." > — [Configure Ory to use your UI: Multiple custom domains](https://www.ory.sh/docs/kratos/bring-your-own-ui/configure-ory-to-use-your-ui#multiple-custom-domains) If you are interested in enabling Multibrand, you may need to contact Ory for access, as noted in the documentation.
q
@chilly-king-10285 when I send an invite to my users they often end up clicking the link, leave and clicking it again. This results in a link already used error. Is it possiblet o configure Ory so that the link is valid until the user has set their password?
b
A message from kapa.ai
I'm sorry, but the knowledge sources do not contain explicit information about configuring Ory so that an invite (recovery) link remains valid until the user has set their password, regardless of how many times the link is clicked. The documentation states that recovery links (used for invites) are valid for a configurable period (e.g.,
expires_in: "12h"
), but it also notes that the link contains a token that is invalidated after use, which is why users see a "link already used" error if they click it again after completing the flow [Invite users](https://www.ory.sh/docs/kratos/manage-identities/invite-users/) [Magic links](https://www.ory.sh/docs/kratos/manage-identities/account-recovery/#magic-links). There is no mention in the knowledge sources of a configuration option to keep the link valid until the password is set, or to allow multiple uses of the same link. The current behavior is that the link is single-use and expires either after use or after the configured time period, whichever comes first. If this behavior is critical for your use case, you may need to implement a workaround, such as generating a new invite link if the user requests it again. However, the knowledge sources do not provide a built-in solution for this scenario.
q
@chilly-king-10285 my customer is not receiving email. When I looks at the delivery status I get the folowing gomail: could not send email 1: 554 Message rejected: Email address is not verified. The following identities failed the check in region EU-WEST-2: test@gmail.com
b
A message from kapa.ai
A message from kapa.ai
The error message you are seeing—`554 Message rejected: Email address is not verified. The following identities failed the check in region EU-WEST-2`—indicates that your SMTP provider is rejecting the email because the sender address (or possibly the recipient address) has not been verified with the provider. This is not an Ory-specific error, but rather an issue with your SMTP/email provider configuration. According to the Ory documentation, if you use a custom SMTP server, you must ensure that the sender address (
from_address
) is properly verified with your SMTP provider. Many providers (such as AWS SES, Mailgun, etc.) require you to verify sender identities before you can send emails from them [Use a custom server to send Ory Identity messages to users](https://www.ory.sh/docs/kratos/emails-sms/sending-emails-smtp). What you should do: - Log in to your SMTP/email provider's dashboard. - Verify the sender email address or domain you are using in your Ory configuration. - After verification, try sending the email again. If you are using the default Ory Network SMTP, this error should not occur unless you have switched to a custom SMTP server and the sender address is not verified. If you continue to have issues, check your SMTP provider's documentation for how to verify sender identities, as this is a common requirement for outbound email delivery [Use a custom server to send Ory Identity messages to users](https://www.ory.sh/docs/kratos/emails-sms/sending-emails-smtp).
The error message you are seeing—`554 Message rejected: Email address is not verified. The following identities failed the check in region EU-WEST-2`—indicates that your SMTP provider is rejecting the email because the sender address (or possibly the recipient address) has not been verified with the provider. According to the Ory documentation, when using a custom SMTP server, you must ensure that the sender address (
from_address
) is properly verified with your SMTP provider. Many providers require you to verify sender identities before you can send emails from them. If the sender address is not verified, the SMTP provider will reject the email, resulting in the error you are seeing [Use a custom server to send Ory Identity messages to users](https://www.ory.sh/docs/kratos/emails-sms/sending-emails-smtp). What you should do: - Log in to your SMTP/email provider's dashboard. - Verify the sender email address or domain you are using in your Ory configuration. - After verification, try sending the email again. If you are using the default Ory Network SMTP, this error should not occur unless you have switched to a custom SMTP server and the sender address is not verified. If you continue to have issues, check your SMTP provider's documentation for how to verify sender identities, as this is a common requirement for outbound email delivery.
q
@chilly-king-10285 how do I look what smtp server is configured for my ory instance?
b
A message from kapa.ai
To see which SMTP server is configured for your Ory instance, you need to check the
connection_uri
in your Ory project's identity configuration under the
courier.smtp
section. You can do this using the Ory CLI:
Copy code
bash ory get identity-config --project <project-id> --workspace <workspace-id> --format jsonpath="courier.smtp"
This command will output the SMTP configuration, including the
connection_uri
, which shows the SMTP server currently in use [Setting SMTP security settings](https://github.com/ory/network/issues/212). If you do not have access to the CLI or the required permissions, you can also view the SMTP configuration in the Ory Console under Authentication → Email configuration [Send emails using your SMTP server](https://www.ory.sh/docs/kratos/emails-sms/sending-emails-smtp).
q
@chilly-king-10285 where can I see my cookies expiry time?
b
A message from kapa.ai
You can see your Ory session cookie expiry time in two main ways: 1. Browser Developer Tools: When you log in through the browser, open your browser’s developer tools, go to the "Application" (Chrome) or "Storage" (Firefox) tab, and look under "Cookies" for your domain. There you will see the expiry time for each cookie, including the Ory session cookie. 2. Configuration Reference: The expiry time of the Ory session cookie is determined by your project’s session lifespan configuration. By default, the session cookie’s
max-age
is set to the session lifespan you configure. You can set this in your Ory configuration under
session.lifespan
. For example, if you set:
Copy code
yaml    session:      cookie:        domain: <http://your-domain.com|your-domain.com>        name: ory_session_{name}        path: /        persistent: false        same_site: Lax      lifespan: 720h
The cookie will expire after 720 hours (30 days). If
max-age
is not set, the browser deletes the cookie when the session ends or the browser is closed [Session lifespan](https://www.ory.sh/docs/kratos/session-management/session-lifespan). Summary: - Check the expiry in your browser’s developer tools for the actual value. - The configured expiry is set in your Ory project’s session lifespan setting. If you need to change the expiry, update the
session.lifespan
value in your Ory configuration.
q
@chilly-king-10285
b
Sorry @quiet-painting-32952, I'm not sure what you mean. Please try again. 👋
q
@chilly-king-10285 how do I configure the cookie expiry in ory console?
b
A message from kapa.ai
To configure the cookie expiry in the Ory Console, you need to set the session lifespan. The session cookie’s expiry (
max-age
) is determined by the session lifespan you configure. Steps: 1. Go to the [Ory Console](https://console.ory.sh/). 2. Navigate to your project. 3. Go to Session Settings. 4. Enter your desired session lifespan (for example,
720h
for 30 days). 5. Click Save. The session cookie will then expire according to the session lifespan you set. By default, the cookie’s
max-age
matches the session lifespan. If you want to further customize cookie behavior (such as domain, path, or SameSite), you can do so in the advanced configuration, but the expiry is always tied to the session lifespan [Session lifespan](https://www.ory.sh/docs/kratos/session-management/session-lifespan#configure-session-settings-in-ory-console). If you need to set a different cookie
max-age
than the session lifespan, you must set
session.cookie.persistent: false
in the configuration, but this is typically managed via the CLI or configuration file, not directly in the Console [Session lifespan](https://www.ory.sh/docs/kratos/session-management/session-lifespan). > Summary: > In the Ory Console, set the session lifespan under Session Settings to control the cookie expiry.
q
@chilly-king-10285 is it possible to invite a user with enforce MFA requirement but just for that user?
b
A message from kapa.ai
Based on the knowledge sources, Ory’s MFA (multi-factor authentication) enforcement is configured at the flow or project level using the
required_aal
setting (such as
aal1
,
aal2
, or
highest_available
). This means that MFA requirements are generally applied to all users or to all users who have a second factor configured, not to individual users only [Step-up authentication](https://www.ory.sh/docs/kratos/mfa/step-up-authentication/). There is no documented way in the knowledge sources to enforce MFA for just a single invited user while allowing others to log in without MFA. The system enforces MFA based on the configuration and the user’s enrolled factors, not on a per-user flag or invite. Summary: It is not possible, according to the knowledge sources, to invite a user and enforce MFA just for that user while keeping it optional or disabled for others. MFA enforcement is controlled at the flow or project level, not per user.
q
@chilly-king-10285 I use the ORY Account experience UI for the login page. When on the login page the url looks like this: https://auth.example.com/ui/login?flow=7940a394-9ddb-477f-a9cc-217e8dba62ea There's been a few cases where users bookmark that url so they can quickly access our website (including the flow). Next time the use the bookmark, since the flow is expired, they are shown this error:
Copy code
{
  "error": {
    "code": 403,
    "status": "Forbidden",
    "request": "b7f05762-f0ea-95d7-851a-63c7bc9d1508",
    "message": "Access credentials are not sufficient to access this resource"
  }
}
Is it possible to just redirect them to the login page with a new flow id when this happens?
c
A message from kapa.ai
The knowledge sources confirm that this is a known issue: when a user bookmarks a login URL containing a flow ID and later revisits it after the flow has expired, they encounter an error instead of being redirected to a fresh login flow. This behavior has been reported by other users as well, and the expected user experience would be to automatically redirect to a new flow or a more user-friendly page. Currently, the Ory Account Experience UI does not automatically redirect users to a new login flow when the bookmarked (and now expired) flow is accessed. Users see an error and must manually navigate to the login page to start a new flow. This limitation is acknowledged in Ory's issue tracker, and there is interest in improving the experience so that expired flows result in a transparent redirect to a new flow, but as of now, this is not the default behavior [If user sits on Account-Experience login page, they get a login flow expired error](https://github.com/ory/network/issues/417). Summary: - There is currently no built-in way in the Ory Account Experience UI to automatically redirect users to a new login flow if they access an expired flow via a bookmarked URL. - This is a known issue and may be improved in the future, but for now, users will see an error and need to manually navigate to the login page to start a new flow. If you require this behavior immediately, you would need to implement a custom UI that detects expired flows and programmatically redirects users to a new flow initialization endpoint.
q
@chilly-king-10285 Noticed something new. When the user clicks on their bookmakr, they're first redirected to https://auth.afternoon.co.uk/ui/welcome and then the error I shown above is displayed. Looks like there's a default behaviour to redirect to https://auth.afternoon.co.uk/ui/welcome, can this default uri redirection be changed?
c
A message from kapa.ai
Yes, the default URI redirection after a flow error (such as an expired flow) can be changed in your Ory configuration. The knowledge sources explain that the default redirect URL is controlled by the
selfservice.default_browser_return_url
setting, and you can also set a specific error UI URL using
selfservice.flows.error.ui_url
. If these are not set, users may end up on the default welcome page or see an error. To change the default redirection, update your configuration as follows:
Copy code
yaml selfservice:   default_browser_return_url: <https://your-app.com/dashboard>   flows:     error:       ui_url: <https://your-app.com/error>
You can also set these values using environment variables: -
SELFSERVICE_DEFAULT_BROWSER_RETURN_URL
-
SELFSERVICE_FLOWS_ERROR_UI_URL
This will ensure that, instead of being redirected to
/ui/welcome
, users are sent to your specified URL after an error or when a flow expires [Default return to](https://www.ory.sh/docs/kratos/fallback/default_return_to) [Error UI](https://www.ory.sh/docs/kratos/fallback/error). If you are using the Ory Console, you can configure these URLs in the relevant settings sections for redirects and error handling. Summary: Yes, you can change the default URI redirection by setting
selfservice.default_browser_return_url
and/or
selfservice.flows.error.ui_url
in your Ory configuration. This will override the default behavior of redirecting to
/ui/welcome
after a flow error.
q
@chilly-king-10285 how do I set the selfservice default_browser_return_url? Can this be achieved via the portal?
c
A message from kapa.ai
Yes, you can set the
selfservice.default_browser_return_url
via the Ory Console (portal). According to the documentation, this setting controls where users are redirected by default after completing self-service flows or when a flow expires. In the Ory Console, you can configure this under Browser Redirects. How to do it: 1. Go to the [Ory Console](https://console.ory.sh/). 2. Select your project. 3. Navigate to Browser Redirects. 4. Set the Default Redirect URL to your desired address. 5. Save your changes. This will update the
selfservice.default_browser_return_url
and control the default redirection behavior for your project [Default return to](https://www.ory.sh/docs/kratos/fallback/default_return_to).
q
@chilly-king-10285 can I change my environment from development to staging?
c
A message from kapa.ai
Based on the knowledge sources, you cannot change the environment of an existing Ory Network project from development to staging (or to any other environment). The environment (development, staging, production) is set when you create the project and cannot be changed afterwards. If you need a project in a different environment, you must create a new project with the desired environment setting [Create Ory Network projects](https://www.ory.sh/docs/migrate-to-ory#create-ory-network-projects) [API Reference: createProject](https://raw.githubusercontent.com/ory/docs/master/docs/reference/api.json). If you need to migrate configuration or data, you can export your configuration from the old project and import it into the new one using the Ory CLI [Ory Identities CLI](https://www.ory.sh/docs/guides/cli/identity-cli).
q
@chilly-king-10285 will the value of my cookie change during my session or stay the same
c
A message from kapa.ai
The value of your Ory session cookie can change during your session. According to the knowledge sources, the session can be updated and changed at any point in time, for example, when the user updates their profile or performs actions like refreshing the session or adding another authentication factor. When such changes occur, Ory may issue a new session cookie with updated information. This ensures that the session state remains consistent and secure [Session-management overview](https://www.ory.sh/docs/kratos/session-management/overview#json-web-token-jwt-support). So, while the session cookie may remain the same during periods of inactivity, it is possible and expected for its value to change if the session is refreshed or updated.
q
@chilly-king-10285 I'm trying to set a default redirect url for my development environment. My website is running on localhost:3000 but when I try to enter that in the Ory console for the browser redirect I get an error saying: The value must be a valid URL or path.
c
A message from kapa.ai
When setting a default redirect URL in the Ory Console, the value must be a valid URL with a scheme (e.g.,
http://
or
https://
). According to the knowledge sources,
<http://localhost:3000>
is considered a valid URL for local development, and it is supported by Ory for redirect purposes [Invalid URL](https://www.ory.sh/docs/concepts/redirects#troubleshooting). If you are seeing an error, double-check that you are entering the full URL, including the scheme (
http://
). For example:
Copy code
<http://localhost:3000>
If you are still encountering issues, it may be a temporary validation bug in the Ory Console UI. The knowledge sources also mention that there was a previous issue where the Console did not accept
localhost
as a valid redirect URI, but this has since been resolved [Ory Cloud OAuth2 Client error configuring localhost for redirect URI](https://github.com/ory/network/issues/282). Summary: - Make sure you enter the full URL:
<http://localhost:3000>
- The value must include the scheme (
http://
) - If the error persists, it may be a UI bug, as
localhost
URLs are supported for development. If you continue to have trouble, try using the Ory CLI to set the redirect URL, as this has been a reliable workaround in the past.
q
@chilly-king-10285 I setup social sign in with google. I'm able to go through the whole flow, however at the end of the flow it does a request to whoami with the acquare cookie, and gets a 401. What could be wrong?
c
A message from kapa.ai
A 401 response from the
/sessions/whoami
endpoint after completing the Google social sign-in flow typically means that the session cookie is missing, invalid, or not being sent correctly with the request. Based on the knowledge sources, here are the most common causes and troubleshooting steps: 1. Cookie Domain or Path Issues: If your frontend and Ory are not on the same domain (or subdomain), the browser may not send the session cookie with the request to
/sessions/whoami
. Make sure your Ory configuration sets the cookie domain appropriately so that cookies are shared between your app and Ory [Cookie settings](https://www.ory.sh/docs/kratos/guides/configuring-cookies) [Cookie-based security model](https://www.ory.sh/docs/security-model#http-cookies). 2. CORS and Credentials: If you are making AJAX requests from your frontend, ensure you are sending requests with
credentials: "include"
and that CORS is configured to allow credentials. Otherwise, cookies will not be sent with the request [CSRF troubleshooting](https://www.ory.sh/docs/troubleshooting/csrf#ory-oauth2) [Check session status](https://www.ory.sh/docs/identities/sign-in/check-session-token-cookie-api). 3. Session Not Persisted: If Ory Kratos is configured with
session.cookie.persistent: false
, the session may not persist across requests, especially after redirects. Setting
session.cookie.persistent: true
can resolve this issue [Github Issue #194](https://github.com/ory/network/issues/194). 4. Secrets Rotation or Mismatch: If the secrets used to encrypt cookies have changed or are not consistent, all cookies will be invalid and users will be signed out [Cookie settings](https://www.ory.sh/docs/kratos/guides/configuring-cookies). 5. Social Sign-In Redirect URI Issues: If the redirect URI used in your social sign-in provider does not match the one configured in Ory, the flow may not complete correctly, resulting in missing or invalid cookies [Social sign-in troubleshooting](https://www.ory.sh/docs/troubleshooting/troubleshooting-social-sign-in#redirect_uri-mismatch). What to check: - Ensure your frontend and Ory are on the same (sub)domain and the cookie domain is set correctly. - Use
credentials: "include"
in your frontend requests. - Check that
session.cookie.persistent
is enabled if you want persistent sessions. - Make sure your secrets have not changed unexpectedly. - Verify that the social sign-in redirect URI matches exactly. If you have checked all of the above and the issue persists, inspect the network requests in your browser’s developer tools to see if the session cookie is being set and sent as expected. If you need more targeted help, please provide details about your domain setup, cookie configuration, and how you are making the
/sessions/whoami
request.
q
@chilly-king-10285 I clicked the invitation link and was directed to the UI exprience registration screen. There I can either add a password or link social sign in. I cliked on google for social sign in and after completing the flow got this error: When reporting this error, please include the following information: ID:
b9ae853b-8576-4c24-9278-67e19b85bb2a
Time:
Wed, 01 Oct 2025 11:57:01 GMT
Message:
The request was initiated by someone else and has been blocked for security reasons. Please go back and try again.
c
A message from kapa.ai
The error message you encountered—"The request was initiated by someone else and has been blocked for security reasons"—typically indicates a security check failure, most likely related to CSRF (Cross-Site Request Forgery) or session state mismatch during the registration or social sign-in flow. Based on the knowledge sources, this can happen if: - The invitation (recovery) flow was started in one browser or device, but the social sign-in was completed in another, causing a mismatch in session or CSRF tokens. - The flow was started, then the user left the page or the flow expired, and then tried to continue or complete the flow after it was no longer valid. - Cookies or session data were cleared or blocked, breaking the link between the invitation flow and the social sign-in attempt. What you can do: - Make sure to complete the invitation and social sign-in flow in the same browser and device, without switching tabs, browsers, or devices. - Avoid refreshing the page or navigating away during the flow. - If you see this error, go back to the original invitation link and try the process again from the start. The knowledge sources do not provide a more detailed explanation or a specific configuration fix for this error, but it is consistent with security measures designed to prevent session hijacking or CSRF attacks [CSRF troubleshooting](https://www.ory.sh/docs/troubleshooting/csrf/). If the problem persists, it may be helpful to clear cookies and try again, or contact Ory support with the error ID for further investigation.
q
@chilly-king-10285 I fixed the issue above but now getting When reporting this error, please include the following information: ID:
8951d188-75ca-4d9a-9997-4181cb1efb1a
Time:
Wed, 01 Oct 2025 12:03:14 GMT
Message:
No active session was found in this request.
c
A message from kapa.ai
The error message
No active session was found in this request.
indicates that Ory could not find a valid session for your request. According to the knowledge sources, this typically happens when: - The session cookie is missing, invalid, or not being sent with the request. - The session has expired or was never established. - There is a domain or path mismatch preventing the cookie from being sent. - The flow was completed in a different browser, device, or incognito window, so the session is not available. What you can do: - Ensure you are completing the flow in the same browser and tab where you started it. - Make sure cookies are enabled and not being blocked by browser settings or extensions. - If you are running your app and Ory on different domains or ports, check that the cookie domain is configured correctly so the session cookie is sent with requests [Check session status](https://www.ory.sh/docs/identities/sign-in/check-session-token-cookie-api). - If the session has expired, restart the flow from the beginning by clicking the invitation link again. If the issue persists, inspect your browser’s developer tools to see if the session cookie is being set and sent with requests to Ory. If not, review your Ory cookie and domain configuration. The knowledge sources do not provide a more specific fix for this error, but it is a common symptom of session or cookie issues in Ory flows.
q
@chilly-king-10285 I fixed the issue above. No when I complete the flow I'm redirected a Ory UI to set my password. I'd like to just redirect the user to my app instead
c
A message from kapa.ai
To redirect the user to your app after completing the flow (instead of showing the Ory UI to set a password), you should configure the post-registration or post-verification redirect URLs in your Ory project. You can do this in two ways: 1. Set the
return_to
or
after_verification_return_to
query parameter
when initializing the registration flow. For example:
Copy code
https://<your-ory-project>/self-service/registration/browser?return_to=<https://your-app.com/dashboard>
Or, if you want to control where the user is sent after email verification:
Copy code
https://<your-ory-project>/self-service/registration/browser?after_verification_return_to=<https://your-app.com/dashboard>
This will redirect the user to your specified URL after the flow is completed, instead of the default Ory UI [User Registration Documentation](https://www.ory.sh/docs/kratos/self-service/flows/user-registration) [Post-verification redirection](https://www.ory.sh/docs/kratos/concepts/browser-redirect-flow-completion#post-verification-redirection). 2. Set the default redirect URL in the Ory Console: - Go to the [Ory Console](https://console.ory.sh/). - Navigate to your project. - Go to Browser Redirects. - Set the Default Redirect or Post-Registration Redirect to your app’s URL (e.g., `https://your-app.com/dashboard`). - Save your changes. This will ensure that, unless overridden by a query parameter, users are redirected to your app after completing the flow [Default return to](https://www.ory.sh/docs/kratos/fallback/default_return_to). Note: If you want to skip the password setup entirely for users who register via social sign-in, make sure your registration flow and hooks are configured to issue a session and redirect immediately after successful social sign-in, rather than prompting for a password. If you need more granular control, you can also use the Ory Actions or webhooks to implement custom logic after registration, but the above methods are the standard way to control post-flow redirection in Ory. If you need to redirect after verification (e.g., after clicking a link in an email), use the
after_verification_return_to
parameter as described above [Post-verification redirection](https://www.ory.sh/docs/kratos/concepts/browser-redirect-flow-completion#post-verification-redirection). If you have set these and still see the Ory UI, double-check that your redirect URLs are allow-listed in your Ory project settings [Advanced redirects](https://www.ory.sh/docs/kratos/bring-your-own-ui/custom-ui-advanced-integration).
q
@chilly-king-10285 now I get the error: Could not update settings: Requested return_to URL "https://portal.staging.afternoon.co.uk" is not allowed.
c
A message from kapa.ai
The error message: > Requested return_to URL "https://portal.staging.afternoon.co.uk" is not allowed. means that the URL you are trying to redirect to after the flow is not in your project's allow list of return URLs. Ory enforces this allow list to prevent open redirect attacks. How to fix: You need to add
<https://portal.staging.afternoon.co.uk>
to your project's allowed return URLs. To do this: 1. Go to the [Ory Console](https://console.ory.sh/). 2. Select your project. 3. Navigate to Browser Redirects or the section for Allowed Return URLs. 4. Add
<https://portal.staging.afternoon.co.uk>
to the list. 5. Save your changes. After this, Ory will allow redirection to that URL. This requirement is described in the documentation: > Because Ory Identities prevents Open Redirect Attacks, you need to whitelist the domain in your Ory Identities config when using the
?return_to=
query parameter. For other return urls specified inside the configuration it isn't necessary to add the domain to the whitelist. [Redirection configuration](https://www.ory.sh/docs/kratos/concepts/browser-redirect-flow-completion#redirection) If you do not add the URL to the allow list, Ory will block the redirect and show the error you encountered.
q
@chilly-king-10285 the Ory UI experience login screen is very flaky when running with playwright, is this a known issue?
c
A message from kapa.ai
I'm sorry, but the knowledge sources do not contain any explicit information about issues with the Ory Account Experience UI login screen being flaky when running with Playwright. There is no mention of Playwright-specific problems or test automation flakiness in the provided documentation or issue reports. If you are experiencing instability, it may be related to how Playwright handles browser sessions, cookies, or CSRF tokens, but this is not addressed in the knowledge sources.
q
@chilly-king-10285 I've setup social sign in for microsoft. My app registration is set to account in any direcoty and personal accounts. When I try to do the oauth flow I get the following error: Sorry, but we’re having trouble signing you in. AADSTS50020: User account 'cicciobello12@hotmail.com' from identity provider 'live.com' does not exist in tenant 'Default Directory' and cannot access the application 'c3cc98e1-8be6-482c-9bc4-910f2e33f5c7'(Afternoon) in that tenant. The account needs to be added as an external user in the tenant first. Sign out and sign in again with a different Azure Active Directory user account.
c
A message from kapa.ai
The error message you are seeing: > AADSTS50020: User account '<cicciobello12@hotmail.com>' from identity provider 'live.com' does not exist in tenant 'Default Directory' and cannot access the application ... The account needs to be added as an external user in the tenant first. indicates that the Microsoft account you are trying to use does not exist in the Azure AD tenant that your application is registered in, and the application is not accessible to this user. Based on the Ory documentation, when configuring Microsoft as a social sign-in provider, you must carefully set the Tenant field in your Ory provider configuration to control which users can sign in: - If you want to allow both work/school and personal Microsoft accounts, you should set the tenant to
common
. - If you want to allow only users from your organization, set the tenant to your Directory (tenant) ID or your organization's domain. From the error, it appears your app registration may not be set up to allow personal accounts, or the tenant value in your Ory configuration is not set to
common
. Double-check your Ory provider configuration and ensure you have:
Copy code
yaml microsoft_tenant: common
and that your Azure app registration is set to allow "Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) and personal Microsoft accounts (e.g. Skype, Xbox)" as described in the Ory documentation [Selecting a Tenant](https://www.ory.sh/docs/kratos/social-signin/microsoft#selecting-a-tenant). If you have already set
microsoft_tenant: common
and are still seeing this error, ensure that your Azure app registration is correctly configured to allow both organizational and personal accounts, and that the redirect URI matches what is configured in Ory [Microsoft Social Sign-In](https://www.ory.sh/docs/kratos/social-signin/microsoft). Summary: - Set
microsoft_tenant: common
in your Ory provider config. - Ensure your Azure app registration allows both organizational and personal accounts. - Make sure the redirect URI is correct. If these are set correctly and the issue persists, the knowledge sources do not provide further troubleshooting steps for this specific Microsoft error.
q
@chilly-king-10285 in the configuration it asks gives me the subject source option between Userinfo and Me, What options should I choose?
c
A message from kapa.ai
When configuring Microsoft as a social sign-in provider in Ory, the subject source determines which unique identifier is used for the user. You have two main options: - userinfo: Uses the
sub
field from the OIDC
id_token
or the standard OIDC
/userinfo
endpoint. This is the default and standard way to identify users in most OIDC flows. - me: Uses the
id
field returned by the
<https://graph.microsoft.com/v1.0/me>
endpoint, or the
oid
(Object ID) field. This is useful if your legacy system or integration expects the Microsoft Graph
id
or
oid
as the user identifier. Which should you choose? - Use userinfo if you want to stick with the standard OIDC subject identifier, which is compatible with most OIDC providers and applications. - Use me if you are migrating from a system that uses the Microsoft Graph
id
or
oid
as the user’s unique identifier, or if you specifically need to match users based on those fields. If you choose
me
, you must also add the
<https://graph.microsoft.com/User.Read>
scope to your configuration, as this is required to access the Microsoft Graph
/me
endpoint [Subject identifier source](https://www.ory.sh/docs/kratos/social-signin/microsoft#subject-identifier-source). Example configuration:
Copy code
yaml providers:   - id: microsoft     ...     subject_source: me # or userinfo     scope:       - <https://graph.microsoft.com/User.Read> # Required when using 'me'     ...
Summary: - Choose userinfo for standard OIDC compatibility. - Choose me if you need to use the Microsoft Graph
id
or
oid
as the subject identifier, and add the required scope. For more details, see the [Ory documentation on subject identifier source for Microsoft](https://www.ory.sh/docs/kratos/social-signin/microsoft#subject-identifier-source).
q
@chilly-king-10285 can I enforce Single sign on for only certain accounts?
c
A message from kapa.ai
Based on the knowledge sources, Ory does not currently support enforcing Single Sign-On (SSO) for only certain accounts or users. SSO enforcement, like MFA enforcement, is configured at the flow or project level (for example, via
required_aal
or SSO connection settings), and not on a per-user basis. The documentation and configuration examples show that SSO is enabled or required for all users matching certain criteria (such as email domain or organization), but there is no documented way to selectively enforce SSO for individual accounts while allowing others to use different authentication methods [See it live](https://www.ory.sh/docs/kratos/organizations#see-it-live) [Step-up authentication](https://www.ory.sh/docs/kratos/mfa/step-up-authentication/). Summary: You cannot enforce SSO for only certain accounts; SSO enforcement is managed at the project or organizational level, not per user. If you need more granular control, such as enforcing SSO for specific users only, this is not currently supported according to the available documentation.
q
@chilly-king-10285 My app has customers that are grouped into organisations. One of the organisations would like to enforce SSO to all members of that organisation (i.e a subset of all my users). How can I achieve that?
c
A message from kapa.ai
You can achieve SSO enforcement for all members of a specific organization using Ory’s Organizations feature. Here’s how it works: - In Ory, organizations allow you to group users within a project. Each organization can have its own SSO (OIDC or SAML) connections. - When an organization is configured with SSO and associated with one or more email domains, any user registering or logging in with an email address from that domain will be required to use the organization’s SSO connection. The login screen will show a Sign in with SSO button instead of the password field for those users. Users outside the organization (with other email domains) will not see this option and can use other authentication methods as configured for your project. Example flow: - You configure an organization in Ory and associate it with the customer’s domain (e.g.,
@customer.com
). - You set up the SSO connection (OIDC or SAML) for that organization. - When a user with an email like
<mailto:user@customer.com|user@customer.com>
tries to register or log in, they are required to use SSO. - Other users (not in that organization) are not affected and can use other login methods. This approach enforces SSO only for members of the specified organization, as requested [See it live](https://www.ory.sh/docs/kratos/organizations#see-it-live) [B2B Single Sign-On & SAML](https://www.ory.sh/docs/kratos/organizations). If you need to support multiple organizations with different SSO requirements, you can configure each organization separately with its own SSO connections and associated domains.
q
@chilly-king-10285 My app has customers that are grouped into organisations. One of the organisations would like to enforce social sign in to all members of that organisation (i.e a subset of all my users). How can I achieve that?
c
A message from kapa.ai
You can enforce social sign-in (such as Google, Microsoft, etc.) for all members of a specific organization in Ory by using the Organizations feature. Here’s how it works according to the knowledge sources: - Organizations in Ory allow you to group users and associate each organization with one or more domains (e.g.,
@customer.com
). - You can configure each organization to have its own SSO or social sign-in connections. - When a user attempts to register or log in with an email address that matches an organization's domain, Ory will require them to use one of the organization's configured SSO or social sign-in providers. The login screen will show a Sign in with SSO (or the relevant social provider) button instead of the password field for those users. Users outside the organization (with other email domains) will not see this option and can use other authentication methods as configured for your project. Example flow: - Configure an organization in Ory and associate it with the customer’s domain (e.g.,
@customer.com
). - Set up the desired social sign-in provider(s) for that organization. - When a user with an email like
<mailto:user@customer.com|user@customer.com>
tries to register or log in, they are required to use the configured social sign-in. - Other users (not in that organization) are not affected and can use other login methods. This setup enforces social sign-in only for members of the specified organization, as requested [See it live](https://www.ory.sh/docs/kratos/organizations#see-it-live) [B2B Single Sign-On & SAML](https://www.ory.sh/docs/kratos/organizations). If you need to support multiple organizations with different social sign-in requirements, you can configure each organization separately with its own providers and associated domains.
q
@chilly-king-10285 is there another way to achieve this without organisations? These are avaialble only in the Growth tier which is much more expensive
c
A message from kapa.ai
I'm sorry, but the knowledge sources do not describe an alternative way to enforce social sign-in (or SSO) for only a subset of users (such as members of a specific customer group) without using the Organizations feature. The documented approach for enforcing SSO or social sign-in for specific groups is through Organizations, which, as you noted, is only available in the Growth tier [B2B Single Sign-On & SAML](https://www.ory.sh/docs/kratos/organizations). There is no mention in the knowledge sources of a built-in method to enforce authentication method restrictions for subsets of users based on traits like email domain or group membership outside of the Organizations feature. If you need this functionality and cannot use Organizations, the knowledge sources do not provide a supported workaround.
q
@chilly-king-10285 when I set my password in my development ory instance I get the error: 1. Requested return_to URL "http://localhost:5173" is not allowed.
c
A message from kapa.ai
The error message: > Requested return_to URL "http://localhost:5173" is not allowed. means that the URL you are trying to redirect to after setting your password is not in your project's allow list of return URLs. Ory enforces this allow list to prevent open redirect attacks. How to fix: You need to add
<http://localhost:5173>
to your project's allowed return URLs. To do this: 1. Go to the [Ory Console](https://console.ory.sh/). 2. Select your project. 3. Navigate to Browser Redirects or the section for Allowed Return URLs. 4. Add
<http://localhost:5173>
to the list. 5. Save your changes. After this, Ory will allow redirection to that URL. This requirement is described in the documentation: > Because Ory Identities prevents Open Redirect Attacks, you need to whitelist the domain in your Ory Identities config when using the
?return_to=
query parameter. For other return urls specified inside the configuration it isn't necessary to add the domain to the whitelist [Redirection configuration](https://www.ory.sh/docs/kratos/concepts/browser-redirect-flow-completion#redirection). If you do not add the URL to the allow list, Ory will block the redirect and show the error you encountered.
q
@chilly-king-10285 can I disable a user\s password programmatically?
c
A message from kapa.ai
Yes, you can disable a user's password programmatically in Ory by deleting the password credential for that identity using the Admin API. According to the knowledge sources, you can use the following endpoint:
Copy code
DELETE /admin/identities/{id}/credentials/password
This API call deletes the password credential for the specified identity, effectively disabling password-based login for that user. Note that you cannot delete passkeys or code auth credentials through this API [Delete a credential for a specific identity](https://raw.githubusercontent.com/ory/kratos/master/spec/api.json). Summary: You can programmatically disable a user's password by deleting their password credential via the Admin API.
q
can I programmatically check if someone has Single Sign on setup?
@chilly-king-10285 can I programmatically check if someone has Single Sign on setup?
c
A message from kapa.ai
The knowledge sources do not explicitly describe a direct API or method to programmatically check if a user has Single Sign-On (SSO) set up. While you can retrieve an identity’s credentials and see which types (e.g.,
oidc
for social sign-in) are present, there is no documented, built-in endpoint or flag that specifically indicates "this user has SSO enabled" in a single call. You can, however, fetch an identity’s details and inspect the
credentials
field to see if there are
oidc
(OpenID Connect) or other SSO-related credentials associated with the user. For example, using the Admin API:
Copy code
bash curl --request GET \   --header "Authorization: Bearer {ORY_API_KEY}" \   'https://$<http://PROJECT_SLUG.projects.oryapis.com/admin/identities/<identity_id|PROJECT_SLUG.projects.oryapis.com/admin/identities/<identity_id>>'
In the response, if you see an
oidc
credential under the
credentials
object, it indicates that the user has set up SSO via an OIDC provider [Credentials](https://www.ory.sh/docs/kratos/concepts/credentials). Summary: - There is no single API call that returns "SSO enabled: true/false" for a user. - You can check the presence of
oidc
credentials in the user’s identity object to infer if SSO is set up. - The knowledge sources do not provide a more direct or specialized method for this check.
q
@chilly-king-10285 I'm getting 429 on the POST [/self-service/login page
c
A message from kapa.ai
A
429
error on the
POST /self-service/login
page means you are hitting a rate limit for login attempts. Ory enforces both project-level and endpoint-based rate limits to protect against abuse and brute-force attacks. This can happen if there are too many login attempts in a short period, either from the same IP, user, or globally for your project. What you can do: - Wait and retry: The rate limit is temporary. Wait for a minute or two and try again. - Check your plan’s rate limits: Development and staging environments have much lower rate limits than production. For example, in the Developer plan, the default is 5 requests per second and 150 per minute for most endpoints, including login [Project rate limits](https://www.ory.sh/docs/guides/rate-limits#rate-limit-tables-by-subscription-plan). - Reduce automated or repeated login attempts: Automated tests or scripts can quickly exhaust the rate limit. - Upgrade your plan: Higher plans (Production, Growth, Enterprise) have higher rate limits. If you need more capacity, consider upgrading [Project rate limits](https://www.ory.sh/docs/guides/rate-limits#rate-limit-tables-by-subscription-plan). - For Enterprise/Growth: You can request IP whitelisting for trusted sources to get higher limits for those IPs [IP whitelisting](https://www.ory.sh/docs/guides/rate-limits#configuration-and-management). Summary: You are receiving a 429 because you have exceeded the allowed number of login requests. This is expected behavior to prevent abuse. Wait and try again, reduce the frequency of login attempts, or consider upgrading your plan if you need higher limits. For more details, see the [Ory rate limiting documentation](https://www.ory.sh/docs/guides/rate-limits).
q
@chilly-king-10285 I'm getting 1. "Too many API requests from your IP have been registered." for the login endpoint. Can I undo this from the console?
c
A message from kapa.ai
No, you cannot manually undo or reset rate limiting for your IP from the Ory Console. According to the knowledge sources, rate limits are enforced automatically by Ory to protect against abuse and brute-force attacks. When you hit the rate limit (such as "Too many API requests from your IP have been registered."), you must wait for the rate limit window to expire before making more requests. There is no option in the Ory Console to clear or reset these limits [Understand Ory Network rate limiting](https://www.ory.sh/docs/guides/rate-limits). If you are on the Enterprise or Growth plan, you can request IP whitelisting for trusted sources to get higher limits, but this also requires contacting Ory support and cannot be done instantly from the Console [Configuration and management](https://www.ory.sh/docs/guides/rate-limits#configuration-and-management). Summary: You must wait for the rate limit to reset; there is no way to manually undo it from the Ory Console.