🦔

【Flutter】認証周りについてAuth0で色々と確認してみた

2024/11/28に公開

Auth0 + Postman + flutter_appauth で OAuth2.0 を色々と確認しながら試してみました。


Auth0 のセットアップ

Auth0 とは、認証と認可のためのプラットフォーム。
有名どこで言えば Firebase Authentication や AWS Cognito などのサービスと同じようなもの。

まずは Auth0 のセットアップ。
小規模の個人利用程度ならば Free プランで最低限の機能は使用可能。

登録が完了したらCreate Applicationからアプリケーションを作成。
今回は Flutter で試したいので Native を選択。

作成が完了すると、自動でDomainClient IDなどが払い出される。

Auth0 のコンソールで主に確認する箇所は以下。

  • settigns -> Basic Information
  • settigns -> Advanced Settings -> Endpoints


最後に settings -> Application URIs でコールバック URL を設定する。
今回は Postman デフォルトのコールバック URL https://oauth.pstmn.io/v1/callbackと、適当な確認用 URLhttps://flutter.devを設定しておく。


Postman のセットアップ

次に Postman の設定を行う。

Postman を起動して「新しいトークンの設定」の項目を埋めていく。

  • トークン名
    • 適当な名前を記入
  • Grant タイプ
    • ここでは「認可コード」とする。
  • コールバック URL
    • Auth0 のコンソールで設定した URL(今回はhttps://flutter.dev)を設定。
    • ※ ここの値がクライアント側と認証サーバー側で一致していないと認証時にエラーとなること注意。
  • 認可 URL
    • Auth0 のOAuth Authorization URLの値を設定。
  • アクセストークン URL
    • Auth0 のOAuth Token URLの値を設定。
  • クライアント ID
    • Auth0 のClient IDの値を設定。
  • クライアントシークレット
    • Auth0 のClient Secretの値を設定。

上記の設定で Postman から Auth0 が有効かどうか確認してみる。
画面下部のボタンを押下すると、Auth0 の認証画面が表示される。
Auth0 で登録したユーザー情報でログインを行うと、Postman にトークンが返却されることが確認できたら OK。

1 2 3


flutter_appauth セットアップ

Flutter アプリで適当にボタンだけ配置。
そして認証に必要な情報を定義する。

Auto0 のコンソールで設定したコールバック URL flutter.devを設定し、ログインが完了してflutter.devが表示されたら OK。

const String clientId = '<Client ID>';
const String clientSecret ='<Client Secret>';
const String authorizationEndpoint ='<OAuth Authorization URL>';
const String tokenEndpoint ='<OAuth Token URL>';
const String redirectUri = 'https://flutter.dev'; // Auto0のコンソールで設定したコールバック URL

// ...省略
ElevatedButton(
    onPressed: () async {
    final result = await _login();
    },
    child: const Text('auth0 login'),
),

// ...省略
Future _login() async {
  try {
    const FlutterAppAuth appAuth = FlutterAppAuth();

    await appAuth.authorizeAndExchangeCode(
      AuthorizationTokenRequest(
        clientId,
        redirectUri,
        clientSecret: clientSecret,
        serviceConfiguration: const AuthorizationServiceConfiguration(
          authorizationEndpoint: authorizationEndpoint,
          tokenEndpoint: tokenEndpoint,
        ),
        scopes: ['openid', 'profile', 'email'], // 任意
      ),
    );
  } catch (e) {
    print('Login error: $e');
    return;
  }
}
1 2 3


アプリへのコールバック

認証後はアプリにコールバックするようにしないと実際のアプリでは使用できない(認証成功しても Token が取得できない)ので、認証後にアプリにコールバックするように設定する。

scheme の設定

認証成功時に WevView からアプリを起動できるように、アプリの scheme を設定する。
設定方法についてはflutter_appauth の Readme 通りに設定する。

今回は scheme をauthsampleとする。

【android】
build.gradleAndroidManifest.xmlに scheme の設定を追加。

defaultConfig {
    <!-- ...省略 -->
    manifestPlaceholders += [
        'appAuthRedirectScheme': 'authsample'
    ]
<activity
    <!-- ...省略  -->
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="authsample" />
    </intent-filter>

【ios】
info.plistに scheme の設定を追加するのみ。

  <key>CFBundleTypeRole</key>
  <string>Editor</string>
  <key>CFBundleURLSchemes</key>
  <array>
    <string>authsample</string>
  </array>


※ 備考
以下 Auth0 のドキュメントから引用。
今回はカスタムスキームでのコールバックとしているため、Auth0 側の設定は不要。
Universal Links でコールバックする際は Auth0 のドキュメント(<project>/Quickstart/Flutter)に沿って設定が必要。

It is needed to use Universal Links as callback and logout URLs. Skip this step to use a custom URL scheme instead.


scheme を用いたコールバック URL の設定

上記で設定した scheme を用いてコールバック URL を設定します。
今回は適当にauthsample://test/callbackとしてみます。

Auth0 コンソールのコールバック URL に上記を追加します。

Flutter アプリで定義したredirectUriauthsample://test/callbackに変更します。

- const String redirectUri = 'https://flutter.dev';
+ const String redirectUri = 'authsample://test/callback';


動作確認

アプリ上で取得する Token が確認できるように適当に Widget を追加。

const String clientId = '<Client ID>';
const String clientSecret ='<Client Secret>';
const String authorizationEndpoint ='<OAuth Authorization URL>';
const String tokenEndpoint ='<OAuth Token URL>';
const String redirectUri = 'authsample://test/callback'; // 変更

// ...省略
ElevatedButton(
    onPressed: () async {
      final result = await _login();
      if (result != null) {
        accessToken.value = result['accessToken'];
        refreshToken.value = result['refreshToken'];
      }
    },
    child: const Text('auth0 login'),
),

// ...省略
Future _login() async {
  try {
    const FlutterAppAuth appAuth = FlutterAppAuth();

    final AuthorizationTokenResponse? result =
      await appAuth.authorizeAndExchangeCode(
        AuthorizationTokenRequest(
          clientId,
          redirectUri,
          clientSecret: clientSecret,
          serviceConfiguration: const AuthorizationServiceConfiguration(
            authorizationEndpoint: authorizationEndpoint,
            tokenEndpoint: tokenEndpoint,
          ),
          scopes: ['openid', 'profile', 'email'], // 任意
        ),
      );

    if (result != null) {
      debugPrint('Access token: ${result.accessToken}\n');
      debugPrint('Refresh token: ${result.refreshToken}\n');
      return {
        'accessToken': result.accessToken,
        'refreshToken': result.refreshToken
      };
    }
  } catch (e) {
    print('Login error: $e');
    return;
  }
}

上記の設定により、アプリ上で認証が成功すると、アプリに戻ってきてトークンを取得できることを確認。

認証前 認証後


備考

android のデフォルトの package 名(applicationId) だと、auth.sample.app.auth_sample_app のような形式だが、これだと認証後にトークンが取得できず、以下のエラーに。(ここが いろんな Issue を調べても原因がわからずで沼った。。。)

PlatformException(null_intent, Failed to authorize: Null intent received, null, null)

id の形式をauth.sample.appに変更すると、認証後にトークンが取得できるようになった。

※ ios だとデフォルトの形式auth.sample.app.authSampleAppでも問題なく動作した。

GitHubで編集を提案
NCDCエンジニアブログ

Discussion