> ## Documentation Index
> Fetch the complete documentation index at: https://turnkey-0e7c1f5b-traian-remove-eip-712-note.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

> Learn how to set up, log in, or sign up easily in your Flutter app using Turnkey's Flutter SDK.

export const FeatureCard = ({title, description, icon, logo, href}) => {
  return <a href={href} className="not-prose font-normal group ring-0 ring-transparent cursor-pointer block rounded-lg border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-transparent p-5 no-underline hover:border-primary/40 transition-colors">
      <div className="tk-card-row">
        <span className="tk-card-icon-wrap">
          {logo ? <img src={`/images/networks/${logo}.svg`} className="tk-card-network-logo" alt="" /> : <span className="tk-card-icon" style={{
    maskImage: `url(/images/icons/${icon}.svg)`,
    WebkitMaskImage: `url(/images/icons/${icon}.svg)`
  }} />}
        </span>
        <div>
          <div className="font-semibold text-sm text-zinc-950 dark:text-white group-hover:text-primary transition-colors">
            {title}
          </div>
          {description && <div className="text-sm text-zinc-500 dark:text-zinc-400 mt-1">
              {description}
            </div>}
        </div>
      </div>
    </a>;
};

Turnkey's Flutter SDK makes authentication simple. You can call specific login and signup functions (email/SMS OTP, passkeys, or social logins) to build your own UI and auth flow.

## Authentication state

To check if a user is authenticated, you can use the `authState` variable from the `TurnkeyProvider`.

`authState` can be one of the following:

* `AuthState.authenticated`: The user has a stored session.
* `AuthState.unauthenticated`: The user does not have a stored session.
* `AuthState.loading`: The provider is initializing. Turnkey is checking for any existing stored sessions or restoring state. UI should show a splash or progress indicator.

You can consume `authState` in any widget using a `Consumer<TurnkeyProvider>`:

```dart title=lib/widgets/auth_status.dart theme={null}
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:turnkey_sdk_flutter/turnkey_sdk_flutter.dart';

class AuthStatus extends StatelessWidget {
  const AuthStatus({super.key});

  @override
  Widget build(BuildContext context) {
    return Consumer<TurnkeyProvider>(
      builder: (context, tk, _) {
        switch (tk.authState) {
          case AuthState.loading:
            return const Center(
              child: CircularProgressIndicator(),
            );

          case AuthState.unauthenticated:
            return ElevatedButton(
              onPressed: () {
                // Navigate to your login screen or trigger your chosen auth flow
                Navigator.of(context).pushNamed('/login');
              },
              child: const Text('Log in'),
            );

          case AuthState.authenticated:
            final user = tk.user;
            return Text('Welcome back, ${user?.userName ?? 'user'}!');
        }
      },
    );
  }
}
```

You can also set up an `onSessionSelected` callback in `TurnkeyConfig` to handle post-authentication logic, such as redirecting.

```dart title=snippet (in main.dart where you construct TurnkeyProvider) theme={null}
final turnkeyProvider = TurnkeyProvider(
  config: TurnkeyConfig(
    // ... your existing config ...
    onSessionSelected: (session) {
      // User authenticated — perform navigation or data preloads
      navigatorKey.currentState?.pushReplacementNamed('/dashboard');
    },
  ),
);
```

## Listening to provider updates

`TurnkeyProvider` is a `ChangeNotifier`, so you can attach listeners to respond to internal state changes (e.g., when user/wallets are fetched or when `authState` changes). This pattern is useful when you want to mirror provider data into local widget state.

Below is an example (adapted from the [demo app](https://github.com/tkhq/dart-sdk/tree/main/examples/flutter-demo-app)) that keeps a local `selectedWallet`/`selectedAccount` in sync with the provider:

```dart title=lib/screens/dashboard.dart (excerpt) theme={null}
class DashboardScreenState extends State<DashboardScreen> {
  Wallet? _selectedWallet;
  v1WalletAccount? _selectedAccount;

  late final TurnkeyProvider _turnkeyProvider;
  late final VoidCallback _providerListener;

  @override
  void initState() {
    super.initState();

    // Capture provider once; no context in listener later.
    _turnkeyProvider = Provider.of<TurnkeyProvider>(context, listen: false);

    _providerListener = _handleProviderUpdate;
    _turnkeyProvider.addListener(_providerListener);

    // Initialize local selections from provider.
    _updateSelectedWalletFromProvider(_turnkeyProvider);
  }

  @override
  void dispose() {
    // Always remove listeners to avoid calling setState on a disposed widget.
    _turnkeyProvider.removeListener(_providerListener);
    super.dispose();
  }

  void _handleProviderUpdate() {
    if (!context.mounted) return;
    _updateSelectedWalletFromProvider(_turnkeyProvider);
  }

  void _updateSelectedWalletFromProvider(TurnkeyProvider provider) {
    final wallets = provider.wallets;
    final user = provider.user;

    if (user == null || wallets == null || wallets.isEmpty) return;
    if (wallets.first.accounts.isEmpty) return;

    if (!context.mounted) return;
    setState(() {
      _selectedWallet = wallets.first;
      _selectedAccount = wallets.first.accounts.first;
    });
  }
}
```

> **Tips**
>
> * Use `addListener/removeListener` for one-off reactions to state changes.
> * Use `Consumer`, `Selector`, or `context.select` when you want automatic rebuilds based on specific slices of provider state.
> * Avoid calling `setState` inside your listener after the widget is disposed — always guard with `if (!mounted) return;` or `if (!context.mounted) return;`.

## Customize sub-organization creation

Need to configure default user names, passkey names, wallet creations or anything sub-org related? You can learn more about customizing the sub-orgs you create in the [Sub-Organization Customization](/solutions/embedded-wallets/integration-guide/flutter/sub-organization-customization).

Follow the guides below to learn how to set up email and SMS authentication, passkey authentication, and social logins in your Flutter app.

<div style={{display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '12px'}}>
  <FeatureCard title="Email & SMS" icon="lock-01" href="/solutions/embedded-wallets/integration-guide/flutter/authentication/email-sms" description="Set up email and SMS authentication in your Flutter app." />

  <FeatureCard title="Passkey Authentication" icon="lock-01" href="/solutions/embedded-wallets/integration-guide/flutter/authentication/passkey" description="Set up passkey authentication in your Flutter app." />

  <FeatureCard title="Social Logins" icon="lock-01" href="/solutions/embedded-wallets/integration-guide/flutter/authentication/social-logins" description="Add social logins (Google, Apple, X, Discord) with wallet creation and account derivation." />
</div>
