apple_sign_in_plugin 1.2.6 copy "apple_sign_in_plugin: ^1.2.6" to clipboard
apple_sign_in_plugin: ^1.2.6 copied to clipboard

A comprehensive Flutter package for integrating Apple Sign-In with features for secure authentication and user data management.

example/lib/main.dart

import 'package:apple_sign_in_plugin/apple_sign_in_plugin.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // Initialize the plugin with your specific credentials
  // correct key path and IDs are required for this to work
  await AppleSignInPlugin.initialize(
    pemKeyPath: 'assets/keys/apple_private_key.pem',
    keyId: 'YOUR_KEY_ID',
    teamId: 'YOUR_TEAM_ID',
    bundleId: 'YOUR_APP_BUNDLE_ID',
  );
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Apple Sign In Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.black),
        useMaterial3: true,
      ),
      home: const SignInPage(),
    );
  }
}

class SignInPage extends StatefulWidget {
  const SignInPage({super.key});

  @override
  State<SignInPage> createState() => _SignInPageState();
}

class _SignInPageState extends State<SignInPage> {
  AppleSignInResult? _result;
  bool _isLoggedIn = false;
  bool _isLoading = false;

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

  /// Checks if the user is already signed in (based on local storage).
  /// This allows the app to stay logged in across restarts.
  Future<void> _checkLoginStatus() async {
    final isSignedIn = AppleSignInPlugin.isSignedIn();
    setState(() {
      _isLoggedIn = isSignedIn;
    });
  }

  /// Initiates the Apple Sign-In flow.
  /// If successful, it returns the [AppleSignInResult] containing all tokens.
  Future<void> _signIn() async {
    setState(() => _isLoading = true);
    try {
      final result = await AppleSignInPlugin.signInWithApple();
      if (result != null) {
        setState(() {
          _result = result;
          _isLoggedIn = true;
        });
        if (kDebugMode) {
          print('Sign in success: ${result.email}');
          print('ID Token: ${result.idToken}');
          print('Access Token: ${result.accessToken}');
        }
      }
    } catch (e) {
      if (kDebugMode) {
        print('Sign in error: $e');
      }
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Sign in failed: $e')),
        );
      }
    } finally {
      if (mounted) {
        setState(() => _isLoading = false);
      }
    }
  }

  /// Signs out the user and revokes the token from Apple's server.
  Future<void> _signOut() async {
    setState(() => _isLoading = true);
    try {
      await AppleSignInPlugin.signOut();
      setState(() {
        _result = null;
        _isLoggedIn = false;
      });
    } catch (e) {
      if (kDebugMode) {
        print('Sign out error: $e');
      }
    } finally {
      if (mounted) {
        setState(() => _isLoading = false);
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Apple Sign In Plugin'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: Center(
        child: _isLoading
            ? const CircularProgressIndicator()
            : Padding(
                padding: const EdgeInsets.all(24.0),
                child: _isLoggedIn ? _buildUserProfile() : _buildLoginButton(),
              ),
      ),
    );
  }

  Widget _buildLoginButton() {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        const Icon(Icons.apple, size: 80),
        const SizedBox(height: 20),
        const Text(
          'Sign in to access your account',
          style: TextStyle(fontSize: 18),
        ),
        const SizedBox(height: 40),
        SizedBox(
          width: double.infinity,
          height: 50,
          child: ElevatedButton.icon(
            onPressed: _signIn,
            icon: const Icon(Icons.apple),
            label: const Text('Sign in with Apple'),
            style: ElevatedButton.styleFrom(
              backgroundColor: Colors.black,
              foregroundColor: Colors.white,
            ),
          ),
        ),
      ],
    );
  }

  Widget _buildUserProfile() {
    return SingleChildScrollView(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const Center(child: Icon(Icons.account_circle, size: 80)),
          const SizedBox(height: 30),
          const Text('User Details:',
              style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
          const Divider(),
          if (_result != null) ...[
            _userInfoRow('Name',
                '${_result?.givenName ?? ''} ${_result?.familyName ?? ''}'),
            _userInfoRow('Email', _result?.email ?? 'N/A'),
            _userInfoRow(
                'User ID',
                _result?.userIdentifier != null
                    ? '${_result!.userIdentifier!.substring(0, 5)}...'
                    : 'N/A'),
            const Divider(),
            const Text('Backend Tokens:',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
            const SizedBox(height: 10),
            _tokenInfoRow('ID Token (JWT)', _result?.idToken),
            _tokenInfoRow('Access Token', _result?.accessToken),
            _tokenInfoRow('Refresh Token', _result?.refreshToken),
          ] else
            const Text('Session active (details pending fresh login)'),
          const SizedBox(height: 40),
          SizedBox(
            width: double.infinity,
            height: 50,
            child: OutlinedButton.icon(
              onPressed: _signOut,
              icon: const Icon(Icons.logout),
              label: const Text('Sign Out'),
              style: OutlinedButton.styleFrom(
                foregroundColor: Colors.red,
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _userInfoRow(String label, String value) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 8.0),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          SizedBox(
            width: 80,
            child: Text(
              '$label:',
              style: const TextStyle(fontWeight: FontWeight.bold),
            ),
          ),
          Expanded(child: Text(value)),
        ],
      ),
    );
  }

  Widget _tokenInfoRow(String label, String? token) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 4.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('$label:', style: const TextStyle(fontWeight: FontWeight.bold)),
          Container(
            width: double.infinity,
            padding: const EdgeInsets.all(8),
            decoration: BoxDecoration(
              color: Colors.grey[200],
              borderRadius: BorderRadius.circular(4),
            ),
            child: Text(
              token != null
                  ? (token.length > 20
                      ? '${token.substring(0, 20)}...[truncated]'
                      : token)
                  : 'Not available',
              style: const TextStyle(fontFamily: 'Courier', fontSize: 12),
            ),
          ),
        ],
      ),
    );
  }
}
14
likes
150
points
342
downloads

Publisher

unverified uploader

Weekly Downloads

A comprehensive Flutter package for integrating Apple Sign-In with features for secure authentication and user data management.

Repository (GitHub)
View/report issues

Documentation

Documentation
API reference

License

MIT (license)

Dependencies

flutter, get_storage, http, jose, sign_in_with_apple

More

Packages that depend on apple_sign_in_plugin