---
title: Authentication flows
description: Learn how to handle sign-in, sign-up, MFA, password reset, and session management with the Clerk Flutter SDK.
---

The Flutter SDK provides pre-built widgets that handle authentication flows automatically, as well as a lower-level API for building custom UI.

## Pre-built authentication UI

The `ClerkAuthentication` widget handles sign-in and sign-up flows, including OAuth, MFA, and password reset, with no additional code required.

```dart
ClerkAuthentication()
```

Place it anywhere in your widget tree when the user is signed out. Wrap your app with `ClerkAuth` to provide the auth state.

```dart
ClerkAuth(
  config: ClerkAuthConfig(publishableKey: 'pk_...'),
  child: ClerkAuthBuilder(
    signedInBuilder: (context, auth) => const HomeScreen(),
    signedOutBuilder: (context, auth) => const ClerkAuthentication(),
  ),
)
```

---

For custom UI, access the auth state with `ClerkAuth.of(context)` and use the methods below.

## Sign in

The `attemptSignIn` method is progressive — call it repeatedly with updated parameters as the user moves through each step of the flow.

### Sign in with password

The following example demonstrates how to sign in with an identifier (email, phone, or username) and password.

```dart
final auth = ClerkAuth.of(context);

await auth.attemptSignIn(
  strategy: Strategy.password,
  identifier: 'user@email.com',
  password: 'secretpassword',
);
```

### Sign in with OTP (email)

The following example demonstrates how to send an OTP to the user's email and verify the code.

```dart
final auth = ClerkAuth.of(context);

// Send the code
await auth.attemptSignIn(
  strategy: Strategy.emailCode,
  identifier: 'user@email.com',
);

// Verify the code
await auth.attemptSignIn(
  strategy: Strategy.emailCode,
  code: '123456',
);
```

### Sign in with OTP (phone)

The following example demonstrates how to send an OTP to the user's phone number and verify the code.

```dart
final auth = ClerkAuth.of(context);

// Send the code
await auth.attemptSignIn(
  strategy: Strategy.phoneCode,
  identifier: '+1234567890',
);

// Verify the code
await auth.attemptSignIn(
  strategy: Strategy.phoneCode,
  code: '123456',
);
```

### Sign in with email link

The following example demonstrates how to send a magic link to the user's email. The link will be polled automatically.

```dart
final auth = ClerkAuth.of(context);

await auth.attemptSignIn(
  strategy: Strategy.emailLink,
  identifier: 'user@email.com',
  redirectUrl: 'yourapp://clerk/callback',
);
```

### Sign in with OAuth

The following example demonstrates how to sign in using an OAuth provider (e.g., Google, GitHub).

```dart
final auth = ClerkAuth.of(context);

await auth.ssoSignIn(context, Strategy.oauthGoogle);
```

The SDK handles the OAuth redirect flow in-app using a WebView by default. To handle the redirect externally (e.g., via a deep link), configure a `redirectionGenerator` in `ClerkAuthConfig`.

### Sign in with ID token

The following example demonstrates how to sign in with an ID token from an identity provider (e.g., Apple).

```dart
final auth = ClerkAuth.of(context);

await auth.idTokenSignIn(
  provider: IdTokenProvider.apple,
  token: credential.identityToken,
);

// If the user doesn't exist, transfer to sign-up
if (auth.signIn?.isTransferable == true) {
  await auth.transfer();
}
```

### Sign in with passkey

The following example demonstrates how to sign in using a passkey.

```dart
final auth = ClerkAuth.of(context);

await auth.attemptSignIn(strategy: Strategy.passkey);
```

### Sign in with Enterprise SSO

The following example demonstrates how to sign in using Enterprise SSO.

```dart
final auth = ClerkAuth.of(context);

await auth.ssoSignIn(context, Strategy.enterpriseSSO);
```

### Multi-factor authentication

After the first factor is verified, if MFA is required, call `attemptSignIn` again with the second factor strategy.

#### MFA with phone code

The following example demonstrates how to send an SMS code and verify it as the second factor.

```dart
// Send the SMS code
await auth.attemptSignIn(strategy: Strategy.phoneCode);

// Verify the code
await auth.attemptSignIn(
  strategy: Strategy.phoneCode,
  code: '123456',
);
```

#### MFA with email code

The following example demonstrates how to send an email code and verify it as the second factor.

```dart
// Send the email code
await auth.attemptSignIn(strategy: Strategy.emailCode);

// Verify the code
await auth.attemptSignIn(
  strategy: Strategy.emailCode,
  code: '123456',
);
```

#### MFA with TOTP (authenticator app)

The following example demonstrates how to verify the TOTP code from the user's authenticator app.

```dart
await auth.attemptSignIn(
  strategy: Strategy.totp,
  code: '123456',
);
```

#### MFA with backup code

The following example demonstrates how to sign in using one of the user's backup codes.

```dart
await auth.attemptSignIn(
  strategy: Strategy.backupCode,
  code: 'backup-code',
);
```

#### Resend a code

