Skip to main content
This guide demonstrates how to integrate Auth0 with a Flutter application using the Auth0 Flutter SDK. This guide covers setup for Android, iOS, macOS, and Web platforms.

Get Started

1

Create a new Flutter project

Create a new Flutter project for this quickstart.In your terminal:
  1. Navigate to your workspace directory
  2. Run: flutter create auth0_flutter_sample
  3. Navigate into the project: cd auth0_flutter_sample
  4. Open in your IDE:
    • VS Code: code .
    • Android Studio: open -a "Android Studio" .
# Create new Flutter project
flutter create auth0_flutter_sample

# Navigate into project directory
cd auth0_flutter_sample

# Open in VS Code
code .
This creates a modern Flutter app with the latest project structure. Run flutter doctor to verify your environment is set up correctly.
2

Install the Auth0 Flutter SDK

Add the Auth0 Flutter SDK to your project using the Flutter CLI.
flutter pub add auth0_flutter
This will add auth0_flutter to your pubspec.yaml dependencies:
pubspec.yaml
dependencies:
  auth0_flutter: ^2.0.0-beta.1
The Auth0 Flutter SDK requires Flutter 3.24.0+ and Dart 3.5.0+. Run flutter doctor to verify your environment meets these requirements.
3

Setup your Auth0 App

Next up, you need to create a new app on your Auth0 tenant and configure the callback URLs.
  1. Head to the Auth0 Dashboard
  2. Click on Applications > Applications > Create Application
  3. In the popup, enter a name for your app, select Native as the app type (or Single Page Application for web-only) and click Create
  4. Switch to the Settings tab on the Application Details page
  5. Note down the Domain and Client ID values - you’ll need these later
On the Settings tab, configure the following URLs based on your target platform(s):Allowed Callback URLs:
https://{yourDomain}/android/{yourPackageName}/callback
Allowed Logout URLs:Add the same URLs from the callback configuration above to the Allowed Logout URLs field.Allowed Web Origins (Web Only):If targeting the web platform, add your application URL:
http://localhost:3000
Allowed Callback URLs are a critical security measure to ensure users are safely returned to your application after authentication. Without a matching URL, the login process will fail.Allowed Logout URLs are essential for providing a seamless user experience upon signing out. Without a matching URL, users will not be redirected back to your application after logout.For example, if your Auth0 domain is example.us.auth0.com and your Android package name is com.example.myapp, your Android callback URL would be: https://example.us.auth0.com/android/com.example.myapp/callback
Important: Ensure the package name (Android) or bundle identifier (iOS/macOS) in your callback URLs matches your actual app identifier. If authentication fails, verify these values are identical.
4

Configure Your Application

Platform-specific configuration is required to enable the authentication flow. Follow the instructions for each platform you’re targeting.
Open the android/app/build.gradle file and add the following manifest placeholders inside android > defaultConfig:
android/app/build.gradle
android {
    // ...
    defaultConfig {
        // Add the following line
        manifestPlaceholders += [auth0Domain: "{yourDomain}", auth0Scheme: "https"]
    }
    // ...
}
Replace {yourDomain} with your Auth0 domain (e.g., example.us.auth0.com).https schemeTo use https scheme for your callback url, set up Android app links for your application.For Biometric Authentication (Optional):If you plan to use biometric authentication, update your MainActivity.kt to extend FlutterFragmentActivity:
android/app/src/main/kotlin/.../MainActivity.kt
import io.flutter.embedding.android.FlutterFragmentActivity

class MainActivity: FlutterFragmentActivity() {
}
Android: Ensure the auth0Domain value matches your Auth0 domain exactly. If authentication fails, verify this value is identical to the domain shown in your Auth0 Dashboard.iOS/macOS: Universal Links require a paid Apple Developer account and iOS 17.4+/macOS 14.4+. On older versions, the SDK automatically falls back to custom URL schemes.
5

Implement Login and Logout

Universal Login is the easiest way to set up authentication in your application. We recommend using it for the best experience, best security, and the fullest array of features.Implement Login:
Import the Auth0 Flutter SDK and create an Auth0 instance:
lib/auth_service.dart
import 'package:auth0_flutter/auth0_flutter.dart';

class AuthService {
  final auth0 = Auth0('{yourDomain}', '{yourClientId}');
  
  Future<Credentials> login() async {
    final credentials = await auth0.webAuthentication().login(useHTTPS: true);
    
    // Access token -> credentials.accessToken
    // ID token -> credentials.idToken
    // User profile -> credentials.user
    
    return credentials;
  }
}
Implement Logout:
lib/auth_service.dart
Future<void> logout() async {
  await auth0.webAuthentication().logout(useHTTPS: true);
  
  // User is now logged out
  // Credentials have been cleared from secure storage
}
iOS/macOS: The useHTTPS: true parameter enables Universal Links on iOS 17.4+ and macOS 14.4+ for enhanced security.Android: if you are using a custom scheme, pass this scheme to the login method so that the SDK can route to the login page and back again correctly:
lib/auth_service.dart
await auth0.webAuthentication(scheme: 'YOUR CUSTOM SCHEME').login();
Web: You must call onLoad() when your application starts. This handles the redirect callback from Auth0 and restores the user’s session if they’re already authenticated.
6

Show User Profile Information

The user profile is automatically retrieved when the user logs in. The Credentials object contains a user property with all the user profile information, populated by decoding the ID token.
lib/profile_screen.dart
void displayUserProfile(Credentials credentials) {
  final user = credentials.user;
  
  print('User ID: ${user.sub}');
  print('Email: ${user.email}');
  print('Name: ${user.name}');
  print('Picture: ${user.pictureUrl}');
  print('Nickname: ${user.nickname}');
}
Request the appropriate scopes during login to access specific user profile fields. The default scopes are openid, profile, email, and offline_access.
7

Run your app

Build and run your Flutter application.In your terminal:
# List available devices
flutter devices

# Run on Android
flutter run -d android

# Run on iOS Simulator
flutter run -d ios

# Run on Web (use port 3000 to match callback URLs)
flutter run -d chrome --web-port 3000
Expected flow:
  1. App launches with your login UI
  2. User taps Log In → Browser/Custom Tab opens with Auth0 Universal Login
  3. User completes authentication
  4. Browser redirects back to your app
  5. User is now authenticated and credentials are stored
Make sure to use port 3000 when running the web app to match the callback URLs configured in Auth0. You can change this port, but ensure it matches your Auth0 configuration.
CheckpointYou should now have a fully functional Auth0 login experience in your Flutter application. The app uses secure browser-based authentication and automatically stores credentials for session persistence.

Troubleshooting & Advanced Usage

Callback URL Mismatch

