メインコンテンツまでスキップ

Logto SDK を使用して FlutterFlow CustomAuthManager をカスタマイズする

FlutterFlow には、独自のバックエンドを使用してユーザーを認証 (Authentication) できる カスタム認証 (Authentication) 機能が組み込まれています。ただし、組み込みのカスタム認証 (Authentication) フローは、単一の認証 (Authentication) API 呼び出しで動作するように設計されています。サードパーティのアイデンティティプロバイダー (IdP) を使用している場合、認証 (Authentication) リクエストは Resource Owner Password Credentials グラントタイプを使用してのみ行うことができ、これは本番環境での使用には推奨されません。詳細については、廃止された ropc グラントタイプ を参照してください。

標準の OpenID Connect (OIDC) 認証 (Authentication) フローには、認可 (Authorization)、トークン交換、ユーザー情報の取得など、複数のステップが含まれます。Logto のような IdP を使用して標準の OIDC 認証 (Authentication) フローを実装するには、FlutterFlow の CustomAuthManager クラスをカスタマイズする必要があります。

このチュートリアルでは、Logto Flutter SDK を使用して FlutterFlow の CustomAuthManager クラスをカスタマイズする方法を示します。FlutterFlow UI ビルダーの利点を維持しながら、標準の OIDC 認証 (Authentication) フローのために Logto SDK を活用できます。

ヒント:
  • Logto SDK パッケージは pub.dev と Logto GitHub リポジトリ で利用可能です。
  • SDK は現在、Android および iOS プラットフォームにのみ適しています。

前提条件

FlutterFlow カスタムコードを有効にする

CustomAuthManager クラスをカスタマイズするには、FlutterFlow でカスタムコード機能を有効にする必要があります。GitHub でカスタムコードを管理する ガイドに従って、FlutterFlow プロジェクトを GitHub と同期します。

注記:

GitHub でカスタムコードを管理することは、FlutterFlow のプレミアム機能です。この機能を有効にするには、FlutterFlow をプロプランにアップグレードする必要があります。

完了すると、GitHub FlutterFlow リポジトリに次の 3 つの異なるブランチが作成されます:

  1. main: Flutter プロジェクトのメインブランチ。このブランチを使用してプロジェクトをデプロイする必要があります。
  2. flutterflow: FlutterFlow が FlutterFlow エディターからの変更を同期するブランチ。
  3. develop: カスタムコードを修正できるブランチ。

FlutterFlow で UI を作成する

まず、FlutterFlow で UI を作成します。要件に基づいて UI を作成するために FlutterFlow ドキュメント を参照できます。このチュートリアルでは、最低限の要件として次の 2 つのページを作成します:

  1. ログインボタンを備えたシンプルなホームページ。
  2. ユーザー情報を表示し、ログアウトボタンを備えたユーザープロファイルページ。

App Settings -> Authentication ページに移動し、カスタム認証 (Authentication) を有効にします。これにより、FlutterFlow プロジェクトに CustomAuthManager クラスが作成されます。

FlutterFlow カスタム認証 (Authentication)

UI が準備できたら、integrations -> GitHub ページに移動し、Push to Repository ボタンをクリックして変更を flutterflow ブランチにプッシュします。

FlutterFlow GitHub プッシュ

CustomAuthManager をカスタマイズする

GitHub リポジトリで develop ブランチに切り替え、flutterflow ブランチから最新の変更をマージします。UI ページと、事前に構築された CustomAuthManager クラスを含めます。

Logto SDK 依存関係をインストールする

プロジェクトに Logto SDK 依存関係を追加します。

  flutter pub add logto_dart_sdk
注記:

オプションの Http パッケージ:

Logto クライアントは API 呼び出しを行うために http クライアントを必要とします。http パッケージや他の任意の http クライアントパッケージを使用できます。

  flutter pub add http

UserProvider を更新する

ユーザー情報を保存するために OpenIdClaims クラスを CustomAuthUserProvider クラスに追加します。

OpenIdClaims クラスは Logto SDK の一部であり、認証 (Authentication) されたユーザーの id_token クレームを提供します。

// lib/auth/custom_auth/custom_auth_user_provider.dart

import 'package:logto_dart_sdk/src/modules/id_token.dart';
import 'package:rxdart/rxdart.dart';

import 'custom_auth_manager.dart';

class FlutterFlowAuthAuthUser {
FlutterFlowAuthAuthUser({required this.loggedIn, this.uid, this.idToken});

bool loggedIn;
String? uid;
OpenIdClaims? idToken;
}