The following example demonstrates how to resend the OTP or sign-in code for the current strategy.

```dart
await auth.resendCode(Strategy.phoneCode);
```

### Password reset

#### Password reset with email

The following example demonstrates how to send a reset code to the user's email, verify it, and set the new password.

```dart
final auth = ClerkAuth.of(context);

// Initiate reset and send code
await auth.initiatePasswordReset(
  identifier: 'user@email.com',
  strategy: Strategy.resetPasswordEmailCode,
);

// Verify the code and set the new password
await auth.attemptSignIn(
  strategy: Strategy.resetPasswordEmailCode,
  code: '123456',
  password: 'newpassword',
);
```

#### Password reset with phone

The following example demonstrates how to send a reset code to the user's phone number, verify it, and set the new password.

```dart
final auth = ClerkAuth.of(context);

// Initiate reset and send code
await auth.initiatePasswordReset(
  identifier: '+1234567890',
  strategy: Strategy.resetPasswordPhoneCode,
);

// Verify the code and set the new password
await auth.attemptSignIn(
  strategy: Strategy.resetPasswordPhoneCode,
  code: '123456',
  password: 'newpassword',
);
```

## Sign up

The `attemptSignUp` method is progressive — call it repeatedly with updated parameters until the user is fully signed up.

### Create a new sign-up

The following example demonstrates how to start a sign-up. Only include fields required by your instance configuration.

```dart
final auth = ClerkAuth.of(context);

await auth.attemptSignUp(
  emailAddress: 'newuser@email.com',
  password: 'secretpassword',
  firstName: 'John',
  lastName: 'Doe',
  username: 'johndoe',
  phoneNumber: '+1234567890',
);
```

### Verify email via OTP

The following example demonstrates how to verify an email address after sign-up using an OTP code.

```dart
// Send the verification code (triggered automatically by attemptSignUp,
// or call again with the emailCode strategy)
await auth.attemptSignUp(strategy: Strategy.emailCode);

// Verify the code
await auth.attemptSignUp(
  strategy: Strategy.emailCode,
  code: '123456',
);
```

### Verify phone via OTP

The following example demonstrates how to send a verification code to the user's phone number and verify it.

```dart
// Send the verification code
await auth.attemptSignUp(strategy: Strategy.phoneCode);

// Verify the code
await auth.attemptSignUp(
  strategy: Strategy.phoneCode,
  code: '123456',
);
```

### Sign up with OAuth

The following example demonstrates how to sign up using an OAuth provider (e.g., Google, GitHub).

```dart
final auth = ClerkAuth.of(context);

await auth.ssoSignUp(context, Strategy.oauthGoogle);
```

### Sign up with ID token

The following example demonstrates how to sign up with an ID token from an identity provider (e.g., Apple).

```dart
final auth = ClerkAuth.of(context);

await auth.idTokenSignUp(
  provider: IdTokenProvider.apple,
  idToken: credential.identityToken!,
  firstName: credential.givenName,
  lastName: credential.familyName,
);

// If the user already exists, transfer to sign-in
if (auth.signUp?.isTransferable == true) {
  await auth.transfer();
}
```

### Sign up with Enterprise SSO

The following example demonstrates how to sign up using Enterprise SSO.

```dart
final auth = ClerkAuth.of(context);

await auth.ssoSignUp(context, Strategy.enterpriseSSO);
```

## Current sign-in/sign-up

Access the in-progress sign-in or sign-up for multi-step flows.

### Current sign-in

The following example demonstrates how to access the in-progress sign-in object.

```dart
final signIn = ClerkAuth.of(context).signIn;
```

### Current sign-up

The following example demonstrates how to access the in-progress sign-up object.

```dart
final signUp = ClerkAuth.of(context).signUp;
```

## Session management

### Sessions

The following example demonstrates how to retrieve all sessions for the current client.

```dart
final sessions = ClerkAuth.of(context).client.sessions;
```

### Get session token

The following example demonstrates how to retrieve the current session token to authenticate requests to your backend.

```dart
final auth = ClerkAuth.of(context);
final tokenObj = await auth.sessionToken();
final token = tokenObj.jwt;
```

You can also listen to the `sessionTokenStream` for token renewals.

```dart
auth.sessionTokenStream.listen((token) {
  // Use token.jwt to authenticate requests
});
```

### Set active session

The following example demonstrates how to switch to a different session.

```dart
final auth = ClerkAuth.of(context);

final session = auth.client.sessions.firstOrNull;
if (session == null) return;

await auth.activate(session);
```

### Set active organization

The following example demonstrates how to set the active organization for the current session.

```dart
final auth = ClerkAuth.of(context);

final organization = auth.user?.organizationMemberships?.firstOrNull?.organization;
if (organization == null) return;

await auth.setActiveOrganization(organization);
```

### Sign out

The following example demonstrates how to sign out the current user from all sessions, or from a specific session.

```dart
final auth = ClerkAuth.of(context);

// Sign out from all sessions
await auth.signOut();

// Sign out from a specific session
final session = auth.session;
await auth.signOutOf(session!);
```
