Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 6 additions & 51 deletions docs/_partials/expo/email-pass-sign-in.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ThemedView } from '@/components/themed-view'
import { useAuth, useSignIn } from '@clerk/expo'
import { Link, useRouter } from 'expo-router'
import React from 'react'
import { Pressable, StyleSheet, Switch, TextInput, View } from 'react-native'
import { Pressable, StyleSheet, TextInput, View } from 'react-native'

export default function Page() {
const { signIn } = useSignIn()
Expand All @@ -15,8 +15,6 @@ export default function Page() {

const [emailAddress, setEmailAddress] = React.useState('')
const [password, setPassword] = React.useState('')
const [code, setCode] = React.useState('')
const [useBackupCode, setUseBackupCode] = React.useState(false)

// Handle the submission of the sign-in form
const onSignInPress = React.useCallback(async () => {
Expand All @@ -25,21 +23,10 @@ export default function Page() {
password,
})

if (signIn.status === 'complete') {
await signIn.finalize({
navigate: () => {
router.push('/')
},
})
}
}, [signIn, emailAddress, password, router])

// Handle the submission of the MFA code
const onVerifyPress = React.useCallback(async () => {
if (useBackupCode) {
await signIn.mfa.verifyBackupCode({ code })
} else {
await signIn.mfa.verifyTOTP({ code })
if (signIn.status === 'needs_second_factor') {
// Further set up is required for multi-factor authentication
// See https://clerk.com/docs/guides/development/custom-flows/authentication/email-password-mfa
return null
}

if (signIn.status === 'complete') {
Expand All @@ -49,44 +36,12 @@ export default function Page() {
},
})
}
}, [signIn, code, useBackupCode, router])
}, [signIn, emailAddress, password, router])

if (signIn.status === 'complete' || isSignedIn) {
return null
}

// Display MFA verification form
if (signIn.status === 'needs_second_factor') {
return (
<ThemedView style={styles.container}>
<ThemedText type="title" style={styles.title}>
Verify your account
</ThemedText>
<ThemedText style={styles.description}>
Enter the verification code from your authenticator app.
</ThemedText>
<TextInput
style={styles.input}
value={code}
placeholder="Enter verification code"
placeholderTextColor="#666666"
onChangeText={(code) => setCode(code)}
keyboardType="numeric"
/>
<View style={styles.switchContainer}>
<ThemedText style={styles.label}>Use backup code</ThemedText>
<Switch value={useBackupCode} onValueChange={setUseBackupCode} />
</View>
<Pressable
style={({ pressed }) => [styles.button, pressed && styles.buttonPressed]}
onPress={onVerifyPress}
>
<ThemedText style={styles.buttonText}>Verify</ThemedText>
</Pressable>
</ThemedView>
)
}

return (
<ThemedView style={styles.container}>
<ThemedText type="title" style={styles.title}>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
title: Build a custom authentication flow with Client Trust
description: Learn how to build a custom authentication flow that supports Client Trust.
---

<Include src="_partials/custom-flows-callout" />

<If sdk={["nextjs", "react", "expo", "js-frontend", "react-router", "tanstack-react-start"]}>
> [!IMPORTANT]
> This guide applies to the following Clerk SDKs:
>
> - `@clerk/react` v6 or higher
> - `@clerk/nextjs` v7 or higher
> - `@clerk/expo` v3 or higher
> - `@clerk/react-router` v3 or higher
> - `@clerk/tanstack-react-start` v0.26.0 or higher
>
> If you're using an older version of one of these SDKs, or are using the legacy API, refer to the [legacy API documentation](/docs/guides/development/custom-flows/authentication/legacy/email-password).
</If>

Client Trust is Clerk's defense against [credential stuffing](https://owasp.org/www-community/attacks/Credential_stuffing) attacks - a type of attack where bad actors use lists of stolen passwords to attempt to gain unauthorized access to user accounts.

When Client Trust is enabled, when a user is signing in with a password on a new client (e.g. device), users will always be challenged for a [second factor](!second-factor). If you have multi-factor authentication (MFA) enabled, users may have already configured a second factor, such as SMS verification code or authenticator app. If you don't have MFA enabled, or if the user has not yet configured one, a one-time email code (default), SMS code, or email link will be used, depending on your application's settings.

This guide will demonstrate how to build a custom sign-in flow that supports the second factor strategies: email code and email link. To support SMS code or authenticator app, see the [MFA custom flow guide](/docs/guides/development/custom-flows/authentication/email-password-mfa).

## Build the custom flow

When Client Trust requires verification, the sign-in attempt will return a status of `needs_second_factor`.

### Email code

### Email link
Loading