【Flutter】認証周りについてAuth0で色々と確認してみた
Auth0 + Postman + flutter_appauth で OAuth2.0 を色々と確認しながら試してみました。
Auth0 のセットアップ
Auth0 とは、認証と認可のためのプラットフォーム。
有名どこで言えば Firebase Authentication や AWS Cognito などのサービスと同じようなもの。
まずは Auth0 のセットアップ。
小規模の個人利用程度ならば Free プランで最低限の機能は使用可能。
登録が完了したらCreate Application
からアプリケーションを作成。
今回は Flutter で試したいので Native を選択。
作成が完了すると、自動でDomain
やClient 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
)を設定。 - ※ ここの値がクライアント側と認証サーバー側で一致していないと認証時にエラーとなること注意。
- Auth0 のコンソールで設定した URL(今回は
- 認可 URL
- Auth0 の
OAuth Authorization URL
の値を設定。
- Auth0 の
- アクセストークン URL
- Auth0 の
OAuth Token URL
の値を設定。
- Auth0 の
- クライアント ID
- Auth0 の
Client ID
の値を設定。
- Auth0 の
- クライアントシークレット
- Auth0 の
Client Secret
の値を設定。
- Auth0 の
上記の設定で 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.gradle
とAndroidManifest.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 アプリで定義したredirectUri
をauthsample://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
でも問題なく動作した。
NCDC株式会社( ncdc.co.jp/ )のエンジニアチームです。 募集中のエンジニアのポジションや、採用している技術スタックの紹介などはこちら( github.com/ncdcdev/recruitment )をご覧ください! ※エンジニア以外も記事を投稿することがあります
Discussion