Symptom: Error “redirect_uri_mismatch” or authentication fails silently.Solutions:
  1. Check Allowed Callback URLs in Auth0 Dashboard match your app configuration exactly
  2. Verify the scheme (https:// vs http://)
  3. Ensure the package name (Android) or bundle identifier (iOS/macOS) is correct
  4. Check for trailing slashes

Android: Chrome Custom Tab Doesn’t Open

Symptom: Nothing happens when calling login().Fix:
  1. Verify manifestPlaceholders are correctly set in build.gradle
  2. Ensure internet permission is in AndroidManifest.xml:
    <uses-permission android:name="android.permission.INTERNET" />
    
  3. Check that Chrome or another browser is installed on the device

iOS: “Open in App” Alert

Symptom: Alert box appears asking to open in your app.Fix: This is expected behavior with ASWebAuthenticationSession. To remove it:
  • Use Universal Links (requires iOS 17.4+ and paid Apple Developer account)
  • Or set useEphemeralSession: true (disables SSO):
await auth0.webAuthentication().login(
  useHTTPS: true,
  useEphemeralSession: true,
);

Web: User Logged Out on Page Refresh

Symptom: User appears logged out after refreshing the page.Fix:
  1. Ensure onLoad() is called during app initialization
  2. Try using localStorage for cache location:
    final auth0Web = Auth0Web(
      '{yourDomain}',
      '{yourClientId}',
      cacheLocation: CacheLocation.localStorage,
    );
    
  3. Ensure your domain is added to Allowed Web Origins in Auth0 Dashboard

Web: “Must run on a secure origin” Error

Symptom: Error about secure origin in browser console.Fix: The Auth0 SPA SDK requires a secure context. Use localhost (which is treated as secure) or deploy to an HTTPS domain.

Authentication cancelled by user

Handle gracefully in your error handling:
try {
  final credentials = await auth0.webAuthentication().login(useHTTPS: true);
  // Handle successful login
} on WebAuthenticationException catch (e) {
  if (e.code == 'USER_CANCELLED') {
    showMessage('Login was cancelled');
  } else {
    showMessage('Login failed: ${e.message}');
  }
}
The Auth0 Flutter SDK includes a built-in Credentials Manager that securely stores user credentials. On mobile platforms, credentials are encrypted and stored in the platform’s secure storage (Keychain on iOS/macOS, encrypted SharedPreferences on Android).

Check for Stored Credentials

Before prompting the user to log in, check if valid credentials already exist:
lib/auth_service.dart
Future<bool> checkAuthentication() async {
  if (kIsWeb) {
    return await auth0Web.hasValidCredentials();
  } else {
    return await auth0.credentialsManager.hasValidCredentials();
  }
}

Retrieve Stored Credentials

Retrieve credentials to access tokens or user information. The Credentials Manager automatically refreshes expired tokens when possible:
lib/auth_service.dart
Future<Credentials> getCredentials() async {
  if (kIsWeb) {
    return await auth0Web.credentials();
  } else {
    return await auth0.credentialsManager.credentials();
  }
}
You don’t need to manually store credentials after login—the SDK handles this automatically. You also don’t need to manually refresh tokens; the Credentials Manager refreshes them when needed.
Handle authentication errors gracefully to provide a good user experience.

Mobile/macOS Errors

lib/auth_service.dart
import 'package:auth0_flutter/auth0_flutter.dart';

Future<void> login() async {
  try {
    final credentials = await auth0.webAuthentication().login(useHTTPS: true);
    // Handle successful login
  } on WebAuthenticationException catch (e) {
    if (e.code == 'USER_CANCELLED') {
      // User cancelled the login
      print('Login cancelled by user');
    } else {
      // Handle other errors
      print('Login error: ${e.message}');
    }
  }
}

Future<Credentials> getCredentials() async {
  try {
    return await auth0.credentialsManager.credentials();
  } on CredentialsManagerException catch (e) {
    if (e.isNoCredentialsFound) {
      // No stored credentials, user needs to log in
      throw Exception('Please log in first');
    } else if (e.isTokenRenewFailed) {
      // Refresh token expired, re-authentication required
      return await auth0.webAuthentication().login(useHTTPS: true);
    }
    rethrow;
  }
}

Web Errors

lib/web_auth_service.dart
import 'package:auth0_flutter/auth0_flutter_web.dart';

Future<void> login() async {
  try {
    await auth0Web.loginWithRedirect(redirectUrl: 'http://localhost:3000');
  } on WebException catch (e) {
    print('Login error: ${e.message}');
  }
}

Enhanced Credential Security with Biometrics

Implement biometric authentication for credential access on mobile:
lib/secure_auth_service.dart
class SecureAuthService {
  final auth0 = Auth0('{yourDomain}', '{yourClientId}');
  
  Future<void> enableBiometrics() async {
    // Enable local authentication (Face ID, Touch ID, Fingerprint)
    await auth0.credentialsManager.enableLocalAuthentication(
      title: 'Authenticate to access your account',
      cancelTitle: 'Cancel',
      fallbackTitle: 'Use passcode',
    );
  }
  
  Future<Credentials> getCredentialsWithBiometrics() async {
    // This will now require biometric authentication
    return await auth0.credentialsManager.credentials();
  }
}
Android: Requires MainActivity to extend FlutterFragmentActivity as configured in Step 4.iOS/macOS: Requires adding NSFaceIDUsageDescription to your Info.plist.

Custom Scopes and Audience

Request specific scopes and audience for your API:
lib/auth_service.dart
Future<Credentials> loginWithCustomScopes() async {
  return await auth0.webAuthentication().login(
    useHTTPS: true,
    scopes: {'openid', 'profile', 'email', 'offline_access', 'read:posts'},
    audience: 'https://myapi.example.com',
    parameters: {'prompt': 'login'},
  );
}

Organizations (B2B/Enterprise)

Authenticate users within a specific organization:
lib/auth_service.dart
Future<Credentials> loginWithOrganization(String organizationId) async {
  return await auth0.webAuthentication().login(
    useHTTPS: true,
    organizationId: organizationId,
  );
}

// Or prompt user to select an organization
Future<Credentials> loginWithOrganizationName(String organizationName) async {
  return await auth0.webAuthentication().login(
    useHTTPS: true,
    organizationName: organizationName,
  );
}

App Store Preparation

  • Configure Universal Links (iOS) and App Links (Android) for seamless authentication
  • Test on multiple device sizes and OS versions
  • Implement proper error handling for network failures
  • Add ProGuard rules for Android if using code obfuscation
  • Follow platform-specific App Store/Play Store policies

Security Considerations

  • Use the built-in Credentials Manager for production credential storage
  • Enable biometric authentication for sensitive operations
  • Consider certificate pinning for additional API security
  • Implement proper token refresh handling
  • Use useHTTPS: true for Universal Links on supported platforms

Next Steps

Check out the EXAMPLES.md file in the SDK repository for comprehensive code examples covering advanced scenarios like DPoP, biometric authentication, passwordless login and many more features.