【Flutter Dart】Firebase Authenticationを使って匿名認証を実装!HooksとRiverpodを利用!

Firebaseで匿名認証
  • URLをコピーしました!

今回は、Flutter と Firebaseを使って匿名認証をやっていこうと思います!

もし、まだFlutterでFirebaseを使えるように設定をしていないの方は、「【Flutter Dart】FirebaseをiOSとAndroidで使えるようにする!」を参考にしてみてください!

クマじい

匿名認証ってなんじゃ!

匿名認証ってなに?

Firebaseで認証する一時的な匿名ユーザを作成することで、アプリに登録していないユーザにも、セキュリティルールで保護されているデータを利用することができるようになる仕組みです。

ユーザ名やパスワードを入力せずにログインするため、一度ログアウトすると別ユーザとして認識されます。
仮ユーザとして利用できるといった用途があります。

また、匿名ユーザをログイン認証情報にリンクさせれば以降のセッションでもデータを利用することが可能です。

学習に使った本はこちら!

クマじい

Amazon Kindle Unlimited でもFlutter、Dartの本はいっぱいあるぞ!

  • 技術書をたくさん読みたい!
  • 色々な技術を学びたい!
初回30日間無料体験があるので、どのような参考書があるか確認してみよう!

Kindle Unlimitedで技術書を読むならタブレットがあるとさらに便利ですよ!
10インチあるとより見やすいと思いますが、7インチでも十分見やすくなります!

目次

プラグインを導入する!

早速始めていきましょう!!

Pubspec.yamlを編集

  • Pubspec.yamlに利用するプラグインを記載していく。
  • 【補足】下記のようなプラグインを利用する予定です。
  • 【参考】firebase_auth:Firebase認証の利用
  • 【参考】firebase_firestore:クラウドFireStoreの利用
  • 【参考】flutter_hooks:State管理でコード量を減らす
  • 【参考】hooks_riverpod:State管理でコード量を減らす
  • 【参考】freezed:immutable なオブジェクト用のコード生成ができる
  • 【参考】freezed_annotation:Freezedアノテーションの提供
  • 【参考】build_runner:ファイルやコードを生成する方法を提供する
  • 【参考】json_serializable:JSONのシリアライズ・デシリアライズ
name: shopping_list
description: A new Flutter project.

version: 1.0.0+1

environment:
  sdk: ">=2.12.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^1.0.2

  firebase_core: ^1.3.0
  firebase_analytics: ^8.1.2
  firebase_auth: ^2.0.0
  cloud_firestore: ^2.3.0

  flutter_hooks: ^0.17.0
  hooks_riverpod: ^0.14.0+4

  freezed_annotation: ^0.14.2

dev_dependencies:
  flutter_test:
    sdk: flutter

  build_runner: ^2.0.6
  freezed: ^0.14.2
  json_serializable: ^4.1.3

flutter:
  uses-material-design: true
  • 上記が記載できたら、pubgetをしましょう!
クマじい

エラーが出た場合は、バージョンを見直してみるのじゃぞ!

FirebaseのAuthenticationを利用!

実際にFirebaseのAuthenticationを使っていきましょう!

Firebaseの初期化とプロバイダーアクセスの設定

Flutterプロジェクトを作成すると、初期のコードが作成されていると思いますが、不必要なところは削除しておきましょう!

  • main.dartを下記のように修正する。
import'package:firebase_core/firebase_core.dart';
import'package:flutter/material.dart';
import'package:hooks_riverpod/hooks_riverpod.dart';

//main()を非同期を制御する
void main() async {
//アプリ起動時に処理したいので追記
  WidgetsFlutterBinding.ensureInitialized();
//Firebaseの初期化(同期)
  await Firebase.initializeApp();
//MyApp()をProviderScopeでラップして、アプリ内のどこからでも全てのプロバイダーにアクセスできるようにする。
  runApp(ProviderScope(child:MyApp()));
}

class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context){
    return MaterialApp(
      title:'TeechLab.',
      theme:ThemeData(
        primarySwatch:Colors.brown,
      ),
      home:Scaffold(),
    );
  }
}

簡単に説明を記載しておきます。

  • WidgetsFlutterBinding.ensureInitialized();
    →runApp()をする前にFlutter Engineの機能を利用したい場合に宣言
  • await Firebase.initializeApp();
    →Firebaseを初期化
  • runApp(ProviderScope(child:MyApp()));
    →ProviderScopeでラップすることで、アプリ内のどこからでも全てのプロバイダーにアクセスできるようにしています。

Authenticationで匿名認証を有効化

  • Firebaseの画面に移動
  • メニュー>Authenticationを選択
  • 「始める」ボタンを押下
  • 著名を有効にして、保存