/// 認証されたユーザーのストリームを生成します。
BehaviorSubject<FlutterFlowAuthAuthUser> flutterFlowAuthAuthUserSubject =
BehaviorSubject.seeded(FlutterFlowAuthAuthUser(loggedIn: false));
Stream<FlutterFlowAuthAuthUser> flutterFlowAuthAuthUserStream() =>
flutterFlowAuthAuthUserSubject
.asBroadcastStream()
.map((user) => currentUser = user);

CustomAuthManager で logto クライアントを初期化する

CustomAuthManager クラスで Logto クライアントを初期化します。

// lib/auth/custom_auth/custom_auth_manager.dart

import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import 'package:logto_dart_sdk/logto_client.dart';
import 'package:logto_dart_sdk/src/modules/id_token.dart';

import 'custom_auth_user_provider.dart';

export 'custom_auth_manager.dart';


class CustomAuthManager {
late LogtoClient logtoClient;

final logtoConfig = const LogtoConfig(
appId: '<YOUR-APP-ID>',
endpoint: '<YOUR-LOGTO-ENDPOINT>');


// ...

FlutterFlowAuthAuthUser? _updateCurrentUser(
{bool loggedIn = false, String? uid, OpenIdClaims? idToken}) {
// 現在のユーザーストリームを更新します。
final updatedUser = FlutterFlowAuthAuthUser(
loggedIn: loggedIn,
uid: uid,
idToken: idToken,
);

flutterFlowAuthAuthUserSubject.add(updatedUser);

return updatedUser;
}

Future initialize() async {
logtoClient = LogtoClient(config: logtoConfig, httpClient: http.Client());

late OpenIdClaims? idToken;

try {
idToken = await logtoClient.idTokenClaims;
} catch (e) {
if (kDebugMode) {
print('認証 (Authentication) の初期化中にエラーが発生しました: $e');
}
}

_updateCurrentUser(
loggedIn: idToken != null, uid: idToken?.subject, idToken: idToken);
}
}

FlutterFlowAuthAuthUser? currentUser;
bool get loggedIn => currentUser?.loggedIn ?? false;

initialize メソッドは Logto クライアントを初期化し、ローカルストレージに保存されたユーザー認証 (Authentication) 状態で現在のユーザーストリームを更新します。

Logto SDK は flutter_secure_storage パッケージを使用して、ユーザー認証 (Authentication) 情報を安全に保存します。

サインインメソッドを実装する

LogtoClient.signIn メソッドを呼び出すと、標準の OIDC 認証 (Authentication) フローが開始されます。Logto サインインページは flutter_web_auth を使用して WebView で開かれます。

// lib/auth/custom_auth/custom_auth_manager.dart

Future<FlutterFlowAuthAuthUser?> signIn(
String redirectUri,
) async {
await logtoClient.signIn(redirectUri);

var idTokenClaims = await logtoClient.idTokenClaims;

return _updateCurrentUser(
loggedIn: idTokenClaims != null,
uid: idTokenClaims?.subject,
idToken: idTokenClaims,
);
}

LogtoClient は認可 (Authorization)、トークン交換、ユーザー情報の取得ステップを処理します。ユーザーが認証 (Authentication) されると、idTokenClaims はローカルストレージに保存されます。 LogtoClient から idTokenClaims を取得し、現在のユーザーストリームを更新します。

サインアウトメソッドを実装する

// lib/auth/custom_auth/custom_auth_manager.dart

Future signOut() async {
await logtoClient.signOut();

flutterFlowAuthAuthUserSubject.add(
FlutterFlowAuthAuthUser(loggedIn: false),
);
}

認証 (Authentication) ユーティリティメソッドを更新する

  • CustomAuthManager インスタンスにアクセスするための authManager ゲッターを追加します。
  • 現在のユーザー uid を取得するための currentUserUid ゲッターを追加します。
  • 現在のユーザーデータを取得するための currentUserData ゲッターを追加します。
  • Logto クライアントインスタンスにアクセスするための logtoClient ゲッターを追加します。
// lib/auth/custom_auth/auth_util.dart

import 'package:logto_dart_sdk/logto_client.dart';
import 'package:logto_dart_sdk/src/modules/id_token.dart';

import 'custom_auth_manager.dart';

export 'custom_auth_manager.dart';

