Skip to content

Commit 0976d17

Browse files
docs: clarify passwordless code vs magic link flows in EXAMPLES.md
1 parent 6a9637d commit 0976d17

1 file changed

Lines changed: 69 additions & 3 deletions

File tree

EXAMPLES.md

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,13 +196,23 @@ auth0.auth
196196

197197
Passwordless is a two-step authentication flow that makes use of this type of connection. The **Passwordless OTP** grant is required to be enabled in your Auth0 application beforehand. Check [our guide](https://auth0.com/docs/dashboard/guides/applications/update-grant-types) to learn how to enable it.
198198

199-
To start the flow, you request a code to be sent to the user's email or phone number. For email scenarios only, a link can be sent in place of the code.
199+
The `send` option controls how the user receives the challenge, and the two options complete differently. Make sure you use the one that matches how you started the flow:
200+
201+
- **`send: 'code'`** — the user receives a 6-digit one-time code that you collect in your app and exchange for tokens with `loginWithEmail` / `loginWithSMS`. This is fully handled by the SDK and is the recommended option for React Native / Expo.
202+
- **`send: 'link'`** — the user receives a magic link (typically by email). Tapping it completes authentication server-side and redirects to your app's callback URL with the tokens already in the URL fragment (e.g. `myapp://callback#access_token=...`). There is **no** code to pass back to `loginWithEmail` in this case; instead your app must listen for the deep link and parse the tokens from the fragment yourself (see [Handling the magic link callback](#handling-the-magic-link-callback) below).
203+
204+
> [!NOTE]
205+
> This SDK accepts only `'code'` or `'link'` for `send`. The underlying native SDKs (Auth0.swift / Auth0.Android) additionally expose platform-specific link types such as `link_ios` / `link_android`, but those are not surfaced through `react-native-auth0`.
206+
207+
#### Code flow (recommended)
208+
209+
To start the flow, request a code to be sent to the user's email or phone number:
200210

201211
```js
202212
auth0.auth
203213
.passwordlessWithEmail({
204214
email: 'info@auth0.com',
205-
send: 'link',
215+
send: 'code',
206216
})
207217
.then(console.log)
208218
.catch(console.error);
@@ -219,7 +229,7 @@ auth0.auth
219229
.catch(console.error);
220230
```
221231

222-
Then, in order to complete the authentication, you must send back that received code value along with the email or phone number used:
232+
Then, to complete the authentication, send back the received code along with the email or phone number used:
223233

224234
```js
225235
auth0.auth
@@ -243,6 +253,62 @@ auth0.auth
243253
.catch(console.error);
244254
```
245255

256+
#### Magic link flow
257+
258+
To start the flow, request a link to be sent to the user's email:
259+
260+
```js
261+
auth0.auth
262+
.passwordlessWithEmail({
263+
email: 'info@auth0.com',
264+
send: 'link',
265+
})
266+
.then(console.log)
267+
.catch(console.error);
268+
```
269+
270+
##### Handling the magic link callback
271+
272+
With `send: 'link'`, tapping the link in the email completes authentication on the Auth0 server and redirects to your registered callback URL with the tokens in the URL fragment:
273+
274+
```text
275+
myapp://callback#access_token=...&scope=openid%20profile%20email%20offline_access&expires_in=7200&token_type=Bearer
276+
```
277+
278+
The SDK does not intercept this redirect, so do **not** call `loginWithEmail` here — there is no code to send back. Instead, listen for the incoming deep link in your app using React Native's [`Linking`](https://reactnative.dev/docs/linking) API (or [`expo-linking`](https://docs.expo.dev/versions/latest/sdk/linking/) on Expo) and parse the tokens from the URL fragment yourself:
279+
280+
```js
281+
import { Linking } from 'react-native';
282+
283+
function parseTokensFromUrl(url) {
284+
const fragment = url.split('#')[1] ?? '';
285+
const params = new URLSearchParams(fragment);
286+
return {
287+
accessToken: params.get('access_token'),
288+
expiresIn: params.get('expires_in'),
289+
scope: params.get('scope'),
290+
tokenType: params.get('token_type'),
291+
};
292+
}
293+
294+
// Handle the case where the app is opened from a cold start by the link
295+
Linking.getInitialURL().then((url) => {
296+
if (url) {
297+
const tokens = parseTokensFromUrl(url);
298+
// store / use the tokens
299+
}
300+
});
301+
302+
// Handle the case where the app is already running
303+
const subscription = Linking.addEventListener('url', ({ url }) => {
304+
const tokens = parseTokensFromUrl(url);
305+
// store / use the tokens
306+
});
307+
```
308+
309+
> [!NOTE]
310+
> For native and Expo apps, the **code flow is recommended** because the SDK handles the full exchange for you. Use the magic link flow only if your use case specifically requires magic links, and be aware that you are responsible for handling the deep link and securely storing the returned tokens.
311+
246312
### Create user in database connection
247313
248314
```js

0 commit comments

Comments
 (0)