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!
https://www.ory.sh/kratos/?utm_source=github&utm_medium=banner&utm_campaign=kratos
Apache License 2.0
10.99k stars 949 forks source link

Using highest_available AAL does not work with SMS based 2FA #3801

Open MichaelMarner opened 5 months ago

MichaelMarner commented 5 months ago

Preflight checklist

Ory Network Project

No response

Describe the bug

Kratos does not enforce aal2 for flows configured for highest_available AAL when using SMS based 2FA.

When using other 2FA methods, Kratos will require AAL2 if 2FA is configured on the identity. For example, setting whoami to highest available:

  whoami:
    required_aal: highest_available

An identity that has TOTP based 2FA configured will not be able to access whoami without an AAL2 session. A call to whoami will redirect the client to a new aal2 login flow, eg:

{
    "error": {
        "id": "session_aal2_required",
        "code": 403,
        "status": "Forbidden",
        "reason": "An active session was found but it does not fulfill the requested Authenticator Assurance Level. Please verify yourself with a second factor to resolve this issue.",
        "details": {
            "redirect_browser_to": "http://127.0.0.1:4433/self-service/login/browser?aal=aal2"
        },
        "message": "Session does not fulfill the requested Authenticator Assurance Level"
    }
}

However, this enforcement of AAL2 does not happen when using SMS based 2FA. whoami responds with a 200 when a session is aal1, even though the identity has a verified phone number and Kratos is configured to use SMS for 2FA.

Reproducing the bug

  1. Configure identity schema with a phone number to be used for 2FA
       "phone": {
          "title": "Mobile Number",
          "type": "string",
          "format": "tel",
          "ory.sh/kratos": {
            "credentials": {
              "password": {
                "identifier": true
              }
            },
            "verification": {
              "via": "sms"
            }
          }
  1. Configure Kratos for SMS based 2FA (relevant sections of Kratos.yml shown)
session:
  whoami:
    required_aal: highest_available

methods:
    code:
      enabled: true
      mfa_enabled: true

courier:
  (omitted, but configured to send SMS)
  1. Log in through Kratos.
  2. In a settings flow, add the user's phone number
  3. Complete the verification process
  4. Log out
  5. Log in with email/password
  6. Call whoami

I would expect that, given the user has a valid 2FA method on their account, that the call to whoami would fail, as the highest_available AAL should be AAL2. However, Kratos works as if the user only has AAL1.

Other flows like settings behave in the same way. It is possible to change a password, generate recovery codes, etc. all at AAL1, which defeats the purpose of configuring SMS based 2FA. This also does not match how Kratos works with other 2FA methods.

Relevant log output

No response

Relevant configuration

No response

Version

1.1.0

On which operating system are you observing this issue?

macOS

In which environment are you deploying?

Docker

Additional Context

No response

jonas-jonas commented 3 months ago

Yes, that is a known limitation of the current implementation. We didn't consider SMS a full MFA method (due to the nature of SMS, and other factors), so the current implementation is more of a workaround to achieve an AAL2 session, rather than a drop-in replacement/full alternative for the other MFA methods.

However, I agree that this leaves room for improvement here, and contributions are welcome.

mapepro commented 3 weeks ago

Hello, I would like to know if any improvements are planned regarding this functionality. From what I understand (but I might be mistaken) of the current design, the SMS 2FA relies on the code workflow and thus allows upgrading the session from AAL1 to AAL2, but it does not set the highest_available level to AAL2 for the account. Are there any drafts or ongoing work on this issue? I would be happy to contribute to this improvement if needed.

aeneasr commented 2 weeks ago

We are actively working on improving htis. No timelines on the open source release though.