Skip to content

Commit cfcfbbc

Browse files
Merge branch 'master' of https://github.com/auth0/react-native-auth0 into SDK-6188-rn-upgrade
2 parents 395fc84 + ecf0577 commit cfcfbbc

25 files changed

Lines changed: 1904 additions & 508 deletions

EXAMPLES-WEB.md

Lines changed: 99 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2,119 +2,159 @@
22

33
This guide provides usage examples specifically for developers targeting **React Native Web**. The web platform uses the underlying `@auth0/auth0-spa-js` library, and its features are aligned with browser security best practices.
44

5-
## Setup: The `Auth0Provider`
5+
## 1. The Hooks-Based Approach (Recommended)
66

7-
All web-based authentication starts with wrapping your application in the `Auth0Provider`. You can also pass `auth0-spa-js` specific options.
7+
This is the simplest and recommended way to integrate Auth0. The `Auth0Provider` handles all the complexity of the redirect flow automatically.
8+
9+
### Step 1: Wrap Your App in the `Auth0Provider`
10+
11+
In your main application entry point (e.g., `App.tsx`), wrap your application with the provider.
812

913
```jsx
10-
// App.js
14+
// src/App.tsx
15+
import React from 'react';
1116
import { Auth0Provider } from 'react-native-auth0';
17+
import config from './auth0-configuration';
18+
import MainComponent from './MainComponent'; // Your main app UI
1219

13-
const App = () => {
14-
return (
15-
<Auth0Provider
16-
domain="YOUR_AUTH0_DOMAIN"
17-
clientId="YOUR_AUTH0_CLIENT_ID"
18-
// Optional spa-js specific settings
19-
cacheLocation="localstorage"
20-
useRefreshTokens={true}
21-
>
22-
<YourAppRoot />
23-
</Auth0Provider>
24-
);
25-
};
20+
const App = () => (
21+
<Auth0Provider domain={config.domain} clientId={config.clientId}>
22+
<MainComponent />
23+
</Auth0Provider>
24+
);
2625

2726
export default App;
2827
```
2928

30-
## Basic Login and Logout
29+
### Step 2: Use the `useAuth0` Hook in Your Components
3130

32-
Use the `useAuth0` hook to access authentication methods and state. The primary flow involves redirecting the user to the Auth0 Universal Login page.
31+
The `Auth0Provider` will automatically handle the redirect callback when your app loads. The `useAuth0` hook will then provide the authentication state.
3332

3433
```jsx
34+
// src/MainComponent.tsx
35+
import React from 'react';
3536
import { useAuth0 } from 'react-native-auth0';
36-
import { View, Button, Text } from 'react-native';
37+
import { View, Button, Text, ActivityIndicator } from 'react-native';
3738

38-
const LoginProfile = () => {
39-
const { authorize, clearSession, user, error, isLoading } = useAuth0();
39+
const MainComponent = () => {
40+
const { authorize, clearSession, user, isLoading, error } = useAuth0();
4041

4142
const onLogin = async () => {
4243
try {
43-
// This will redirect the user to the login page.
44-
// The promise does not resolve as the page context is lost.
44+
// This triggers a redirect to the Auth0 Universal Login page.
4545
await authorize({ scope: 'openid profile email' });
4646
} catch (e) {
47-
console.log('Login cancelled or failed', e);
47+
console.error('Login error:', e);
4848
}
4949
};
5050

5151
const onLogout = async () => {
5252
try {
53-
// This will redirect the user to the logout page.
5453
await clearSession();
5554
} catch (e) {
56-
console.log('Logout error', e);
55+
console.error('Logout error:', e);
5756
}
5857
};
5958

6059
if (isLoading) {
6160
return (
6261
<View>
63-
<Text>Loading...</Text>
62+
<ActivityIndicator size="large" />
6463
</View>
6564
);
6665
}
6766

6867
return (
6968
<View>
70-
{user && (
69+
{error && <Text>Error: {error.message}</Text>}
70+
{user ? (
7171
<>
72-
<Text>Logged in as {user.name}</Text>
73-
<Button onPress={onLogout} title="Log Out" />
72+
<Text>Welcome, {user.name}!</Text>
73+
<Button title="Log Out" onPress={onLogout} />
7474
</>
75+
) : (
76+
<Button title="Log In" onPress={onLogin} />
7577
)}
76-
{!user && <Button onPress={onLogin} title="Log In" />}
77-
{error && <Text style={{ color: 'red' }}>{error.message}</Text>}
7878
</View>
7979
);
8080
};
8181
```
8282

