🔑

【Flutter】katana_modelの様にシステムを簡単に切り替えることが可能な認証パッケージ

2023/01/17に公開

こんにちは。広瀬マサルです。

後々リリース予定の総合フレームワークのために利用されるパッケージをいくつか紹介します。

今回は認証周りのパッケージとなります。

Firebase Authenticationを後々利用するためのテスト用のパッケージとなります。

使い方をまとめたので興味ある方はぜひ使ってみてください!

katana_auth

https://pub.dev/packages/katana_auth

はじめに

認証周りを利用するためのFirebaseAuthenticationは便利です。

メールアドレス認証や電話番号での認証、SNSアカウントを用いた認証など様々な認証を簡単に実装することが出来ます。

ただ、後々にFirebaseの認証を利用するにしてもアプリのモックアップを作成する際にサーバーへ接続せずに認証機能を実装したい場合やテストコードで認証機能を実装したい場合があります。

そのためkatana_modelで実装したときと同じ様にアダプターを利用してFirebaseやローカルでの認証を切り替えることが可能になるようなパッケージを実装しました。

また、GoogleサインインやAppleサインインの利用の有無をアプリによって切り替え易いようにインターフェースを整備しました

インストール

下記パッケージをインポートします。

flutter pub add katana_auth

Firestoreを利用する場合は下記のパッケージを合わせてインポートします。

flutter pub add katana_auth_firebase

実装

事前準備

必ずAuthAdapterScopeのWidgetをアプリのルート近くに配置します。

adapterのパラメーターにRuntimeAuthAdapterといったAuthAdapterを渡します。

// main.dart
import 'package:flutter/material.dart';
import 'package:katana_auth/katana_auth.dart';

void main() {
  runApp(const MyApp());
}

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

  
  Widget build(BuildContext context) {
    return AuthAdapterScope(
      adapter: const RuntimeAuthAdapter(),
      child: MaterialApp(
        home: const AuthPage(),
        title: "Flutter Demo",
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
      ),
    );
  }
}

認証オブジェクトの作成

認証を行うにはまずAuthenticationを作成しどこかに保持しておきます。

Authenticationのオブジェクトは下記のデータを取得することができるため認証の状態を確認可能です。

  • isSignedIn:認証済みの場合trueを返します。
  • isAnonymously:匿名認証の場合trueを返します。
  • userId:ユーザーIDを返します。
  • userEmail:メール認証等を行った場合ユーザーのメールアドレスを返します。
  • userPhoneNumber:電話番号認証を行った場合ユーザーの電話番号を返します。

また、AuthenticationはChangeNotifierを継承しているので、addListenerやriverpodのChangeNotifierProviderを利用する等して更新を監視することが可能です。

// auth_page.dart
import 'package:flutter/material.dart';
import 'package:katana_auth/katana_auth.dart';

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

  
  State<StatefulWidget> createState() => AuthPageState();
}

class AuthPageState extends State<AuthPage> {
  final auth = Authentication();

  
  void initState() {
    super.initState();
    auth.addListener(_handledOnUpdate);
  }

  void _handledOnUpdate() {
    setState(() {});
  }

  
  void dispose() {
    super.dispose();
    auth.removeListener(_handledOnUpdate);
    auth.dispose();
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("App Demo")),
      body: ListView(
        children: [
          ListTile(
            title: Text("SignedIn: ${auth.isSignedIn}"),
          ),
          ListTile(
            title: Text("Anonymously: ${auth.isAnonymously}"),
          ),
          ListTile(
            title: Text("ID: ${auth.userId}"),
          ),
          ListTile(
            title: Text("Email: ${auth.userEmail}"),
          ),
          ListTile(
            title: Text("Phone: ${auth.userPhoneNumber}"),
          ),
        ],
      ),
    );
  }
}

ユーザー登録・ログイン

ユーザー登録を行うためにはauth.registerメソッドを利用します。

引数にはRegisterAuthProviderを渡す必要があります。

RegisterAuthProviderはregisterメソッドがあるAuthQueryを使用して取得してください。

(AuthQueryについては後述します)

await auth.register(
  EmailAndPasswordAuthQuery.register(
    email: "test@email.com",
    password: "12345678",
  ),
);

また、ログインを行うにはauth.signInを使用します。

引数にはSignInAuthProviderを渡す必要があり、signInメソッドがあるAuthQueryを使用して取得してください。

await auth.signIn(
  EmailAndPasswordAuthQuery.signIn(
    email: "test@email.com",
    password: "12345678",
  ),
);

メールリンク認証やSMS認証を行うといった、認証の確定を行う場合はauth.confirmSignInを使用します。

await auth.confirmSignIn(
  SmsAuthQuery.confirmSignIn(
    code: "012345",
  ),
);

ユーザー情報の変更

ユーザー情報を変更する場合はauth.changeを使用します。

引数にChangeAuthProviderを渡しますが、変更する内容によってAuthQueryのメソッドを変えることができます。

  • EmailAndPasswordAuthQuery.changeEmail:メールアドレスの変更。
  • EmailAndPasswordAuthQuery.changePassword:パスワードの変更。
  • SmsAuthQuery.changePhoneNumber:電話番号の変更。
await auth.change(
  EmailAndPasswordAuthQuery.changeEmail(
    email: "changed@email.com"
  ),
);

※ログイン時にしか利用できません。

ログアウト

ログアウトを行う場合はauth.signOutを使用します。

ログイン時にのみ利用可能で、引数は必要ありません。

await auth.signOut();

AuthAdapter

AuthAdapterScopeを定義する際に渡すことで認証システムを変更することが可能です。

  • RuntimeAuthAdapter:アプリ起動時のみで動作する認証システム。アプリを起動し直すと認証情報はリセットされます。テスト時に利用してください。
  • LocalAuthAdapter:端末ローカルのみで動作する認証システム。アプリを起動し直しても認証情報は残りますが他端末間で共有はできません。
  • FirebaseAuthAdapter:FirebaseAuthenticationのシステム。端末間で認証情報を共有できます。Firebaseの初期設定が必要です。

AuthQuery

認証プロバイダ別にAuthQueryが用意されています。

AuthQueryのメソッドを利用することによりAuthenticationクラスで用意されている認証用の機能を利用することが可能です。

(認証プロバイダによって利用できる機能が限定されます)

  • AnonymouslyAuthQuery:匿名認証を提供するプロバイダ用AuthQuery。
  • EmailAndPasswordAuthQuery:メールアドレスとパスワードでの認証を提供するプロバイダ用AuthQuery。
  • EmailLinkAuthQuery:メールリンクでの認証を提供するプロバイダ用AuthQuery。
  • SmsAuthQuery:SMSでの認証を提供するプロバイダ用AuthQuery。
  • SnsSignInAuthProvider:SNSアカウントでの認証を提供するプロバイダ用AuthQueryの抽象クラス。抽象クラスなので他の関連パッケージを読み込むことによって実際のAuthQueryを利用することが可能。

おわりに

自分で使う用途で作ったものですが実装の思想的に合ってそうならぜひぜひ使ってみてください!

また、こちらにソースを公開しているのでissueやPullRequestをお待ちしてます!

また仕事の依頼等ございましたら、私のTwitterWebサイトで直接ご連絡をお願いいたします!

https://mathru.net/ja/contact

GitHub Sponsors

スポンサーを随時募集してます。ご支援お待ちしております!

https://github.com/sponsors/mathrunet

Discussion