Authenticationを利用するコードを実装

  • lib>repositories>auth_repository.dartを作成
  • lib>general_providers.dartを作成
  • firebaseAuthのインスタンスを生成
import 'package:firebase_auth/firebase_auth.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

// firebaseAuthのインスタンスを提供
final firebaseAuthProvider = Provider<FirebaseAuth>((ref) => FirebaseAuth.instance);
  • BaseAuthRepositoryを定義(詳細はコードのコメントを参照)
  • BaseAuthRepositoryをimplementsしたAuthRepositoryを実装(詳細はコードのコメントを参照)
  • 【補足】authStateChanges()は、匿名ユーザの初期化、サインイン、サインアウトの際にイベントする。
  • 【補足】匿名認証なのでログアウトした場合は、別の匿名ユーザでログインさせている。
import 'package:firebase_auth/firebase_auth.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shopping_list/general_providers.dart';

import 'custom_exception.dart';

// 抽象クラスを定義
abstract class BaseAuthRepository {

  // ログイン状態の確認用(ログイン状態の変更や初期化時にイベントする)
  Stream<User?> get authStateChanges;

  // サインイン(著名ユーザを作成)
  Future<void> signInAnonymously();
  // 現在サインインしているユーザを取得する。
  User? getCurrentUser();
  // ログアウト
  Future<void> signOut();
}

// AuthRepositoryを提供し、ref.readを渡してアクセスできるようにする
final authRepositoryProvider = Provider<AuthRepository>((ref) => AuthRepository(ref.read));

// 認証リポジトリクラス
class AuthRepository implements BaseAuthRepository {
  // riverpod Reader
  // アプリ内の他のプロバイダーを読み取ることを許可
  final Reader _read;

  const AuthRepository(this._read);

  // Readerを利用して、firebaseAuth.instanceにアクセス
  @override
  Stream<User?> get authStateChanges => _read(firebaseAuthProvider).authStateChanges();

  // 匿名ユーザでログイン
  @override
  Future<void> signInAnonymously() async {
    try {
      await _read(firebaseAuthProvider).signInAnonymously();
    } on FirebaseAuthException catch (e) {
      throw CustomException(message: e.message);
    }
  }

  // 既存の匿名ユーザを返却
  @override
  User? getCurrentUser() {
    try {
      return _read(firebaseAuthProvider).currentUser;
    } on FirebaseAuthException catch (e) {
      throw CustomException(message: e.message);
    }
  }

  // サインアウトしたら、新たに匿名ユーザでログインさせる。
  @override
  Future<void> signOut() async {
    try {
      // サインアウト
      await _read(firebaseAuthProvider).signOut();
      // 匿名でサインイン
      await signInAnonymously();
    } on FirebaseAuthException catch (e) {
      throw CustomException(message: e.message);
    }
  }
}
  • repositoriesにcustom_exception.dartを作成
  • CustomExceptionを実装
// カスタム例外
class CustomException implements Exception {
  final String? message;

  const CustomException({this.message = 'Auth Error!'});

  @override
  String toString() => 'CustomException { message: $message}';
}
  • lib>controllersを作成
  • controllersにauth_controller.dartを作成
  • auth_controller.dartを実装(詳細はコードのコメントを参照)
import 'dart:async';

import 'package:firebase_auth/firebase_auth.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shopping_list/repositories/auth_repository.dart';

final authControllerProvider = StateNotifierProvider<AuthController, User?>(
      (ref) => AuthController(ref.read)..appStarted(),
);


class AuthController extends StateNotifier<User?> {
  final Reader _read;

  StreamSubscription<User?>? _authStateChangesSubscription;

  AuthController(this._read) : super(null) {
    // 受信停止
    _authStateChangesSubscription?.cancel();
    // 受信開始
    _authStateChangesSubscription = _read(authRepositoryProvider)
        .authStateChanges
        .listen((user) => state = user);
  }

  // 不要な受信をキャンセルするためにdisposeでキャンセルする
  @override
  void dispose() {
    _authStateChangesSubscription?.cancel();
    super.dispose();
  }

  // アプリ開始
  void appStarted() async {
    // Currentユーザを取得
    final user = _read(authRepositoryProvider).getCurrentUser();
    // ログインされていなければ、匿名でサインインしてログインさせる。
    if (user == null) {
      await _read(authRepositoryProvider).signInAnonymously();
    }
  }

  // サインアウト
  void signOut() async {
    // サインアウトメソッド
    await _read(authRepositoryProvider).signOut();
  }

}
  • main.dartを修正
