Skip to content

Commit ca4def4

Browse files
authored
(/references/expo/local-credentials): update guide (#2001)
1 parent c092252 commit ca4def4

File tree

1 file changed

+77
-74
lines changed

1 file changed

+77
-74
lines changed

docs/references/expo/local-credentials.mdx

Lines changed: 77 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
---
2-
title: Allow returning users to sign in with biometrics in Expo
3-
description: Learn how to use the useLocalCredentials hook in your Expo app with Clerk.
2+
title: Enable biometric sign-in for returning users in Expo
3+
description: Learn how to use the useLocalCredentials() hook in your Expo app to enable biometric sign-ins for returning users.
44
---
55

6-
Clerk's [`useLocalCredentials()`](/docs/references/expo/use-local-credentials) hook enables you to store a user's password credentials on their device and subsequently use biometrics for sign-in.
7-
8-
This guide shows you how to use the `useLocalCredentials()` hook to enhance your user experience by allowing users to sign in using biometrics when they re-sign in to your Expo app.
9-
106
> [!WARNING]
11-
> This API is available only for [@clerk/clerk-expo v2](/docs/upgrade-guides/expo-v2/upgrade) >=2.2.0.
12-
> Be aware that this works only for sign in attempts with the password strategy.
7+
> This feature requires `@clerk/clerk-expo >[email protected]` and works only for sign-in attempts that use the password strategy.
8+
9+
This guide demonstrates how to use the [`useLocalCredentials()`](/docs/references/expo/use-local-credentials) hook in your Expo app to securely store a user's password credentials on their device, enabling biometric sign-in for returning users.
1310

1411
<Steps>
1512
## Install the necessary peer dependencies
1613

17-
These packages are required to be installed in order to use the `useLocalCredentials()` hook.
14+
The `useLocalCredentials()` hook requires the following packages to be installed in your project:
15+
16+
- `expo-local-authentication`: Provides biometric authentication functionality
17+
- `expo-secure-store`: Enables secure storage of credentials on the device
1818

1919
<CodeBlockTabs options={["npm", "yarn", "pnpm"]}>
2020
```bash {{ filename: 'terminal' }}
@@ -32,82 +32,103 @@ This guide shows you how to use the `useLocalCredentials()` hook to enhance your
3232

3333
## Update `app.json`
3434

35-
Update your app.json file as instructed in the Expo documentation:
35+
See the following Expo docs to update your `app.json` file with the necessary configurations for biometric sign-in. Replace `$(PRODUCT_NAME)` with your app's name as specified in the `"name"` field in your `app.json` file.
3636

3737
- [`expo-local-authentication`](https://docs.expo.dev/versions/latest/sdk/local-authentication/#configuration-in-appjsonappconfigjs)
3838
- [`expo-secure-store`](https://docs.expo.dev/versions/latest/sdk/securestore/#configuration-in-appjsonappconfigjs)
3939

4040
## Securely store/access the user's credentials during sign in
4141

42-
The following example demonstrates how to use `useLocalCredentials()` in a custom flow for signing users in.
42+
The following example demonstrates how to use `useLocalCredentials()` in a custom flow for signing in users.
4343

4444
```tsx {{ filename: 'app/sign-in.tsx' }}
4545
import { useSignIn } from '@clerk/clerk-expo'
46+
import { Link, useRouter } from 'expo-router'
47+
import { Text, TextInput, Button, View } from 'react-native'
48+
import { useState } from 'react'
4649
import { useLocalCredentials } from '@clerk/clerk-expo/local-credentials'
47-
import { Link, Stack, useRouter } from 'expo-router'
48-
import { Text, TextInput, Button, View, TouchableOpacity, StyleSheet } from 'react-native'
49-
import React from 'react'
50-
import { SymbolView } from 'expo-symbols'
5150

5251
export default function Page() {
53-
const { signIn, setActive, isLoaded } = useSignIn()
5452
const router = useRouter()
55-
56-
const [emailAddress, setEmailAddress] = React.useState('')
57-
const [password, setPassword] = React.useState('')
53+
const { signIn, setActive, isLoaded } = useSignIn()
5854
const { hasCredentials, setCredentials, authenticate, biometricType } = useLocalCredentials()
5955

60-
const onSignInPress = React.useCallback(
61-
async (useLocal = false) => {
62-
if (!isLoaded) {
63-
return
64-
}
56+
const [emailAddress, setEmailAddress] = useState('')
57+
const [password, setPassword] = useState('')
6558

66-
try {
67-
const signInAttempt =
68-
hasCredentials && useLocal
69-
? await authenticate()
70-
: await signIn.create({
71-
identifier: emailAddress,
72-
password,
73-
})
74-
75-
if (signInAttempt.status === 'complete') {
76-
if (!useLocal) {
77-
await setCredentials({
59+
const onSignInPress = async (useLocal: boolean) => {
60+
if (!isLoaded) return
61+
62+
// Start the sign-in process using the email and password provided
63+
try {
64+
const signInAttempt =
65+
hasCredentials && useLocal
66+
? await authenticate()
67+
: await signIn.create({
7868
identifier: emailAddress,
7969
password,
8070
})
81-
}
82-
await setActive({ session: signInAttempt.createdSessionId })
8371

84-
// navigate away
85-
} else {
86-
// handle other statuses of sign in
72+
// If sign-in process is complete,
73+
// set the created session as active and redirect the user
74+
if (signInAttempt.status === 'complete') {
75+
console.log('status is complete?', signInAttempt.status)
76+
77+
if (!useLocal) {
78+
await setCredentials({
79+
identifier: emailAddress,
80+
password,
81+
})
8782
}
88-
} catch (err: any) {
89-
// handle any other error
83+
84+
await setActive({ session: signInAttempt.createdSessionId })
85+
router.replace('/')
86+
} else {
87+
// If the status is not complete, check why.
88+
// User may need to complete further steps.
89+
console.error(JSON.stringify(signInAttempt, null, 2))
9090
}
91-
},
92-
[isLoaded, emailAddress, password],
93-
)
91+
} catch (err) {
92+
// For info on error handing,
93+
// see https://clerk.com/docs/custom-flows/error-handling
94+
console.error(JSON.stringify(err, null, 2))
95+
}
96+
}
9497

9598
return (
9699
<View>
97100
<TextInput
101+
autoCapitalize="none"
98102
value={emailAddress}
99-
onChangeText={(emailAddress) => setEmailAddress(emailAddress)}
103+
placeholder="Enter email"
104+
onChangeText={(emailAddress: string) => setEmailAddress(emailAddress)}
100105
/>
101-
<TextInput value={password} onChangeText={(password) => setPassword(password)} />
102-
<Button title="Sign In" onPress={() => onSignInPress()} />
106+
107+
<TextInput
108+
value={password}
109+
placeholder="Enter password"
110+
secureTextEntry={true}
111+
onChangeText={(password: string) => setPassword(password)}
112+
/>
113+
114+
<Button title="Sign In" onPress={() => onSignInPress(false)} />
115+
103116
{hasCredentials && biometricType && (
104-
<TouchableOpacity onPress={() => onSignInPress(true)}>
105-
<SymbolView
106-
name={biometricType === 'face-recognition' ? 'faceid' : 'touchid'}
107-
type="monochrome"
108-
/>
109-
</TouchableOpacity>
117+
<Button
118+
title={
119+
biometricType === 'face-recognition' ? 'Sign in with Face ID' : 'Sign in with Touch ID'
120+
}
121+
onPress={() => onSignInPress(true)}
122+
/>
110123
)}
124+
125+
<View>
126+
<Text>Don't have an account?</Text>
127+
128+
<Link href="/sign-up">
129+
<Text>Sign up</Text>
130+
</Link>
131+
</View>
111132
</View>
112133
)
113134
}
@@ -120,6 +141,7 @@ This guide shows you how to use the `useLocalCredentials()` hook to enhance your
120141
```tsx {{ filename: 'app/user.tsx' }}
121142
import { useUser, useClerk } from '@clerk/clerk-expo'
122143
import { useLocalCredentials } from '@clerk/clerk-expo/local-credentials'
144+
import { View, Text, Button } from 'react-native'
123145

124146
export default function Page() {
125147
const { user } = useUser()
@@ -192,22 +214,3 @@ This guide shows you how to use the `useLocalCredentials()` hook to enhance your
192214
}
193215
```
194216
</Steps>
195-
196-
## More resources
197-
198-
Use the following guides to learn more about Clerk components, how to build custom flows for your native apps, and how to use Clerk's client-side helpers.
199-
200-
<Cards>
201-
- [Expo SDK](/docs/quickstarts/expo)
202-
- Use Clerk with Expo to authenticate users in your React Native application.
203-
204-
---
205-
206-
- [Custom flows](/docs/custom-flows/overview)
207-
- Expo native apps require custom flows in place of prebuilt components. Learn more about custom flows.
208-
209-
---
210-
211-
- [Client-side helpers](/docs/references/react/use-user)
212-
- Clerk's client-side helpers enable you to access user data and perform actions on the client-side.
213-
</Cards>

0 commit comments

Comments
 (0)