# useReverification()

> This feature requires one of the following SDKS:
>
> - `@clerk/nextjs@6.12.7` or later
> - `@clerk/react`, or `@clerk/react@5.25.1` or later
> - `@clerk/clerk-js@5.57.1` or later
> - `@clerk/clerk-sdk-ruby@3.3.0` or later

Reverification allows you to prompt a user to verify their credentials before performing sensitive actions, even if they're already authenticated. For example, in a banking application, transferring money is considered a "sensitive action." Reverification can be used to confirm the user's identity.

The `useReverification()` hook is used to handle a session's reverification flow. If a request requires reverification, a modal will display, prompting the user to verify their credentials. Upon successful verification, the original request will automatically retry. If you'd like to build a custom UI, you can use the [onNeedsReverification](https://clerk.com/docs/chrome-extension/reference/hooks/use-reverification.md#use-reverification-options) option.

When using reverification, a user's credentials are valid for 10 minutes. Once stale, a user will need to reverify their credentials. This time duration can be customized by using the `has()` helper on the server-side. See the [guide on reverification](https://clerk.com/docs/guides/secure/reverification.md?sdk=chrome-extension) for more information.

## Parameters

| Parameter  | Type                                               | Description                                                                                                                                                                   |
| ---------- | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `fetcher`  | `Fetcher extends (...args: any[]) => Promise<any>` | A function that returns a promise.                                                                                                                                            |
| `options?` | `Options`                                          | Optional configuration object extending [UseReverificationOptions](https://clerk.com/docs/chrome-extension/reference/hooks/use-reverification.md#use-reverification-options). |

### `UseReverificationOptions`

The optional options object.

| Property                                                    | Type                                                                                                                                                                                         | Description                                                                                              |
| ----------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| <a id="onneedsreverification"></a> `onNeedsReverification?` | <code>(properties: <a href="https://clerk.com/docs/chrome-extension/reference/hooks/use-reverification.md#needs-reverification-parameters">NeedsReverificationParameters</a>) => void</code> | Handler for the reverification process. Opts out of using the default UI. Use this to build a custom UI. |

### `NeedsReverificationParameters`

| Property                         | Type                                                                       | Description                                                                     |
| -------------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| <a id="cancel"></a> `cancel`     | `() => void`                                                    | Marks the reverification process as cancelled and rejects the original request. |
| <a id="complete"></a> `complete` | `() => void`                                                    | Marks the reverification process as complete and retries the original request.  |
| <a id="level"></a> `level`       | `undefined | "first_factor" | "second_factor" | "multi_factor"` | The verification level required for the reverification process.                 |

## Examples

The `useReverification()` hook displays a prebuilt UI when the user needs to reverify their credentials. You can also build a custom UI to handle the reverification process yourself. Use the following tabs to see examples of either option.

**Prebuilt UI**

### Handle reverification for an action

The following example demonstrates how to use the `useReverification()` hook to require a user to reverify their credentials before being able to update their primary email address. It also demonstrates how to handle the cancellation of the reverification process.

filename: components/UpdateUserEmail.tsx
```tsx
import { useReverification, useUser } from '@clerk/chrome-extension'
import { isClerkRuntimeError, isReverificationCancelledError } from '@clerk/shared'

export function UpdateUserEmail() {
  // Use `useUser()` to get the current user's `User` object
  // `User` includes the `update()` method to update the user's primary email address
  const { user } = useUser()

  // Use `useReverification()` to enhance the `update()` method
  // to handle the reverification process
  const changePrimaryEmail = useReverification((emailAddressId: string) =>
    user?.update({ primaryEmailAddressId: emailAddressId }),
  )

  const handleClick = async (emailAddressId: string) => {
    try {
      await changePrimaryEmail(emailAddressId)
    } catch (e) {
      // Handle if user cancels the reverification process
      if (isClerkRuntimeError(e) && isReverificationCancelledError(e)) {
        console.error('User cancelled reverification', e.code)
      }

      // Handle other errors
      // See https://clerk.com/docs/guides/development/custom-flows/error-handling
      // for more info on error handling
      console.error(JSON.stringify(e, null, 2))
    }
  }

  return (
    <div>
      <span>Your primary email address is {user?.primaryEmailAddress?.emailAddress}</span>

      <ul>
        {user?.emailAddresses.map((email) => (
          <li key={email.id}>
            <span>{email.emailAddress}</span>
            {email.id !== user?.primaryEmailAddress?.id && (
              <button onClick={() => handleClick(email.id)}>Make primary</button>
            )}
          </li>
        ))}
      </ul>
    </div>
  )
}
```

### Handle reverification for a fetcher function

The following example demonstrates how to use the `useReverification()` hook to enhance a fetcher function that fetches data from a route that requires reverification. For examples on how to set up a route that requires reverification, see the [guide on reverification](https://clerk.com/docs/guides/secure/reverification.md?sdk=chrome-extension).

filename: components/AccountBalance.tsx
```tsx
import { useAuth, useReverification } from '@clerk/chrome-extension'
import { isClerkRuntimeError, isReverificationCancelledError } from '@clerk/shared'
import { useState } from 'react'

export function AccountBalance() {
  const { getToken } = useAuth()
  const [balance, setBalance] = useState<number | null>(null)
  const accountBalance = useReverification(async () => {
    const response = await fetch('/api/balance', {
      headers: {
        Authorization: `Bearer ${await getToken()}`,
      },
    })
    return await response.json()
  })

  const handleClick = async () => {
    try {
      const accountBalanceResponse = await accountBalance()

      setBalance(accountBalanceResponse.amount)
    } catch (e) {
      // Handle if user cancels the reverification process
      if (isClerkRuntimeError(e) && isReverificationCancelledError(e)) {
        console.error('User cancelled reverification', e.code)
      }

      // Handle other errors
      // See https://clerk.com/docs/guides/development/custom-flows/error-handling
      // for more info on error handling
      console.error('Error fetching account balance', e)
    }
  }

  return (
    <div>
      <span>Your account balance is {balance ? `$${balance}` : '$******'}</span>
      <button onClick={() => handleClick()}>See account balance</button>
    </div>
  )
}
```

**Custom UI**

The following example demonstrates how to build a custom UI when using the `useReverification()` hook. In the example, the `useReverification()` hook is used to require a user to reverify their credentials before being able to update their primary email address. It requires two components: the `<UpdateUserEmail />` component displays the list of email addresses to choose from and it renders the second component, `<VerificationComponent />`, which handles the reverification process.

The example handles first factor verification using an email code, so you will need to have the [**Email verification code**](https://clerk.com/docs/guides/configure/auth-strategies/sign-up-sign-in-options.md?sdk=chrome-extension#email) setting enabled for your application. But you can adapt this example to handle any type of verification level or strategy.

**UpdateUserEmail**

The `<UpdateUserEmail />` component uses `useReverification()` to enhance the `update()` method, requiring the user to reverify their credentials before being able to update their primary email address.

The `useReverification()` hook provides the `onNeedsReverification` option, which is a handler for building a custom UI. It provides four properties: `level`, `complete`, `cancel`, and `inProgress`. The example tracks these using the `verificationState` state variable.

- The `level` property determines the verification level required for the reverification process. This example only handles first factor verification, which is done in the `<VerificationComponent>` component.
- The `complete` and `cancel` properties are the steps of the reverification process, which is also done in the `<VerificationComponent>` component.
- The `inProgress` property is used to track the state of the reverification process. When the user selects the "Make primary" button, it triggers the reverification process and sets the `inProgress` property is `true`, which displays the `<VerificationComponent>` component.

filename: components/UpdateUserEmail.tsx
```tsx
import { useReverification, useUser } from '@clerk/chrome-extension'
import { isClerkRuntimeError, isReverificationCancelledError } from '@clerk/shared'
import { useState } from 'react'
import type { SessionVerificationLevel } from '@clerk/shared/types'
import { VerificationComponent } from './VerificationComponent'

export function UpdateUserEmail() {
  // Use `useUser()` to get the current user's `User` object
  // `User` includes the `update()` method to update the user's primary email address
  const { user } = useUser()

  // TODO: Update to use exported type once available
  const [verificationState, setVerificationState] = useState<
    | {
        complete: () => void
        cancel: () => void
        level: SessionVerificationLevel | undefined
        inProgress: boolean
      }
    | undefined
  >(undefined)

  // Use `useReverification()` to enhance the `update()` method
  // to handle the reverification process
  const changePrimaryEmail = useReverification(
    (emailAddressId: string) => user?.update({ primaryEmailAddressId: emailAddressId }),
    {
      onNeedsReverification: ({ complete, cancel, level }) => {
        setVerificationState({
          complete,
          cancel,
          level,
          inProgress: true,
        })
      },
    },
  )

  const handleClick = async (emailAddressId: string) => {
    try {
      await changePrimaryEmail(emailAddressId)
    } catch (e) {
      // Handle if user cancels the reverification process
      if (isClerkRuntimeError(e) && isReverificationCancelledError(e)) {
        console.error('User cancelled reverification', e.code)
      }

      // Handle other errors
      // See https://clerk.com/docs/guides/development/custom-flows/error-handling
      // for more info on error handling
      console.error(JSON.stringify(e, null, 2))
    }
  }

  return (
    <div>
      <span>Your primary email address is {user?.primaryEmailAddress?.emailAddress}</span>

      <ul>
        {user?.emailAddresses.map((email) => (
          <li key={email.id}>
            <span>{email.emailAddress}</span>
            {user?.primaryEmailAddressId !== email.id && (
              <button onClick={() => handleClick(email.id)}>Make primary</button>
            )}
          </li>
        ))}
      </ul>

      {verificationState?.inProgress && (
        <VerificationComponent
          level={verificationState?.level}
          onComplete={() => {
            verificationState.complete()
            setVerificationState(undefined)
          }}
          onCancel={() => {
            verificationState.cancel()
            setVerificationState(undefined)
          }}
        />
      )}
    </div>
  )
}
```

**VerificationComponent**

The `<VerificationComponent />` component handles the reverification process. It uses the `level` property to determine the verification level, which is set to `first_factor`. First, it finds the determined starting first factor from the supported first factors. Then, it prepares the first factor verification using the `strategy` (`email_code` in this case) and `emailAddressId` properties. Finally, it attempts to verify the session with email code provided by the user. If the verification is successful, the `onComplete()` handler is called to complete the reverification process.

filename: components/VerificationComponent.tsx
```tsx
import { useEffect, useRef, useState } from 'react'
import { useSession } from '@clerk/chrome-extension'
import type {
  EmailCodeFactor,
  SessionVerificationLevel,
  SessionVerificationResource,
} from '@clerk/shared/types'

export function VerificationComponent({
  level = 'first_factor',
  onComplete,
  onCancel,
}: {
  level: SessionVerificationLevel | undefined
  onComplete: () => void
  onCancel: () => void
}) {
  const { session } = useSession()
  const [code, setCode] = useState<string>('')
  const reverificationRef = useRef<SessionVerificationResource | undefined>(undefined)
  const [determinedStartingFirstFactor, setDeterminedStartingFirstFactor] = useState<
    EmailCodeFactor | undefined
  >()

  useEffect(() => {
    if (reverificationRef.current) {
      return
    }

    session?.startVerification({ level }).then(async (response) => {
      reverificationRef.current = response
      await prepareEmailVerification(response)
    })
  }, [])

  const prepareEmailVerification = async (verificationResource: SessionVerificationResource) => {
    // To simplify the example we will only handle the first factor verification
    if (verificationResource.status === 'needs_first_factor') {
      // Determine the starting first factor from the supported first factors
      const determinedStartingFirstFactor = verificationResource.supportedFirstFactors?.filter(
        (factor) => factor.strategy === 'email_code',
      )[0]

      if (determinedStartingFirstFactor) {
        setDeterminedStartingFirstFactor(determinedStartingFirstFactor)
        // Prepare the first factor verification with the determined starting first factor
        await session?.prepareFirstFactorVerification({
          strategy: determinedStartingFirstFactor.strategy,
          emailAddressId: determinedStartingFirstFactor?.emailAddressId,
        })
      }
    }
  }

  const handleVerificationAttempt = async () => {
    try {
      // Attempt to verify the session with the provided code
      await session?.attemptFirstFactorVerification({
        strategy: 'email_code',
        code,
      })
      onComplete()
    } catch (e) {
      // Any error from the attempt to verify the session can be handled here
      console.error('Error verifying session', e)
    }
  }

  if (!determinedStartingFirstFactor) {
    return null
  }

  return (
    <div>
      <p>Enter verification code sent to {determinedStartingFirstFactor.safeIdentifier || ''}</p>
      <input type="number" name="code" onChange={(e) => setCode(e.target.value)} />
      <button onClick={async () => handleVerificationAttempt()}>Complete</button>
      <button onClick={() => onCancel()}>Cancel</button>
    </div>
  )
}
```

## Next steps

See the custom flow guides for examples of how to use the `useReverification()` hook, such as the [Add a phone number to a user's account](https://clerk.com/docs/guides/development/custom-flows/account-updates/add-phone.md?sdk=chrome-extension) guide.

---

## Sitemap

[Overview of all docs pages](https://clerk.com/docs/llms.txt)
