🐶

FlutterとFirebaseでメール認証を作ってみた

2020/10/28に公開

これはなに?

FlutterでFirebaseを使った認証系であまり記事がなかったのでYoutubeを参考にしながら設計してみました。
ちょっとずつアップデートしながら書いてます、説明足りない箇所があるとは思いますがご容赦ください🙏

この記事で説明しないこと

  • Firebaseの導入方法

作ったもの

アプリの流れ

1

起動するとWrapperでログイン状況を確認
ユーザ情報がnullでなければホーム画面に遷移、nullであればログイン画面を表示

2

ログイン画面ではメールアドレスとパスワードを要求
右上のボタンで新規登録画面とログイン画面を切り替えられる

3

ログイン後はFlutterで毎度お馴染みのカウンター画面とログアウトボタンが表示されている

パッケージの準備

  #  FIREBASE
  firebase_core: ^0.5.0
  firebase_auth: ^0.18.0+1

認証系

ログイン

  Future signInWithEmailAndPassword(String email, String password) async {
    try {
      UserCredential result = await _auth.signInWithEmailAndPassword(email: email, password: password);
      User user = result.user;
      return _userFromFirebaseUser(user);
    } catch (error) {
      print(error.toString());
      return null;
    }
  }

新規登録

  Future registerWithEmailAndPassword(String email, String password) async {
    try {
      UserCredential result = await _auth.createUserWithEmailAndPassword(email: email, password: password);
      User user = result.user;
      return _userFromFirebaseUser(user);
    } catch (error) {
      print(error.toString());
      return null;
    }
  }

ログアウト

  Future signOut() async {
    try {
      return await _auth.signOut();
    } catch (error) {
      print(error.toString());
      return null;
    }
  }

ソースコード

まず、mainはこちら。
今回は状態管理にProviderを採用しています。

main.dart

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (context) => CounterService(),
        ),
        StreamProvider<MyUser>.value(
          value: UserService().user,
        )
      ],
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: Wrapper(),
    );
  }
}

home: Wrapper()ここでWrapperを呼び出してユーザ状態を確認しにいっています
ユーザ情報がnullであれば認証ページを返し、nullでなければホーム(カウンター)ページを表示しています

wrapper.dart

class Wrapper extends StatelessWidget {
  
  Widget build(BuildContext context) {
    final user = Provider.of<MyUser>(context);
    if (user == null) {
      return Authenticate();
    } else {
      return HomePage();
    }
  }
}

MyUserクラス、ユーザーIDを持たせておく部分

my_user.dart

class MyUser {
  final String uid;
  MyUser({ this.uid });
}

user_service.dart

class UserService with ChangeNotifier {
  final FirebaseAuth _auth = FirebaseAuth.instance;

  MyUser _userFromFirebaseUser(User user) {
    return user != null ? MyUser(uid: user.uid) : null;
  }

  Stream<MyUser> get user {
    return _auth.onAuthStateChanged
        .map(_userFromFirebaseUser);
  }

  Future signInWithEmailAndPassword(String email, String password) async {
    try {
      UserCredential result = await _auth.signInWithEmailAndPassword(email: email, password: password);
      User user = result.user;
      return _userFromFirebaseUser(user);
    } catch (error) {
      print(error.toString());
      return null;
    }
  }

  Future registerWithEmailAndPassword(String email, String password) async {
    try {
      UserCredential result = await _auth.createUserWithEmailAndPassword(email: email, password: password);
      User user = result.user;
      return _userFromFirebaseUser(user);
    } catch (error) {
      print(error.toString());
      return null;
    }
  }

  Future signOut() async {
    try {
      return await _auth.signOut();
    } catch (error) {
      print(error.toString());
      return null;
    }
  }
}

参考

ソースコード

Flutter & Firebase App Tutorial

Discussion