83-
## Accessing User Information and Tokens
83+
## 2. The Class-Based / Manual Approach
84+
85+
If you are not using React Hooks or need more fine-grained control, you can instantiate the `Auth0` class and handle the redirect callback manually.
86+
87+
### Step 1: Instantiate the `Auth0` Client
88+
89+
Create a singleton instance of the client.
90+
91+
```javascript
92+
// src/api/auth0.ts
93+
import Auth0 from 'react-native-auth0';
94+
import config from '../auth0-configuration';
95+
96+
const auth0 = new Auth0({
97+
domain: config.domain,
98+
clientId: config.clientId,
99+
});
100+
101+
export default auth0;
102+
```
103+
104+
### Step 2: Handle the Redirect Callback
84105

85-
After a user is logged in, you can access their profile from the `user` object. To get a fresh access token for calling a protected API, use `getCredentials`.
106+
In your application's root component or entry point, you need to add logic to process the result from Auth0 after the user is redirected back.
86107

87108
```jsx
88-
import { useAuth0 } from 'react-native-auth0';
109+
// src/App.tsx
110+
import React, { useEffect, useState } from 'react';
111+
import { View, Button, Text } from 'react-native';
112+
import auth0 from './api/auth0'; // Import your singleton
113+
import type { User } from 'react-native-auth0';
89114

90-
const Profile = () => {
91-
const { user } = useAuth0();
92-
return user ? <Text>Welcome, {user.name}!</Text> : null;
93-
};
115+
const App = () => {
116+
const [user, setUser] = useState<User | null>(null);
117+
const [isLoading, setIsLoading] = useState(true);
118+
119+
useEffect(() => {
120+
const checkSession = async () => {
121+
// Check if the URL contains redirect parameters
122+
if (window.location.search.includes('code=') && window.location.search.includes('state=')) {
123+
try {
124+
// Process the redirect
125+
await auth0.webAuth.handleRedirectCallback();
126+
} catch (e) {
127+
console.error(e);
128+
}
129+
// Clean the URL
130+
window.history.replaceState({}, document.title, '/');
131+
}
132+
133+
// After handling a potential redirect, check for an existing session
134+
try {
135+
const credentials = await auth0.credentialsManager.getCredentials();
136+
// Assuming you have a way to decode the idToken to get the user
137+
// const decodedUser = jwt_decode(credentials.idToken);
138+
// setUser(decodedUser);
139+
} catch (e) {
140+
// No credentials, user is not logged in
141+
setUser(null);
142+
}
143+
setIsLoading(false);
144+
};
145+
146+
checkSession();
147+
}, []);
94148

95-
const ApiButton = () => {
96-
const { getCredentials } = useAuth0();
149+
const onLogin = async () => {
150+
await auth0.webAuth.authorize({ scope: 'openid profile email' });
151+
};
97152

98-
const callApi = async () => {
99-
try {
100-
// getCredentials uses getTokenSilently() from auth0-spa-js
101-
// to get a valid token, refreshing it if necessary.
102-
const credentials = await getCredentials();
103-
const accessToken = credentials.accessToken;
104-
105-
const response = await fetch('https://api.example.com/data', {
106-
headers: {
107-
Authorization: `Bearer ${accessToken}`,
108-
},
109-
});
110-
const data = await response.json();
111-
console.log('API Data:', data);
112-
} catch (e) {
113-
console.error('Failed to get token or call API', e);
114-
}
153+
const onLogout = async () => {
154+
await auth0.webAuth.clearSession();
115155
};
116156

117-
return <Button onPress={callApi} title="Call Protected API" />;
157+
// ... Render UI based on isLoading and user state ...
118158
};
119159
```
120160