final _authManager = CustomAuthManager();
CustomAuthManager get authManager => _authManager;
String get currentUserUid => currentUser?.uid ?? '';
OpenIdClaims? get currentUserData => currentUser?.idToken;
LogtoClient get logtoClient => _authManager.logtoClient;

UI にカスタム認証 (Authentication) を統合する

ホームページ

ユーザーがサインインボタンをクリックしたときに認証 (Authentication) フローを開始するために authManager.signIn メソッドを呼び出します。

redirectUri は、Logto サインインページからの認可 (Authorization) コールバックをキャプチャするために使用されるコールバック URL です。 redirectUri の詳細については、Flutter SDK を参照してください。

// lib/pages/home_page/home_page_widget.dart

final redirectUri = 'io.logto://callback';

// ...

FFButtonWidget(
onPressed: () async {
GoRouter.of(context).prepareAuthEvent();

await authManager.signIn(redirectUri);

context.replaceNamed('user');
},
text: 'Sign In',
// ...
)

ユーザープロファイルページ

現在のユーザーデータと Logto クライアントインスタンスにアクセスするために認証 (Authentication) ユーティリティゲッターを使用します。

// lib/pages/user/user_widget.dart

import '/auth/custom_auth/auth_util.dart';

// ...

children: [
Text(
'User ID: $currentUserUid',
),
Text(
'Display Name: ${currentUserData?.name}',
),
Text(
'Username: ${currentUserData?.username}',
),
Text(
'Email: ${currentUserData?.emailVerified ?? currentUserData?.email}',
),
]

ユーザーがサインアウトボタンをクリックしたときにサインアウトメソッドを実装します。

// lib/pages/user/user_widget.dart

FFButtonWidget(
onPressed: () async {
await authManager.signOut();

context.replaceNamed('HomePage');
},
text: 'Sign Out',
// ...
)

さらなる読み物

Logto SDK は Logto API と対話するためのより多くのメソッドを提供します。CustomAuthManager クラスをさらにカスタマイズして、より多くの機能を実装することができます。

依存関係のトラブルシューティング

flutter_secure_storage

クロスプラットフォームの永続的なセキュアトークンストレージを実装するために、flutter_secure_storage を使用しています。内部では:

  • iOS では Keychain が使用されます
  • Android では AES 暗号化が使用されます。

Android バージョンの設定:

[project]/android/app/build.gradle で minSdkVersion を >= 18 に設定します。

  android {
...

defaultConfig {
...
minSdkVersion 18
...
}
}

自動バックアップを無効にする:

注記:

デフォルトでは、Android は Google Drive にデータをバックアップします。これにより、例外 java.security.InvalidKeyException:Failed to unwrap key が発生する可能性があります。

これを避けるために、アプリの自動バックアップを無効にするか、FlutterSecureStorage から sharedprefs を除外することができます。

  1. 自動バックアップを無効にするには、アプリのマニフェストファイルに移動し、ブール値 android:allowBackup を設定します:

    <manifest ... >
    ...
    <application
    android:allowBackup="false"
    android:fullBackupContent="false"
    ...
    >
    ...
    </application>
    </manifest>

  2. FlutterSecureStorage から sharedprefs を除外します。

    アプリの android:fullBackupContent を有効にする必要がある場合は、プラグインで使用される prefs を 除外 するバックアップルールを設定します:

    <application ...
    android:fullBackupContent="@xml/backup_rules">
    </application>
    <?xml version="1.0" encoding="utf-8"?>
    <full-backup-content>
    <exclude domain="sharedpref" path="FlutterSecureStorage"/>
    </full-backup-content>

    詳細については、flutter_secure_storage を確認してください。

flutter_web_auth

flutter_web_auth は Logto の flutter SDK の背後で使用されます。Logto の認可 (Authorization) ページを開くために、その webview ベースのインタラクションインターフェースに依存しています。

注記:

このプラグインは、iOS 12+ および macOS 10.15+ では ASWebAuthenticationSession、iOS 11 では SFAuthenticationSession、Android では Chrome Custom Tabs を使用し、Web では新しいウィンドウを開きます。 iOS 8+ でビルドできますが、現在サポートされているのは iOS 11 以上のみです。

Android でコールバック URL を登録する

Logto のサインインウェブページからコールバック URL をキャプチャするためには、サインイン redirectUri を AndroidManifest.xml に登録する必要があります。

<activity android:name="com.linusu.flutter_web_auth.CallbackActivity" android:exported="true">
<intent-filter android:label="flutter_web_auth">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="io.logto"/>
</intent-filter>
</activity>