ory / kratos

Next-gen identity server replacing your Auth0, Okta, Firebase with hardened security and PassKeys, SMS, OIDC, Social Sign In, MFA, FIDO, TOTP and OTP, WebAuthn, passwordless and much more. Golang, headless, API-first. Available as a worry-free SaaS with the fairest pricing on the market!

Home Page:https://www.ory.sh/kratos/?utm_source=github&utm_medium=banner&utm_campaign=kratos

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Kratos generates broken redirects to AAL2 login flows if identity has both SMS and another 2FA method

MichaelMarner opened this issue · comments

Preflight checklist

Ory Network Project

No response

Describe the bug

If an identity is configured for SMS 2FA, and also has another 2FA method configured, such as TOTP, then any redirects to an AAL2 login flow generated by Kratos are broken, as they do not include a via request parameter.

Reproducing the bug

  1. Configure an identity schema with a phone verifiable phone number
  2. Configure Kratos to enable SMS based 2FA
  3. Configure Kratos to use highest_available on whoami, settings, or other self service flows
  4. Log into Kratos
  5. In a settings flow, add a phone number to the account, complete the verification process
  6. In a settings flow, add TOTP to the account
  7. Log out
  8. Attempt to log in with email/password

At this point, Kratos will redirect the client:

{
    "error": {
        "id": "browser_location_change_required",
        "code": 422,
        "status": "Unprocessable Entity",
        "reason": "In order to complete this flow please redirect the browser to: http://127.0.0.1:4433/self-service/login/browser?aal=aal2",
        "message": "browser location change required"
    },
    "redirect_browser_to": "http://127.0.0.1:4433/self-service/login/browser?aal=aal2"
}

However, navigating to the URL provided will result in an error screen, with the following error:

{
  "id": "ff1cb352-2137-40e9-8eb5-04f4c74ffdd1",
  "error": {
    "code": 400,
    "reason": "AAL2 login via code requires the `via` query parameter",
    "status": "Bad Request",
    "message": "The request was malformed or contained invalid parameters"
  },
  "created_at": "2024-03-07T01:53:18.011166Z",
  "updated_at": "2024-03-07T01:53:18.011166Z"
}

Note: I've focused on the login redirect here, but equivalent broken redirects are generated when making other calls, such as to whoami.

Relevant log output

No response

Relevant configuration

Kratos.yml:


version: 1.1.0
session:
  whoami:
    required_aal: highest_available
  methods:
    password:
      enabled: true
    totp:
      config:
        issuer: My Cool Business
      enabled: true
    lookup_secret:
      enabled: true
    code:
      enabled: true
      mfa_enabled: true


Identity Schema:


{
  "$id": "https://schemas.ory.sh/presets/kratos/quickstart/email-password/identity.schema.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Person",
  "type": "object",
  "properties": {
    "traits": {
      "type": "object",
      "properties": {
        "email": {
          "type": "string",
          "format": "email",
          "title": "E-Mail",
          "minLength": 3,
          "ory.sh/kratos": {
            "credentials": {
              "password": {
                "identifier": true
              }
            },
            "verification": {
              "via": "email"
            },
            "recovery": {
              "via": "email"
            }
          }
        },
        "phone": {
          "title": "Phone Number",
          "type": "string",
          "format": "tel",
          "ory.sh/kratos": {
            "credentials": {
              "password": {
                "identifier": true
              }
            },
            "verification": {
              "via": "sms"
            }
          }
        },
        "name": {
          "type": "object",
          "properties": {
            "first": {
              "title": "First Name",
              "type": "string"
            },
            "last": {
              "title": "Last Name",
              "type": "string"
            }
          }
        }
      },
      "required": ["email"],
      "additionalProperties": false
    }
  }
}

Version

1.1.0

On which operating system are you observing this issue?

macOS

In which environment are you deploying?

Docker

Additional Context

It feels like the via= request parameter isn't really the right approach to start an AAL2 login flow - it requires the client to know too much about how Kratos is configured, and requires the client to have information about the identity that is not possible to know (ie what 2FA approaches are enabled on the account). It makes the client very brittle and at risk of breaking if any Kratos configuration changes.

I think Kratos needs another step to the login flow that generates a UI presenting all the ways the user can complete AAL2 authentication, allowing the user to select "use Authenticator app" or "send an SMS". Kratos could be configured to have a default or preferred option.

This matches what other services tend to do. For example Github I have TOTP and phone number configured. When I login, Github asked for my TOTP code by default, but also gives me the option to authenticate with an SMS or recovery code.