@@ -129,7 +169,3 @@ For security reasons, the web platform **does not support** direct authenticatio
129169
- `auth.refreshToken()`
130170

131171
All these flows should be configured in your [Auth0 Universal Login](https://auth0.com/docs/universal-login) page and initiated via the `authorize()` method.
132-
133-
```
134-
135-
```

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,7 @@ This library provides a unified API across Native (iOS/Android) and Web platform
673673
| **Web Authentication** | | | --- |
674674
| `webAuth.authorize()` ||| **Primary login method.** Uses `ASWebAuthenticationSession`/`Custom Tabs` on Native and `loginWithRedirect` on Web. |
675675
| `webAuth.clearSession()` ||| **Primary logout method.** Clears the session cookie on the server via a browser redirect. |
676+
| `webAuth.handleRedirectCallback()` ||| **Web-only.** Manually processes the callback from Auth0. Handled automatically when using the `Auth0Provider` hook. |
676677
| **Credential Management** | | | --- |
677678
| `credentialsManager.getCredentials()` ||| Retrieves stored tokens. On Native, it uses the secure Keychain/Keystore. On Web, it uses the `@auth0/auth0-spa-js` cache and `getTokenSilently`. |
678679
| `credentialsManager.hasValidCredentials()` ||| Checks for a valid local session. |

example/ios/Podfile.lock

Lines changed: 58 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2277,7 +2277,7 @@ PODS:
22772277
- ReactCommon/turbomodule/core
22782278
- SocketRocket
22792279
- Yoga
2280-
- RNScreens (4.11.1):
2280+
- RNScreens (4.13.1):
22812281
- boost
22822282
- DoubleConversion
22832283
- fast_float
@@ -2305,10 +2305,10 @@ PODS:
23052305
- ReactCodegen
23062306
- ReactCommon/turbomodule/bridging
23072307
- ReactCommon/turbomodule/core
2308-
- RNScreens/common (= 4.11.1)
2308+
- RNScreens/common (= 4.13.1)
23092309
- SocketRocket
23102310
- Yoga
2311-
- RNScreens/common (4.11.1):
2311+
- RNScreens/common (4.13.1):
23122312
- boost
23132313
- DoubleConversion
23142314
- fast_float
@@ -2585,7 +2585,7 @@ EXTERNAL SOURCES:
25852585
:path: "../node_modules/react-native/ReactCommon/yoga"
25862586

25872587
SPEC CHECKSUMS:
2588-
A0Auth0: 8fa9f0f74593d0c762528e8f7eb6e334d6fe912d
2588+
A0Auth0: e4937337ecc5cad23640c403347f6051e440fc57
25892589
Auth0: 2876d0c36857422eda9cb580a6cc896c7d14cb36
25902590
boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90
25912591
DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb
@@ -2601,67 +2601,67 @@ SPEC CHECKSUMS:
26012601
RCTTypeSafety: d877728097547d0a37786cc9130c43ad71739ac3
26022602
React: 4b0b9cb962e694611e5e8a697c1b0300a2510c21
26032603
React-callinvoker: 70f125c17c7132811a6b473946ac5e7ae93b5e57
2604-
React-Core: 7cbc3118df2334b2ef597d9a515938b02c82109f
2605-
React-CoreModules: 7d8c14ecb889e7786a04637583b55b7d8f246baf
2606-
React-cxxreact: f32be07cba236c2f20f4e05ca200577ba5358e78
2604+
React-Core: bab40f5b1f46fe0c5896895a6f333e861a821a81
2605+
React-CoreModules: 05647d952e521113c128360633896ba7ba652e82
2606+
React-cxxreact: 2b4bac1ec6eecc6288ac8a6caea6afb42585740e
26072607
React-debug: deb3a146ef717fa3e8f4c23e0288369fe53199b7
2608-
React-defaultsnativemodule: 2c13a4240c5f96c42d069d1ba2392de6b4145bbd
2609-
React-domnativemodule: 91349b0b1cb20310cec1341b87cdd461aaa85e57
2610-
React-Fabric: bdfc7ec2481f26d7a9b8f59461f29ba4d903c549
2611-
React-FabricComponents: 47898469543d1bfb4528a9846419ec5568be89b1
2612-
React-FabricImage: ac8fc85ef452e5e9ae935c41118814651bd9e7f3
2613-
React-featureflags: 793b911e4c53e680db4a7d9965d0d6dc87b2fa88
2614-
React-featureflagsnativemodule: 25c9516d0dd004493c9bbafeb97da20bf9bde7dc
2615-
React-graphics: e07281690425dd9eeba3875d1faad28bc1f6da3b
2616-
React-hermes: bc1440d0e0662cc813bbf1c5ffbf9e0db2993a0f
2617-
React-idlecallbacksnativemodule: a2a3bb4a1793280b34d06d00169153b094be8c16
2618-
React-ImageManager: c9fa7461f3cab08e7bc98cbf55455b499e71c8b3
2619-
React-jserrorhandler: 15e591702040afed99cfcd088cf2337a8d09d807
2620-
React-jsi: 512ab3a1a628bc8824c41de8bcbbb81b2ac6fa8d
2621-
React-jsiexecutor: 653ccd2dee1e5ea558eecaf2f27b8bba0f09add8
2622-
React-jsinspector: 9121ccd2676a3f7c079ac01c9f90183422e3190e
2623-
React-jsinspectorcdp: 5c723ff2a09d73f2fdc496a545fb7003e7fdc079
2624-
React-jsinspectornetwork: 9cb0173f69e8405cef33fc79030fad26bbc3c073
2625-
React-jsinspectortracing: 65dc04125dc2392d85a82b6916f8cb088ea77566
2626-
React-jsitooling: 21af93cc98f760dd88d65b06b9317e0d4849fbbc
2627-
React-jsitracing: 4cc1b7de8087ae41c61a0eeee2593bc3362908b6
2628-
React-logger: 2f0d40bc8e648fbb1ff3b6580ad54189a8753290
2629-
React-Mapbuffer: 9a7c65078c6851397c1999068989e4fc239d0c80
2630-
React-microtasksnativemodule: 4f1ef719ba6c7ebbd2d75346ffa2916f9b4771c9
2631-
react-native-safe-area-context: 339885703b6dd1be2bce42d9c0b0350c21180032
2632-
React-NativeModulesApple: f6f696e510b9d89c3c06b7764f56947dc13ae922
2608+
React-defaultsnativemodule: 11e2948787a15d3cf1b66d7f29f13770a177bff7
2609+
React-domnativemodule: 2f4b279acdb2963736fb5de2f585811dd90070b5
2610+
React-Fabric: 6f8d1a303c96f1d078c14d74c4005bf457e5b782
2611+
React-FabricComponents: b106410970e9a0c4e592da656c7a7e0947306c23
2612+
React-FabricImage: 1abaf230dfce9b58fdf53c4128f3f40c6e64af6a
2613+
React-featureflags: f7ef58d91079efde3ad223bcca6d197e845d5bcf
2614+
React-featureflagsnativemodule: ae5abc9849d1696f4f8f11ee3744bf5715e032cf
2615+
React-graphics: b306856c6ed9aac32f717a229550406a53b28a6d
2616+
React-hermes: b6edce8fa19388654b1aea30844497cbeade83bc
2617+
React-idlecallbacksnativemodule: cb386712842cb9e479c89311edb234d529b64db4
2618+
React-ImageManager: 8ce94417853eaa22faaad1f4cc1952dd3f8e2275
2619+
React-jserrorhandler: ab827d67dc270a9c8703eef524230baeafaf6876
2620+
React-jsi: 545342ec5c78ab1277af5f0dbe8d489e7e73db14
2621+
React-jsiexecutor: 20210891c7c77255c16dec6762faf68b373f9f74
2622+
React-jsinspector: 4e73460e488132d70d2b4894e5578cc856f2cb74
2623+
React-jsinspectorcdp: 8b2bcb5779289cb2b9ca517f2965ed23eb2fd3e0
2624+
React-jsinspectornetwork: b5e0cb9e488d294eed2d8209dc3dc0f9587210c1
2625+
React-jsinspectortracing: f3c4036e7b984405ac910f878576d325dd9f2834
2626+
React-jsitooling: 75bbfd221b6173a5e848ca5a6680506bac064a56
2627+
React-jsitracing: 11ed7d821864dd988c159d4943e0a1e0937c11b1
2628+
React-logger: 984ebd897afad067555d081deaf03f57c4315723
2629+
React-Mapbuffer: 0c045c844ce6d85cde53e85ab163294c6adad349
2630+
React-microtasksnativemodule: d9499269ad1f484ae71319bac1d9231447f2094e
2631+
react-native-safe-area-context: 68d1363b8354472a961aa6861ba8451beaf9a810
2632+
React-NativeModulesApple: 983f3483ef0a3446b56d490f09d579fba2442e17
26332633
React-oscompat: 114036cd8f064558c9c1a0c04fc9ae5e1453706a
2634-
React-perflogger: 4b2f88ae059b600daf268528a4a83366338eef05
2635-
React-performancetimeline: e15fd9798123436f99e46898422fe921fecf506b
2634+
React-perflogger: e7287fee27c16e3c8bd4d470f2361572b63be16b
2635+
React-performancetimeline: 8ebbaa31d2d0cea680b0a2a567500d3cab8954fc
26362636
React-RCTActionSheet: 68c68b0a7a5d2b0cfc255c64889b6e485974e988
2637-
React-RCTAnimation: 6bf502c89c53076f92cd1a254f5ec8d63ee263de
2638-
React-RCTAppDelegate: c90f5732784684c3dd226d812eccb578cd954ad7
2639-
React-RCTBlob: d2905f01749b80efd6d3b86fb15e30ed26d5450b
2640-
React-RCTFabric: 435b3ffaad113fb1f274c2f2a677c9fcc9b5cf55
2641-
React-RCTFBReactNativeSpec: a3178b419f42af196e90ca4bf07710dce5d68301
2642-
React-RCTImage: 8f5ffa03461339180a68820ea452af6e20ace2c7
2643-
React-RCTLinking: 1151646834d31f97580d8a75d768a84b2533b7f9
2644-
React-RCTNetwork: 52008724d0db90a540f4058ed0de0e41c4b7943c
2645-
React-RCTRuntime: 10ce9a7cb27ba307544d29a2a04e6202dc7b3e9a
2646-
React-RCTSettings: f724cacbd892ee18f985e1aebdd97386e49c76f5
2647-
React-RCTText: 6e1b95d9126d808410dfa96e09bc4441ec6f36f7
2648-
React-RCTVibration: 862a4e5b36d49e6299c8cbfb86486fc31f86f6fa
2637+
React-RCTAnimation: d6c5c728b888a967ce9aff1ff71a8ed71a68d069
2638+
React-RCTAppDelegate: 0fc048666bda159cd469a6fb9befb04b3fa62be4
2639+
React-RCTBlob: 12d8c699a1f906840113ee8d8bb575e69a05509f
2640+
React-RCTFabric: 01e815845ebc185f44205dcbf50eeb712fec23fe
2641+
React-RCTFBReactNativeSpec: f57927fb0af6ce2f25c19f8b894e2986138aa89f
2642+
React-RCTImage: a82518168f4ee407913b23ca749ca79ef51959f3
2643+
React-RCTLinking: 7f343b584c36f024f390fea563483568fe763ef6
2644+
React-RCTNetwork: 3165eb757ceb62a7cde4cdad043d63314122e8a3
2645+
React-RCTRuntime: feee590c459c4cb6aaa7a00f3abc8c04709b536f
2646+
React-RCTSettings: 6bad0ae45d8d872c873059f332f586f99875621f
2647+
React-RCTText: 657d60f35983062de8f0cea67c279aa7a3ea9858
2648+
React-RCTVibration: 78f4770515141efb7f55f9b27c49dda95319c3a8
26492649
React-rendererconsistency: f7baab26c6d0cd5b2eb7afcecfd2d8b957017b18
2650-
React-renderercss: 62acb8f010a062309e3bd0e203aa14636162e3b3
2651-
React-rendererdebug: 3a89ac44f15c7160735264d585a29525655238d2
2650+
React-renderercss: bdd2f83a4a054c3e4321fd61305c202b848e471b
2651+
React-rendererdebug: 9f8865ee038127a9d99d4b034c9da4935d204993
26522652
React-rncore: f7438473c4c71ee1963fb06a8635bb96013c9e1c
2653-
React-RuntimeApple: 81f0a9ba81ce7eb203529b0471dc69bf18f5f637
2654-
React-RuntimeCore: 6356e89b2518ba66a989c39a2adb18122a5e3b7b
2653+
React-RuntimeApple: 4d2ab9f72b9193da86eceded128a67254fc18aeb
2654+
React-RuntimeCore: 5fd73030438d094975ca0f549d162dd97746ae38
26552655
React-runtimeexecutor: 17c70842d5e611130cb66f91e247bc4a609c3508
2656-
React-RuntimeHermes: 0a1d7ce2fe08cf182235de1a9330b51aa6b935cd
2657-
React-runtimescheduler: 10ae98e1417eff159be5df8fdc8fcdaac557aba6
2656+
React-RuntimeHermes: 3c88e6e1ea7ea0899dcffc77c10d61ea46688cfd
2657+
React-runtimescheduler: 024500621c7c93d65371498abb4ee26d34f5d47d
26582658
React-timing: c3c923df2b86194e1682e01167717481232f1dc7
2659-
React-utils: 7791a96e194eec85cb41dc98a2045b5f07839598
2660-
ReactAppDependencyProvider: ba631a31783569c13056dd57ff39e19764abdd6f
2661-
ReactCodegen: b16d00d43b4e9dc44af53be171b17d93b4b20267
2662-
ReactCommon: 96684b90b235d6ae340d126141edd4563b7a446a
2663-
RNGestureHandler: c202f13fa95347076d8aca4ccb61739b067396cb
2664-
RNScreens: 45a4564413205e2a1695d40bbc0297f6eefc9b74
2659+
React-utils: 9154a037543147e1c24098f1a48fc8472602c092
2660+
ReactAppDependencyProvider: afd905e84ee36e1678016ae04d7370c75ed539be
2661+
ReactCodegen: f8d5fb047c4cd9d2caade972cad9edac22521362
2662+
ReactCommon: 17fd88849a174bf9ce45461912291aca711410fc
2663+
RNGestureHandler: 5e1a1605659c22098719fc2e8aee453fe728f52e
2664+
RNScreens: c63849403489bd068ea160f276fbc8416f19f2f7
26652665
SimpleKeychain: 768cf43ae778b1c21816e94dddf01bb8ee96a075
26662666
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
26672667
Yoga: daa1e4de4b971b977b23bc842aaa3e135324f1f3

0 commit comments

Comments
 (0)