> ## Documentation Index
> Fetch the complete documentation index at: https://docs.privy.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Require MFA on every app session

> Clear MFA state when your app is backgrounded so users must re-verify on their next session

By default, Privy caches the MFA token after verification and skips re-prompting until it expires.
Apps that need fresh verification on every launch can clear the cached token whenever the app moves
to the background. A trading app, for example, might treat each app open as a new security session.

This recipe uses React Native's `AppState` API and Privy's `clear` method from `useMfa` to tie MFA
verification to app session lifecycle.

## How it works

1. The user opens the app, authenticates, and proceeds normally. Wallet actions trigger MFA as usual.
2. When the user backgrounds the app, `clear()` invalidates the cached MFA token.
3. When the user returns and performs a wallet action, Privy finds no valid token and prompts for
   fresh verification.

## Implementation

Register an `AppState` listener in a component near the root of your app. When the app leaves the
`active` state — backgrounded or inactive — clear the MFA token:

```tsx theme={"system"}
import {useEffect} from 'react';
import {AppState} from 'react-native';
import {useMfa} from '@privy-io/expo';

export default function AppSessionMfaGuard() {
  const {clear} = useMfa();

  useEffect(() => {
    const subscription = AppState.addEventListener('change', (nextState) => {
      if (nextState !== 'active') {
        clear();
      }
    });

    return () => subscription.remove();
  }, [clear]);

  return null;
}
```

Render `<AppSessionMfaGuard />` inside `PrivyProvider`, near the root of your app:

```tsx theme={"system"}
import {PrivyProvider} from '@privy-io/expo';
import AppSessionMfaGuard from './AppSessionMfaGuard';

export default function App() {
  return (
    <PrivyProvider appId="your-privy-app-id" clientId="your-privy-client-id">
      <AppSessionMfaGuard />
      {/* rest of your app */}
    </PrivyProvider>
  );
}
```

## Proactively prompting on app resume

Wallet actions naturally re-trigger MFA after `clear()`. To prompt immediately on foreground
instead, call `prompt()` when the app returns to `active`:

```tsx theme={"system"}
import {useEffect, useRef} from 'react';
import {AppState, AppStateStatus} from 'react-native';
import {useMfa} from '@privy-io/expo';

export default function AppSessionMfaGuard() {
  const {clear, prompt} = useMfa();
  const appState = useRef<AppStateStatus>(AppState.currentState);

  useEffect(() => {
    const subscription = AppState.addEventListener('change', async (nextState) => {
      const previousState = appState.current;
      appState.current = nextState;

      if (nextState !== 'active') {
        // App is going to the background — clear the cached MFA token
        clear();
      } else if (previousState !== 'active' && nextState === 'active') {
        // App is returning to the foreground — proactively prompt for MFA
        await prompt();
      }
    });

    return () => subscription.remove();
  }, [clear, prompt]);

  return null;
}
```

<Note>
  `prompt()` no-ops when the user has no MFA methods enrolled. Because `clear()` runs on every
  background event, there is never a cached token on resume. The user is always prompted.
</Note>

## Extending the cache duration

By default, MFA tokens stay valid for 15 minutes. For a session-based approach, a longer cache
prevents mid-session expiry. `clear()` then handles explicit invalidation on background.

Configure the MFA token duration in the
[Privy Dashboard](https://dashboard.privy.io/admin/mfa-cache-duration). Setting a value of several
hours ensures no mid-session re-prompts while the user is active.

## iOS background constraints

On iOS, apps that move to the background have limited time before execution suspends. `clear()` makes
no network requests and operates only on local state. It completes reliably within iOS background
execution limits.