import'package:firebase_core/firebase_core.dart';
import'package:flutter/material.dart';
import'package:flutter_hooks/flutter_hooks.dart';
import'package:hooks_riverpod/hooks_riverpod.dart';
import'package:shopping_list/controllers/auth_controller.dart';

//main()を非同期にする
void main() async {
  //アプリ起動時に処理したいので追記
  WidgetsFlutterBinding.ensureInitialized();
  //Firebaseの初期化
  await Firebase.initializeApp();
  //MyApp()をProviderScopeでラップして、アプリ内のどこからでも全てのプロバイダーにアクセスできるようにする。
  runApp(ProviderScope(child:MyApp()));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context){
    return MaterialApp(
      title:'TeechLab.',
      theme:ThemeData(
        primarySwatch:Colors.brown,
      ),
      home:HomeScreen(),
    );
  }
}

class HomeScreen extends HookWidget{
  @override
  Widget build(BuildContext context){
    final authControllerState = useProvider(authControllerProvider);
    return Scaffold (
      appBar: AppBar(
        title: Text('ShoppingList'),
        leading: authControllerState!=null
            ? IconButton(
            onPressed:()=>context.read(authControllerProvider.notifier).signOut(),
            icon:Icon(Icons.logout)
            )
            : null,
      ),
    );
  }
}
クマじい

ちゃんとできてるんじゃろな?

動作確認してみよう!

ここまでできたら動作確認して見ましょう!

アプリを起動

  • シュミレータを起動(iOSでもAndroidでも構いません。今回はiOSで確認しております。)
1:55 
Shopping List
  • Firebaseを確認してみる
  • 匿名ユーザが作成されていることを確認
Authentication 
Users Sign-in method 
Templates 
Usage 
十 : 
Local Em 飜 0 「 Su ⅱ 0 で FirebaseAuthentication を 使 用 し た プ ロ ト タ イ ヒ 。 ン グ と エ ン ド ッ ー エ ン ド の テ ス ト が 可 能 に 
ス ! 
0 、 メ 
( 匿 名 ) 
ー ル ア ド レ ス 、 電 話 番 号 、 ま た は ユ ー ザ ー I-JID で 検 索 
プ ロ バ イ ダ 
作 成 日 
0 
2021 / 07 / 11 
ロ グ イ ン 日 
2021 / 07 / 11 
ユ ー ザ ー UID ↑ 
vndHKa9LCCXLJg2PkxcxE501

ログアウトを確認

  • ログインされていると思うので、ログアウトボタンを押下
  • ログアウトすると、再度ログインされることを確認
  • Firebaseでログアウトするたび(再度ログインするたび)匿名ユーザが作成されることを確認
0 、 
メ ー ル ア ド レ ス 、 電 話 番 号 、 ま た は ユ ー ザ ー I-JID で 検 索 
( 匿 名 ) 
( お 名 ) 
( 匿 名 ) 
プ ロ バ イ ダ 
0 
0 
0 
作 成 日 
2021 / 07 / 1 1 
2021 / 07 / 1 1 
2021 / 07 / 1 1 
ロ グ イ ン 日 
2021 / 0 刀 11 
2021 / 0 刀 11 
2021 / 07 / 11 
ュ ・ 
ユ ー ザ ー UID ↑ 
LxtA5M680TM6avD 
hYVRhtY4A2Sgyifk9 
vndHKa9LCCX 凵 92ト
クマじい

できたぞーー

まとめ

今回は、FirebaseのAuthenticationを使った匿名認証をやっていきました。

次回は、FirebaseのFireStoreを使っていこうと思いますので興味がある方はぜひ参考にしてみてください。

また、今回Flutterを勉強するにあたり利用した教材をあげています。
主に本とUdemyの動画教材を利用しています。興味ある方は、本やUdemyを購入して勉強してみることをおすすめします。

学習に使った本はこちら!

クマじい

Amazon Kindle Unlimited でもFlutter、Dartの本はいっぱいあるぞ!

  • 技術書をたくさん読みたい!
  • 色々な技術を学びたい!
初回30日間無料体験があるので、どのような参考書があるか確認してみよう!

Kindle Unlimitedで技術書を読むならタブレットがあるとさらに便利ですよ!
10インチあるとより見やすいと思いますが、7インチでも十分見やすくなります!

Firebaseで匿名認証

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!

この記事を書いた人

東京在住で20代のエンジニアです。
特に特技があるわけではありませんが、誰もが楽しくプログラミングができたらいいと思い、「teech lab.」を開設いたしました。

Enjoy Diaryという、ガジェットや雑貨を紹介しているブログもあります!
ぜひ、みてください!!

目次