feat: add Passwordless OTP for database connections#1585
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds a native-only passwordless OTP flow for database connections across shared types, native bridge layers, platform adapters, Android and iOS implementations, example screens, and documentation. Native dependency versions were also updated. ChangesPasswordless OTP Feature
Estimated code review effort: 4 (Complex) | ~60 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration. 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
src/types/common.ts (1)
46-51: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAvoid
anyin the index signature.
[key: string]: anydisables type checking for every extra property on this object, includingauthSessionnarrowing at call sites. Preferunknownto preserve the opaque/extensible intent while keeping type safety; consumers can narrow if they need to inspect a specific key. As per coding guidelines, "Avoid usinganytypes; use strict TypeScript typing instead."♻️ Proposed fix
export type PasswordlessChallenge = { /** The opaque auth session token used to complete the OTP login. */ authSession: string; /** Allows for additional, non-standard properties returned from the server. */ - [key: string]: any; + [key: string]: unknown; };🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/types/common.ts` around lines 46 - 51, Replace the `PasswordlessChallenge` index signature’s `any` with `unknown` so extra server-returned properties remain extensible without disabling type safety. Update the `[key: string]: any` member in `PasswordlessChallenge` to use `unknown`, and keep `authSession` unchanged so callers can still narrow specific optional keys when needed.Source: Coding guidelines
src/platforms/native/bridge/__tests__/NativeBridgeManager.spec.ts (1)
479-502: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd an error-wrapping test for
passwordlessChallengeWithPhoneNumber.Unlike the sibling
passwordlessChallengeWithEmailandpasswordlessLoginWithOTPsuites, this block doesn't verify that a native rejection is wrapped inAuthError.As per coding guidelines: "All test files must maintain minimum 80% code coverage."
✅ Suggested additional test
it('forwards all parameters including delivery method to the native module', async () => { ... }); + + it('wraps a native error in an AuthError', async () => { + MockedAuth0NativeModule.passwordlessChallengeWithPhoneNumber.mockRejectedValue({ + code: 'a0.passwordless.challenge_failed', + message: 'boom', + }); + + await expect( + bridge.passwordlessChallengeWithPhoneNumber( + '+15555550123', + 'Username-Password-Authentication', + 'voice', + true + ) + ).rejects.toThrow(AuthError); + }); });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/platforms/native/bridge/__tests__/NativeBridgeManager.spec.ts` around lines 479 - 502, Add a rejection-path test for passwordlessChallengeWithPhoneNumber in NativeBridgeManager.spec.ts: mirror the existing passwordlessChallengeWithEmail/passwordlessLoginWithOTP error-wrapping coverage by making MockedAuth0NativeModule.passwordlessChallengeWithPhoneNumber reject and asserting bridge.passwordlessChallengeWithPhoneNumber throws an AuthError. Keep the current success-path parameter-forwarding test, and ensure the new test verifies the native error is wrapped rather than returned directly.Source: Coding guidelines
src/platforms/native/bridge/INativeBridge.ts (1)
293-313: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider reusing the shared
PasswordlessChallengetype.Both challenge methods return an anonymous
{ authSession: string }object, butPasswordlessChallenge(insrc/types/common.ts) already models this exact shape and includes the extensible index signature. Reusing it here keeps bridge, adapter, and public-facing types aligned.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/platforms/native/bridge/INativeBridge.ts` around lines 293 - 313, Both passwordless challenge methods in INativeBridge currently return an inline { authSession: string } shape instead of the shared PasswordlessChallenge type. Update passwordlessChallengeWithEmail and passwordlessChallengeWithPhoneNumber to return PasswordlessChallenge from src/types/common.ts so the bridge stays aligned with the adapter and public API types while preserving the extensible index signature.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/platforms/native/adapters/NativePasswordlessClient.ts`:
- Around line 18-51: Add JSDoc comments to the public API methods in
NativePasswordlessClient: challengeWithEmail, challengeWithPhoneNumber, and
loginWithOTP. Document each method’s purpose and key parameters/return value so
the class methods conform to the public API documentation guideline without
changing their behavior.
In `@src/platforms/web/adapters/__tests__/WebPasswordlessClient.spec.ts`:
- Around line 11-27: The test cases in WebPasswordlessClient.spec.ts are calling
challengeWithEmail and challengeWithPhoneNumber without the required connection
field, which breaks strict TypeScript checks. Update the
client.challengeWithEmail and client.challengeWithPhoneNumber calls to pass a
valid connection string alongside email/phoneNumber so the test inputs match
PasswordlessChallengeEmailParameters and PasswordlessChallengePhoneParameters.
Keep the assertions unchanged; just fix the parameter objects used in these two
tests.
---
Nitpick comments:
In `@src/platforms/native/bridge/__tests__/NativeBridgeManager.spec.ts`:
- Around line 479-502: Add a rejection-path test for
passwordlessChallengeWithPhoneNumber in NativeBridgeManager.spec.ts: mirror the
existing passwordlessChallengeWithEmail/passwordlessLoginWithOTP error-wrapping
coverage by making MockedAuth0NativeModule.passwordlessChallengeWithPhoneNumber
reject and asserting bridge.passwordlessChallengeWithPhoneNumber throws an
AuthError. Keep the current success-path parameter-forwarding test, and ensure
the new test verifies the native error is wrapped rather than returned directly.
In `@src/platforms/native/bridge/INativeBridge.ts`:
- Around line 293-313: Both passwordless challenge methods in INativeBridge
currently return an inline { authSession: string } shape instead of the shared
PasswordlessChallenge type. Update passwordlessChallengeWithEmail and
passwordlessChallengeWithPhoneNumber to return PasswordlessChallenge from
src/types/common.ts so the bridge stays aligned with the adapter and public API
types while preserving the extensible index signature.
In `@src/types/common.ts`:
- Around line 46-51: Replace the `PasswordlessChallenge` index signature’s `any`
with `unknown` so extra server-returned properties remain extensible without
disabling type safety. Update the `[key: string]: any` member in
`PasswordlessChallenge` to use `unknown`, and keep `authSession` unchanged so
callers can still narrow specific optional keys when needed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 11863ecc-04de-4321-bf49-5acc8679fc6c
⛔ Files ignored due to path filters (1)
example/ios/Podfile.lockis excluded by!**/*.lock
📒 Files selected for processing (27)
A0Auth0.podspecEXAMPLES.mdandroid/build.gradleandroid/src/main/java/com/auth0/react/A0Auth0Module.ktandroid/src/main/java/com/auth0/react/Passwordless.ktexample/src/screens/class-based/ClassLogin.tsxexample/src/screens/hooks/Home.tsxios/A0Auth0.mmios/Passwordless.swiftsrc/Auth0.tssrc/core/interfaces/IAuth0Client.tssrc/core/interfaces/IPasswordlessClient.tssrc/core/interfaces/index.tssrc/hooks/Auth0Context.tssrc/hooks/Auth0Provider.tsxsrc/platforms/native/adapters/NativeAuth0Client.tssrc/platforms/native/adapters/NativePasswordlessClient.tssrc/platforms/native/adapters/__tests__/NativePasswordlessClient.spec.tssrc/platforms/native/bridge/INativeBridge.tssrc/platforms/native/bridge/NativeBridgeManager.tssrc/platforms/native/bridge/__tests__/NativeBridgeManager.spec.tssrc/platforms/web/adapters/WebAuth0Client.tssrc/platforms/web/adapters/WebPasswordlessClient.tssrc/platforms/web/adapters/__tests__/WebPasswordlessClient.spec.tssrc/specs/NativeA0Auth0.tssrc/types/common.tssrc/types/parameters.ts
| This flow lets a user authenticate with a one-time code sent to their email or phone against a standard **database** connection (`auth0` strategy) that has `email_otp` or `phone_otp` enabled. It is distinct from [Login with Passwordless](#login-with-passwordless), which targets dedicated `email` / `sms` connections. | ||
|
|
||
| It is a two-step, challenge-response flow: request a challenge (which delivers the OTP and returns an opaque `auth_session`), then exchange the challenge and the user-entered code for credentials. | ||
|
|
There was a problem hiding this comment.
lets update EXAMPLES.md with info related to an optional allowSignup parameter (defaults to false) that controls whether a new user is created if one does not yet exist.
| private val reactContext: ReactApplicationContext | ||
| ) { | ||
|
|
||
| private fun createClient(): AuthenticationAPIClient { |
There was a problem hiding this comment.
Why are you creating a new client for each API request ? Can't we have one client created when this class in instantiated and used by all the APIs
| fun challengeWithEmail( | ||
| email: String, | ||
| connection: String, | ||
| allowSignup: Boolean, |
There was a problem hiding this comment.
allowSignup can have a default value false
There was a problem hiding this comment.
in RN layer we have set the dafault value as false, also updated here as well
| phoneNumber: String, | ||
| connection: String, | ||
| deliveryMethod: String, | ||
| allowSignup: Boolean, |
There was a problem hiding this comment.
| self.useDPoP = useDPoP | ||
| } | ||
|
|
||
| private func createClient() -> Authentication { |
There was a problem hiding this comment.
Same comment as in Android. Pbly not needed to create a client each time
…into feat/passwordless-otp-database-connections
Adds support for Passwordless OTP on database connections — an embedded (non-redirect) flow where a user authenticates with a one-time code sent to their email or phone, against a standard database connection that has
email_otp/phone_otpenabled.This is distinct from the existing
/passwordless/startflow (which only works with dedicatedemail/smsstrategy connections). It is delegated to the native SDKs (Auth0.swift ≥ 2.23.0, Auth0.Android ≥ 3.20.0) and exposed through a newauth0.passwordlessnamespace.Public API
A new
passwordlessclient, available on both theAuth0instance and theuseAuth0hook:Example
Summary by CodeRabbit
passwordlessAPI in the SDK, including native bindings (web will report it as unsupported).