Flutter Firebase ログイン機能 初歩歩の歩


自分用に書いたメモです。
間違っている部分やおかしな部分があったらコメントください！

Firebaseを使ってログイン機能とアカウント登録機能、
あと自動ログイン機能を実装していきます。

Firebaseの設定は[公式ドキュメント](https://firebase.google.com/docs/flutter/setup?hl=ja&platform=android)を見て設定してください。

こちらのサイトを参考にさせていただきました。
[FlutterでFirebase Authenticationを使ったログインUIを作成してみた。](https://qiita.com/smiler5617/items/b004debc847ffed4e3af)
[[Flutter x Firebase] カウンターアプリに認証機能を追加する](https://zenn.dev/popy1017/articles/b9f3e46b5efeb79af1f7)

パッケージ
[firebase_core](https://pub.dev/packages/firebase_core)
[firebase_auth](https://pub.dev/packages/firebase_auth)

```pubspec.yaml
  firebase_core: ^1.3.0
  firebase_auth: ^1.4.1
```

ログインページ

```login.dart
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';

import 'registration.dart';
import 'myHomePage.dart';

class Login extends StatelessWidget {
  final String title;

  Login({Key? key, required this.title}) : super(key: key);

  final _auth = FirebaseAuth.instance;

  @override
  Widget build(BuildContext context) {
    String loginEmail = '';
    String loginPassword = '';

    UserCredential _authResult;

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [

            /// メールアドレスの入力フォーム
            Padding(
                padding: EdgeInsets.fromLTRB(25, 0, 25, 0),
                child: TextFormField(
                  decoration: InputDecoration(labelText: 'メールアドレス'),
                  onChanged: (String value) {
                    loginEmail = value;
                  },
                )),

            /// パスワード入力フォーム
            Padding(
                padding: EdgeInsets.fromLTRB(25, 0, 25, 10),
                child: TextFormField(
                  decoration: InputDecoration(
                    labelText: 'パスワード (8~20文字)',
                  ),
                  // Passwordが見えないようにする
                  obscureText: true,
                  maxLength: 20,
                  onChanged: (String value) {
                    loginPassword = value;
                  },
                )),

            /// ログインボタン
            ButtonTheme(
              minWidth: 350,
              height: 100,
              child: ElevatedButton(
                child: Text(
                  'ログイン',
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                    color: Colors.white,
                  ),
                ),
                style: ElevatedButton.styleFrom(
                  shape: const RoundedRectangleBorder(
                    borderRadius: BorderRadius.all(Radius.circular(10)),
                  ),
                ),
                onPressed: () async {
                  _authResult = await _auth.signInWithEmailAndPassword(
                      email: loginEmail, password: loginPassword);
                  if (_authResult.user != null) {
                    Navigator.push(
                        context,
                        MaterialPageRoute(
                            builder: (context) => MyHomePage(title: title)));
                  }
                },
              ),
            )
          ],
        ),
      ),

      /// 登録ボタン
      bottomNavigationBar: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Padding(
            padding: const EdgeInsets.all(8),
            child: ButtonTheme(
              minWidth: 350,
              height: 100,
              child: ElevatedButton(
                child: Text(
                  'アカウントを作成する',
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                    color: Colors.white,
                  ),
                ),
                style: ElevatedButton.styleFrom(
                  shape: const RoundedRectangleBorder(
                    borderRadius: BorderRadius.all(Radius.circular(10)),
                  ),
                ),
                onPressed: () {
                  Navigator.push(
                      context,
                      MaterialPageRoute(
                        fullscreenDialog: true,
                        builder: (BuildContext context) =>
                            Registration(title: title),
                      ));
                },
              ),
            ),
          )
        ],
      ),
    );
  }
}
```

会員登録ページ

```registration.dart
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';

import 'myHomePage.dart';

class Registration extends StatelessWidget {
  final String title;

  Registration({Key? key, required this.title}) : super(key: key);

  final _auth = FirebaseAuth.instance;

  @override
  Widget build(BuildContext context) {
    String newEmail = '';
    String newPass = '';
    bool passwordCheck = false;

    UserCredential _authResult;

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            /// ラベル
            Padding(
                padding: EdgeInsets.fromLTRB(25, 0, 25, 30),
                child: Text(
                  '新規アカウントの作成',
                  style: TextStyle(
                    fontSize: 20,
                    fontWeight: FontWeight.bold,
                  ),
                )),

            /// メールアドレス入力フォーム
            Padding(
                padding: EdgeInsets.fromLTRB(25, 0, 25, 0),
                child: TextFormField(
                  decoration: InputDecoration(labelText: 'メールアドレス'),
                  onChanged: (String value) {
                    newEmail = value;
                  },
                )),

            /// パスワード入力フォーム
            Padding(
                padding: EdgeInsets.fromLTRB(25, 0, 25, 10),
                child: TextFormField(
                  decoration: InputDecoration(
                    labelText: 'パスワード (6~20文字)',
                  ),

                  // パスワードを見えないようにする。
                  obscureText: true,
                  maxLength: 20,
                  onChanged: (String value) {
                    if (value.length >= 6) {
                      newPass = value;
                      passwordCheck = true;
                    } else {
                      passwordCheck = false;
                    }
                  },
                )),

            /// 登録ボタン
            ButtonTheme(
              minWidth: 350,
              height: 100,
              child: ElevatedButton(
                child: Text('登録',
                    style: TextStyle(
                      fontWeight: FontWeight.bold,
                      color: CupertinoColors.white,
                    )),
                style: ElevatedButton.styleFrom(
                    shape: const RoundedRectangleBorder(
                  borderRadius: BorderRadius.all(Radius.circular(10)),
                )),
                onPressed: () async {
                  if (passwordCheck) {
                    _authResult = await _auth.createUserWithEmailAndPassword(
                        email: newEmail, password: newPass);
                    Navigator.push(
                        context,
                        MaterialPageRoute(
                          builder: (context) => MyHomePage(title: title),
                        ));
                  }
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}
```

Main

```main.dart
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';

import 'myHomePage.dart';
import 'login.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  final String _title = 'Flutter Demo Home Page';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: _LoginCheck(title: _title),
    );
  }
}

class _LoginCheck extends StatelessWidget {
  final String title;

  _LoginCheck({Key? key, required this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final bool _loggedIn = AuthModel().loggedIn;
    return _loggedIn ? MyHomePage(title: title) : Login(title: title);
  }
}

class AuthModel with ChangeNotifier {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  User? _user;

  User? get user => _user;

  bool get loggedIn => _user != null;

  AuthModel() {
    final User? _currentUser = _auth.currentUser;
    if (_currentUser != null) {
      _user = _currentUser;
      notifyListeners();
    }
  }
}

```