Skip to content

feat(embedded-auth): Add POST /e/authorize Email OTP flow - #1292

Merged
NandanPrabhu merged 11 commits into
v4-developmentfrom
feat/embedded-auth-authorize
Sep 30, 2026
Merged

NandanPrabhu merged 11 commits into
v4-developmentfrom
feat/embedded-auth-authorize

Conversation

@NandanPrabhu

@NandanPrabhu NandanPrabhu commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Changes

This PR adds the interactive Embedded Authorization loop (POST /e/authorize, Email OTP delivery) and unifies it with the existing discovery client. Discovery and the authorize loop are now a single client: one EmbeddedAuth protocol, one Auth0EmbeddedAuth implementation, and one embeddedAuth(...) factory handle both GET /e/discovery and POST /e/authorize.

API added to EmbeddedAuth

  • authorize(connection:capabilities:scope:audience:) / authorize(connection:) — starts the multi-step flow; connection is required (omitting it yields invalid_request server-side)
  • identify(_:) — submits the user's email address as the identifier and identifierType
  • challengeEmail(index:) — triggers email OTP delivery for the given next-array index
  • verifyOtp(_:type:) — submits the OTP (type: .oob for email/SMS, .totp for authenticator) and, on success, internally exchanges the authorization code for Credentials and returns them directly; callers never handle the raw code, code_verifier, or redirect_uri

Demo app (App/)

Full end-to-end SwiftUI flow across iOS, macOS, and tvOS:

Screen Triggered by
Start "Start Embedded Auth" button calls authorize(connection:)
Discover "Discover Login Options" button calls discover() and lists LoginOption values
Identify Email server nextActions: [identifyEmail] → email TextField → identify(_:)
Challenge Email server nextActions: [challengeEmail] → masked destination shown → challengeEmail(index:)
Verify OTP server nextActions: [verifyOTP] → OTP TextField → verifyOtp(_:type:)
Success credentials (token type, scope, expiry)
Error wrong-OTP inline retry; terminal errors with "Try Again"

Checklist

  • New/changed behaviour covered by tests
  • No force-unwraps in library source
  • auth_session / authorization_code / otp redacted in logs; never exposed to callers
  • accessToken / idToken / refreshToken never logged
  • Both callback and async throws APIs provided
  • DocC comments on all public members
  • SwiftLint passes
  • Demo app builds on iOS, macOS, tvOS

@NandanPrabhu
NandanPrabhu requested a review from a team as a code owner September 24, 2026 04:24
@coderabbitai

coderabbitai Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository: auth0/Auth0.swift/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: b07dbaf6-7541-40c2-a13d-7f7e492e3746

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@NandanPrabhu
NandanPrabhu marked this pull request as draft September 24, 2026 05:24
@NandanPrabhu
NandanPrabhu force-pushed the feat/embedded-auth-authorize branch from d439050 to a12fe54 Compare September 24, 2026 06:38
@NandanPrabhu
NandanPrabhu force-pushed the feat/embedded-auth-discovery branch 3 times, most recently from 89d0d25 to c29c983 Compare September 24, 2026 09:58
Base automatically changed from feat/embedded-auth-discovery to v4-development September 24, 2026 10:13
@NandanPrabhu
NandanPrabhu force-pushed the feat/embedded-auth-authorize branch from a12fe54 to 2c2517f Compare September 25, 2026 06:59
@NandanPrabhu
NandanPrabhu marked this pull request as ready for review September 25, 2026 08:11
@NandanPrabhu NandanPrabhu changed the title feat(embedded-auth): implement POST /e/authorize client with Email OTP flow feat(embedded-auth): add POST /e/authorize Email OTP flow in a unified EmbeddedAuth client Sep 25, 2026
@NandanPrabhu NandanPrabhu changed the title feat(embedded-auth): add POST /e/authorize Email OTP flow in a unified EmbeddedAuth client feat(embedded-auth): Add POST /e/authorize Email OTP flow Sep 25, 2026
@NandanPrabhu
NandanPrabhu force-pushed the feat/embedded-auth-authorize branch 3 times, most recently from 7df360a to 1483a56 Compare September 28, 2026 03:31
Comment thread Auth0/EmbeddedAuth/Auth0EmbeddedAuth.swift Outdated
Comment thread Auth0/EmbeddedAuth/Auth0EmbeddedAuth.swift Outdated
Comment thread Auth0/EmbeddedAuth/EmbeddedAuthHandlers.swift Outdated
Comment thread Auth0/EmbeddedAuth/EmbeddedAuthHandlers.swift Outdated
Comment thread Auth0/EmbeddedAuth/Auth0EmbeddedAuth.swift Outdated
Comment thread Auth0/EmbeddedAuth/Auth0EmbeddedAuth.swift Outdated
Comment thread Auth0/EmbeddedAuth/Auth0EmbeddedAuth.swift Outdated
@NandanPrabhu
NandanPrabhu force-pushed the feat/embedded-auth-authorize branch from 1483a56 to 7dc6725 Compare September 28, 2026 10:03
Implements the Embedded Login Discovery API (ROAD-5978 milestone 1).

- Auth0.embeddedAuth() factory (explicit + plist-sourced overloads)
- EmbeddedAuth protocol with discover(connection:) returning Request<DiscoveryResult, EmbeddedAuthError>
- DiscoveryResult with typed LoginOption enum covering all 6 known grant types plus .unknown for forward-compatibility
- Lenient decoding: unrecognized grant_type values surface as .unknown rather than throwing
- EmbeddedAuthError with isFeatureDisabled / isInvalidRequest / isInvalidClient helpers
- 43 Quick/Nimble tests covering all grant types, query params, error paths, and async API
… nextActions, isTooManyAttempts, isTooManyLogins to EmbeddedAuthError
@NandanPrabhu
NandanPrabhu force-pushed the feat/embedded-auth-authorize branch from 0b507a6 to 55d25ab Compare September 29, 2026 06:20
Comment thread Auth0/EmbeddedAuth/Auth0EmbeddedAuth.swift
Comment thread Auth0/EmbeddedAuth/EmbeddedAuthError.swift Outdated
Comment thread Auth0/EmbeddedAuth/EmbeddedAuthHandlers.swift
Comment thread Auth0/EmbeddedAuth/EmbeddedAuthHandlers.swift
Comment thread Auth0/EmbeddedAuth/EmbeddedAuthHandlers.swift
Comment thread Auth0/EmbeddedAuth/Auth0EmbeddedAuth.swift Outdated
Comment thread examples/embedded-auth.md
…sitive data redaction, API surface

- Remove redundant raw values from OtpType (redundant_string_enum_value lint)
- Fix colon spacing in identifyEmail/identifyPhone/verifyOtp body dicts (colon lint)
- Guard .keyboardType/.autocapitalization/.numberPad with #if !os(macOS) in ContentView
- Remove challengeEmail(index:) — parameter was silently dropped; no-arg overload is the API
- Add auth_session, authorization_code, otp to SensitiveDataRedactor.sensitiveKeys
- Fix stale "Discovery API" doc on EmbeddedAuthError to "Authentication API"
- Remove dead capturedBody(from:) test helper
@NandanPrabhu
NandanPrabhu force-pushed the feat/embedded-auth-authorize branch 2 times, most recently from 07f397f to eec046f Compare September 30, 2026 05:10
…thorization_code response

Add AuthorizationCodeResponse Decodable wire type and use JSONDecoder in
decodeAuthorizationCodeResponse. Also clear session on decode failure (200
without authorization_code is a terminal error — the flow cannot resume).
@NandanPrabhu
NandanPrabhu force-pushed the feat/embedded-auth-authorize branch from eec046f to 5917a45 Compare September 30, 2026 05:16
Comment thread examples/embedded-auth.md Outdated
@NandanPrabhu
NandanPrabhu force-pushed the feat/embedded-auth-authorize branch 2 times, most recently from 9cfcf15 to f2df198 Compare September 30, 2026 06:37
Comment thread Auth0/EmbeddedAuth/EmbeddedAuthError.swift Outdated
Comment thread Auth0/EmbeddedAuth/EmbeddedAuthError.swift Outdated
Comment thread Auth0/EmbeddedAuth/EmbeddedAuthError.swift Outdated

@sanchitmehtagit sanchitmehtagit 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.

Does this PR have any breaking changes if yes we should start the migration guide too

Comment thread Auth0/Request.swift
Comment thread Auth0/EmbeddedAuth/EmbeddedAuthError.swift
Comment thread Auth0/EmbeddedAuth/EmbeddedAuthError.swift
Comment thread App/OAuth2.entitlements Outdated
@NandanPrabhu
NandanPrabhu force-pushed the feat/embedded-auth-authorize branch from ed90dca to b45432f Compare September 30, 2026 07:44
@NandanPrabhu

Copy link
Copy Markdown
Contributor Author

Does this PR have any breaking changes if yes we should start the migration guide too

right now. It doesnot

if error.isInsufficientAuthorization, let newSession = error.info["auth_session"] as? String {
currentSession = newSession
} else if !error.isRetryable {
} else if error.isAccessDenied || error.isTooManyAttempts || error.isTooManyLogins {

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.

could we have a function that wraps this ..

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.

instead of making changes here that function can be modified in future if needed

@NandanPrabhu
NandanPrabhu merged commit 46900c1 into v4-development Sep 30, 2026
16 of 19 checks passed
@NandanPrabhu
NandanPrabhu deleted the feat/embedded-auth-authorize branch September 30, 2026 09:33
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.

3 participants