Skip to content

feat: passwordless support - #153

Merged
rmad17 merged 23 commits into
mainfrom
feat/passwordless-support
Aug 19, 2026
Merged

feat: passwordless support#153
rmad17 merged 23 commits into
mainfrom
feat/passwordless-support

Conversation

@rmad17

@rmad17 rmad17 commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Changes

Added

  • Adds ServerClient.passwordless for embedded passwordless flows: Email OTP, SMS OTP (via /passwordless/start + the passwordless OTP token grant), and Email Magic Link (SDK-owned state/redirect_uri, transaction
    storage for callback completion).
  • Creates server-side sessions after successful OTP verification and magic-link callback completion, reusing the shared _persist_session_from_token_response path (issuer/audience/session-expiry checks already
    enforced there, not new in this PR).
  • Handles mfa_required during passwordless OTP verification; MFA can be completed into a new SDK session via mfa.verify(..., persist=True). Known limitation, not yet fixed: this MFA-initiated session-creation
    path does not run organization-claim validation, unlike every other session-creating path in the SDK. Flagging for reviewer visibility — no organization-scoped passwordless/MFA usage should ship until this is
    closed.
  • Adds typed passwordless option models (StartPasswordlessEmailOptions, StartPasswordlessSmsOptions, VerifyPasswordlessOtpOptions) and passwordless-specific typed errors (PasswordlessStartError,
    PasswordlessVerifyError), including retry_after (from Retry-After), raw non-JSON error body capture (truncated), and 429 → too_many_requests mapping.
  • Enforces E.164 validation for SMS phone numbers.
  • Adds safeguards so magic-link callers cannot override SDK-owned protocol values (redirect_uri, response_type, state); supports caller-supplied scope on magic link, re-injecting openid when omitted.
  • Removes organization support from passwordless start/verify. The field existed but always failed in practice — the server ignores it on this grant, and the SDK's own claim validation then hard-raised on the
    missing claim. Removed rather than fixed, since there was no working path to preserve. Flag if organization on passwordless was already relied on anywhere.
  • Fixes session sid sourcing for all interactive logins, not just passwordless — complete_interactive_login previously fell back to a random sid whenever user_info was absent, even when the ID token carried a sid
    claim. It now prefers the ID token's sid claim, then user_info, then random. This affects every existing interactive-login session, since OIDC back-channel logout matches by sid and previously could silently
    fail to target sessions created this way.
  • Adds Passwordless documentation (examples/Passwordless.md) and README links.

Testing

This has been tested for the following flows

# Flow MFA Configuration Result
1 Email OTP No MFA ✅ Pass
2 Email OTP Global MFA ✅ Pass
3 Email OTP Step Up MFA ✅ Pass
4 SMS OTP No MFA ✅ Pass
5 SMS OTP Global MFA ✅ Pass
6 SMS OTP Step Up MFA ✅ Pass
7 Magic Link No MFA ✅ Pass
8 Magic Link Global MFA ✅ Pass
9 Magic Link Step Up MFA ✅ Pass
  • This change adds unit test coverage
  • This change adds integration test coverage
  • This change has been tested on the latest version of the platform/language or why not

Checklist

@rmad17
rmad17 requested a review from a team as a code owner August 8, 2026 05:33

def __init__(self, code: str, message: str, cause=None, retry_after: Optional[int] = None):
super().__init__(code, message, cause, retry_after)
self.name = "PasswordlessStartError"

def __init__(self, code: str, message: str, cause=None, retry_after: Optional[int] = None):
super().__init__(code, message, cause, retry_after)
self.name = "PasswordlessVerifyError"
Piyush-85
Piyush-85 previously approved these changes Aug 12, 2026

@Piyush-85 Piyush-85 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed it async with @rmad17, LGTM

feat: MFA support in passwordless
Comment thread src/auth0_server_python/auth_server/server_client.py Outdated
Comment thread src/auth0_server_python/auth_server/server_client.py Outdated
Comment thread src/auth0_server_python/auth_types/__init__.py Outdated
Comment thread src/auth0_server_python/auth_types/__init__.py Outdated
Comment thread src/auth0_server_python/auth_types/__init__.py Outdated
Comment thread src/auth0_server_python/auth_types/__init__.py Outdated
Comment thread src/auth0_server_python/auth_server/server_client.py Outdated
Comment thread src/auth0_server_python/tests/test_passwordless_client.py
Comment thread src/auth0_server_python/tests/test_passwordless_client.py
Comment thread src/auth0_server_python/auth_types/__init__.py Outdated
Comment thread src/auth0_server_python/auth_types/__init__.py Outdated
Comment thread src/auth0_server_python/tests/test_passwordless_client.py Outdated
Comment thread src/auth0_server_python/tests/test_passwordless_client.py Outdated
Comment thread examples/Passwordless.md Outdated
Comment thread examples/Passwordless.md Outdated
Comment thread examples/Passwordless.md Outdated

@kishore7snehil kishore7snehil left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@rmad17
rmad17 merged commit 75920ab into main Aug 19, 2026
9 checks passed
@rmad17
rmad17 deleted the feat/passwordless-support branch August 19, 2026 13:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants