|
25 | 25 | - [Handling DPoP token migration](#handling-dpop-token-migration) |
26 | 26 | - [Checking token type](#checking-token-type) |
27 | 27 | - [Handling nonce errors](#handling-nonce-errors) |
| 28 | +- [Multi-Resource Refresh Tokens (MRRT)](#multi-resource-refresh-tokens-mrrt) |
| 29 | + - [Overview](#mrrt-overview) |
| 30 | + - [Prerequisites](#mrrt-prerequisites) |
| 31 | + - [Using MRRT with Hooks](#using-mrrt-with-hooks) |
| 32 | + - [Using MRRT with Auth0 Class](#using-mrrt-with-auth0-class) |
| 33 | + - [Web Platform Configuration](#web-platform-configuration) |
28 | 34 | - [Bot Protection](#bot-protection) |
29 | 35 | - [Domain Switching](#domain-switching) |
30 | 36 | - [Android](#android) |
@@ -304,6 +310,128 @@ auth0.webAuth |
304 | 310 |
|
305 | 311 | If the URL doesn't contain the expected values, an error will be raised through the provided callback. |
306 | 312 |
|
| 313 | +## Multi-Resource Refresh Tokens (MRRT) |
| 314 | + |
| 315 | +### MRRT Overview |
| 316 | + |
| 317 | +Multi-Resource Refresh Tokens (MRRT) allow your application to obtain access tokens for multiple APIs using a single refresh token. This is useful when your application needs to access multiple backend services, each identified by a different audience. |
| 318 | + |
| 319 | +### MRRT Prerequisites |
| 320 | + |
| 321 | +Before using MRRT, ensure: |
| 322 | + |
| 323 | +1. **MRRT is enabled on your Auth0 tenant** - Contact Auth0 support or enable it through the Auth0 Dashboard |
| 324 | +2. **Request `offline_access` scope during login** - This ensures a refresh token is issued |
| 325 | +3. **Configure your APIs in Auth0 Dashboard** - Each API you want to access should be registered with its own audience identifier |
| 326 | + |
| 327 | +### Using MRRT with Hooks |
| 328 | + |
| 329 | +```tsx |
| 330 | +import { useAuth0 } from 'react-native-auth0'; |
| 331 | + |
| 332 | +function MyComponent() { |
| 333 | + const { authorize, getApiCredentials, clearApiCredentials } = useAuth0(); |
| 334 | + |
| 335 | + const login = async () => { |
| 336 | + // Login with offline_access to get a refresh token |
| 337 | + await authorize({ |
| 338 | + scope: 'openid profile email offline_access', |
| 339 | + audience: 'https://primary-api.example.com', |
| 340 | + }); |
| 341 | + }; |
| 342 | + |
| 343 | + const getFirstApiToken = async () => { |
| 344 | + try { |
| 345 | + // Get credentials for the first API |
| 346 | + const credentials = await getApiCredentials( |
| 347 | + 'https://first-api.example.com', |
| 348 | + 'read:data write:data' |
| 349 | + ); |
| 350 | + console.log('First API Access Token:', credentials.accessToken); |
| 351 | + console.log('Expires At:', new Date(credentials.expiresAt * 1000)); |
| 352 | + } catch (error) { |
| 353 | + console.error('Error:', error); |
| 354 | + } |
| 355 | + }; |
| 356 | + |
| 357 | + const getSecondApiToken = async () => { |
| 358 | + try { |
| 359 | + // Get credentials for a different API using the same refresh token |
| 360 | + const credentials = await getApiCredentials( |
| 361 | + 'https://second-api.example.com', |
| 362 | + 'read:reports' |
| 363 | + ); |
| 364 | + console.log('Second API Access Token:', credentials.accessToken); |
| 365 | + } catch (error) { |
| 366 | + console.error('Error:', error); |
| 367 | + } |
| 368 | + }; |
| 369 | + |
| 370 | + const clearFirstApiCache = async () => { |
| 371 | + // Clear cached credentials for a specific API |
| 372 | + await clearApiCredentials('https://first-api.example.com'); |
| 373 | + }; |
| 374 | + |
| 375 | + return ( |
| 376 | + // Your UI components |
| 377 | + ); |
| 378 | +} |
| 379 | +``` |
| 380 | + |
| 381 | +### Using MRRT with Auth0 Class |
| 382 | + |
| 383 | +```js |
| 384 | +import Auth0 from 'react-native-auth0'; |
| 385 | + |
| 386 | +const auth0 = new Auth0({ |
| 387 | + domain: 'YOUR_AUTH0_DOMAIN', |
| 388 | + clientId: 'YOUR_AUTH0_CLIENT_ID', |
| 389 | +}); |
| 390 | + |
| 391 | +// Login with offline_access scope |
| 392 | +await auth0.webAuth.authorize({ |
| 393 | + scope: 'openid profile email offline_access', |
| 394 | + audience: 'https://primary-api.example.com', |
| 395 | +}); |
| 396 | + |
| 397 | +// Get credentials for a specific API |
| 398 | +const apiCredentials = await auth0.credentialsManager.getApiCredentials( |
| 399 | + 'https://first-api.example.com', |
| 400 | + 'read:data write:data' |
| 401 | +); |
| 402 | + |
| 403 | +console.log('Access Token:', apiCredentials.accessToken); |
| 404 | +console.log('Token Type:', apiCredentials.tokenType); |
| 405 | +console.log('Expires At:', apiCredentials.expiresAt); |
| 406 | +console.log('Scope:', apiCredentials.scope); |
| 407 | + |
| 408 | +// Clear cached credentials for a specific API |
| 409 | +await auth0.credentialsManager.clearApiCredentials( |
| 410 | + 'https://first-api.example.com' |
| 411 | +); |
| 412 | +``` |
| 413 | + |
| 414 | +### Web Platform Configuration |
| 415 | + |
| 416 | +On the **web platform**, you must explicitly enable MRRT support in the `Auth0Provider`: |
| 417 | + |
| 418 | +```tsx |
| 419 | +import { Auth0Provider } from 'react-native-auth0'; |
| 420 | + |
| 421 | +function App() { |
| 422 | + return ( |
| 423 | + <Auth0Provider |
| 424 | + domain="your-domain.auth0.com" |
| 425 | + clientId="your-client-id" |
| 426 | + useMrrt={true} |
| 427 | + cacheLocation="localstorage" |
| 428 | + > |
| 429 | + <YourApp /> |
| 430 | + </Auth0Provider> |
| 431 | + ); |
| 432 | +} |
| 433 | +``` |
| 434 | + |
307 | 435 | ## Bot Protection |
308 | 436 |
|
309 | 437 | If you are using the [Bot Protection](https://auth0.com/docs/anomaly-detection/bot-protection) feature and performing database login/signup via the Authentication API, you need to handle the `requires_verification` error. It indicates that the request was flagged as suspicious and an additional verification step is necessary to log the user in. That verification step is web-based, so you need to use Universal Login to complete it. |
|
0 commit comments