Skip to content

Commit 68da0e4

Browse files
feat: Implement Auth0 authentication flow with user management features in web app
1 parent 1f88157 commit 68da0e4

1 file changed

Lines changed: 215 additions & 0 deletions

File tree

example/src/App.web.tsx

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
import React, { useState } from 'react';
2+
import {
3+
SafeAreaView,
4+
ScrollView,
5+
View,
6+
Text,
7+
StyleSheet,
8+
ActivityIndicator,
9+
} from 'react-native';
10+
import { Auth0Provider, useAuth0 } from 'react-native-auth0';
11+
12+
import config from './auth0-configuration';
13+
import Button from './components/Button';
14+
import Header from './components/Header';
15+
import Result from './components/Result';
16+
import LabeledInput from './components/LabeledInput';
17+
18+
const AuthContent = (): React.JSX.Element => {
19+
const {
20+
authorize,
21+
clearSession,
22+
user,
23+
error,
24+
isLoading,
25+
getCredentials,
26+
createUser,
27+
resetPassword,
28+
auth, // For direct access to the orchestrator
29+
users, // For access to the management API client
30+
} = useAuth0();
31+
32+
const [result, setResult] = useState<object | null>(null);
33+
const [apiError, setApiError] = useState<Error | null>(null);
34+
35+
const [email, setEmail] = useState('');
36+
const [password, setPassword] = useState('');
37+
38+
// Helper to run a function and display its result or error
39+
const runDemo = async (action: () => Promise<any>) => {
40+
setResult(null);
41+
setApiError(null);
42+
try {
43+
const response = await action();
44+
setResult(response ?? { success: true });
45+
} catch (e) {
46+
setApiError(e as Error);
47+
}
48+
};
49+
50+
if (isLoading) {
51+
return (
52+
<View style={styles.content}>
53+
<ActivityIndicator size="large" color="#E53935" />
54+
</View>
55+
);
56+
}
57+
58+
return (
59+
<View style={styles.content}>
60+
<Header title="React Native Auth0" />
61+
{error && <Result title="Hook Error" error={error} result={null} />}
62+
<Result title="Last Action Result" result={result} error={apiError} />
63+
64+
{user ? (
65+
// ------ Logged In State ------
66+
<View style={styles.section}>
67+
<Text style={styles.title}>Welcome, {user.name}!</Text>
68+
<Result title="User Profile" result={user} error={null} />
69+
<Button
70+
onPress={() => runDemo(getCredentials)}
71+
title="Get Credentials"
72+
/>
73+
<Button
74+
onPress={() =>
75+
runDemo(() =>
76+
users(result?.accessToken).getUser({ id: user.sub })
77+
)
78+
}
79+
title="Get Full Profile (Mgmt API)"
80+
disabled={!result?.accessToken}
81+
/>
82+
<Button onPress={clearSession} title="Log Out" />
83+
</View>
84+
) : (
85+
// ------ Logged Out State ------
86+
<>
87+
<Section title="Web Auth (Recommended Flow)">
88+
<Button
89+
onPress={() =>
90+
authorize({ scope: 'openid profile email offline_access' })
91+
}
92+
title="Log In"
93+
/>
94+
</Section>
95+
96+
<Section title="User Self-Service">
97+
<LabeledInput
98+
label="Email"
99+
value={email}
100+
onChangeText={setEmail}
101+
autoCapitalize="none"
102+
keyboardType="email-address"
103+
/>
104+
<LabeledInput
105+
label="Password"
106+
value={password}
107+
onChangeText={setPassword}
108+
secureTextEntry
109+
/>
110+
<Button
111+
onPress={() =>
112+
runDemo(() =>
113+
createUser({
114+
email,
115+
password,
116+
connection: 'Username-Password-Authentication',
117+
})
118+
)
119+
}
120+
title="Create User (Public Signup)"
121+
/>
122+
<Button
123+
onPress={() =>
124+
runDemo(() =>
125+
resetPassword({
126+
email,
127+
connection: 'Username-Password-Authentication',
128+
})
129+
)
130+
}
131+
title="Reset Password"
132+
/>
133+
</Section>
134+
135+
<Section title="Unsupported Web Methods (Will Fail)">
136+
<Button
137+
onPress={() =>
138+
runDemo(() =>
139+
auth.passwordRealm({ username: '', password: '', realm: '' })
140+
)
141+
}
142+
title="Test auth.passwordRealm()"
143+
/>
144+
</Section>
145+
</>
146+
)}
147+
</View>
148+
);
149+
};
150+
151+
const App = (): React.JSX.Element => {
152+
return (
153+
<Auth0Provider
154+
domain={config.domain}
155+
clientId={config.clientId}
156+
cacheLocation="localstorage"
157+
>
158+
<SafeAreaView style={styles.container}>
159+
<ScrollView contentContainerStyle={{ flexGrow: 1 }}>
160+
<AuthContent />
161+
</ScrollView>
162+
</SafeAreaView>
163+
</Auth0Provider>
164+
);
165+
};
166+
167+
const Section = ({
168+
title,
169+
children,
170+
}: {
171+
title: string;
172+
children: React.ReactNode;
173+
}) => (
174+
<View style={styles.section}>
175+
<Text style={styles.sectionTitle}>{title}</Text>
176+
<View style={styles.buttonGroup}>{children}</View>
177+
</View>
178+
);
179+
180+
const styles = StyleSheet.create({
181+
container: {
182+
flex: 1,
183+
backgroundColor: '#F5F5F5',
184+
},
185+
content: {
186+
flex: 1,
187+
padding: 16,
188+
alignItems: 'center',
189+
justifyContent: 'center',
190+
},
191+
title: {
192+
fontSize: 24,
193+
fontWeight: 'bold',
194+
marginBottom: 24,
195+
textAlign: 'center',
196+
},
197+
section: {
198+
width: '100%',
199+
padding: 16,
200+
borderWidth: 1,
201+
borderColor: '#E0E0E0',
202+
borderRadius: 8,
203+
marginBottom: 20,
204+
},
205+
sectionTitle: {
206+
fontSize: 18,
207+
fontWeight: 'bold',
208+
marginBottom: 12,
209+
},
210+
buttonGroup: {
211+
gap: 10,
212+
},
213+
});
214+
215+
export default App;

0 commit comments

Comments
 (0)