前提・実現したいこと
Both English and Japanese are written.
英語圏の方にも相談したいので、英語併記させて頂いています。
This is a continuation from the previous question.
I want to implement oauth login using flutter_appauth plugin with flutter 3
I'm trying to make an application with Flutter that performs OAuth authentication and obtains an API.
The app will not use Firebase or SNS authentication, but will authenticate with its own authentication server. The server is built using KeyCloak software.
The authentication server is running on localhost using Docker.
The plugin uses the following:
flutter_appauth 0.8.2
The sample code referred to the following Github:
MaikuB/flutter_appauth
前回の質問 flutterでflutter_appauthプラグインを使ってoauthログインを実装したい3 からの続きの質問です。
アプリから、認証サーバのログインページを呼び出してログインし、認証が済んだら
アプリに戻ってアクセストークンでAPIを取得しようとしています。
認証サーバは自前で用意したものを使います。(FirebaseやSNS認証などは使わない)
今回はKeycloakを使い、DockerのコンテナでローカルPCに立ち上げています。
そのため、以下のプラグインを使用して実装しようとしています。
flutter_appauth 0.8.2
こちらのGitHubのサンプルコードを参照して実装しました。
MaikuB/flutter_appauth
発生している問題・エラーメッセージ Occurring problems and error messages
What's in trouble ①
From the app, I call the login page of the authentication server to log in, and I have been authenticated → callback to return to the app.
It will end abnormally the moment I callback the app. It seems that it is falling inside the plugin
No error message is displayed and I cannot enter Try catch.
It's easy to understand if you watch the video, but there's no video, so here's a picture
困っていることその①
アプリから、認証サーバのログインページを呼び出してログインし、認証済み→callbackでアプリに戻るのですが
アプリに戻った瞬間に異常終了してしまいます。プラグイン内部で落ちていると思われるのですが
エラーメッセージも出ず、Try catchにも入りません。
動画が貼れれば分かりやすいのですが
Application initial screen. Click the "Go to Login Page" button to move the screen.
アプリ初期画面 「ログインページへ」ボタンを押して画面遷移
Display the web screen of the authentication server.
認証サーバのweb画面を表示
Enter the ID and PW and press the login button.
ID、PWを入力してログインボタンをおす
Return to the app for a moment.
見えないくらい一瞬だけアプリに戻る
Immediately terminates abnormally.
すぐに落ちる
error message
(The print statement I put in the code showed up halfway through and stopped there. )
エラーメッセージ(コード中に入れたprintを途中まで表示して止まった)
エラーメッセージ error message Launching lib/main.dart on Android SDK built for x86 64 in debug mode... ✓ Built build/app/outputs/apk/debug/app-debug.apk. I/flutter ( 4932): 1 I/flutter ( 4932): 2
該当のソースコード The corresponding source code
dart
1main.dart 2 3import 'package:flutter/material.dart'; 4import 'package:http/http.dart' as http; 5import 'package:flutter_appauth/flutter_appauth.dart'; 6import 'package:flutter_auth_login_app/screen1.dart'; 7 8void main() => runApp(MyApp()); 9 10class MyApp extends StatelessWidget { 11 12 Widget build(BuildContext context) { 13 return MaterialApp( 14 title: 'Flutter Demo', 15 theme: ThemeData( 16 primarySwatch: Colors.blue, 17 ), 18 home: MyHomePage(title: 'Flutter Demo Home Page'), 19 ); 20 } 21} 22 23class MyHomePage extends StatefulWidget { 24 MyHomePage({Key key, this.title}) : super(key: key); 25 final String title; 26 27 _MyHomePageState createState() => _MyHomePageState(); 28} 29 30class _MyHomePageState extends State<MyHomePage> { 31 final String _clientId = 'test001'; // Client ID registered in the authentication server 32 final String _redirectUrl = 'jp.co.milabo:/oauthredirect'; // Specify this app as the redirect destination 33 34 final List<String> _scopes = <String>[ 35 'openid', 36 'offline_access', 37 ]; 38 39// String _codeVerifier; 40// String _authorizationCode; 41 String _accessToken; 42 String _refreshToken; 43 String _userInfo = ''; 44 45 final FlutterAppAuth _appAuth = FlutterAppAuth(); 46// final TextEditingController _authorizationCodeTextController = TextEditingController(); 47 final TextEditingController _idTokenTextController = TextEditingController(); 48 final TextEditingController _accessTokenExpirationTextController = TextEditingController(); 49 final TextEditingController _accessTokenTextController = TextEditingController(); 50 final TextEditingController _refreshTokenTextController = TextEditingController(); 51 52 final AuthorizationServiceConfiguration _serviceConfiguration = 53 AuthorizationServiceConfiguration( 54 'http://10.0.2.2:18080/…/auth', // Authentication endpoint of own authentication server NG 55 'http://10.0.2.2:18080/…/token' // Token endpoint of own authentication server NG 56 // 'https://demo.identityserver.io/connect/authorize', // Authentication endpoint of demo authentication server. OK 57 // 'https://demo.identityserver.io/connect/token'); // Token endpoint of demo authentication server. OK 58 ); 59 60 61 void initState() { 62 super.initState(); 63 } 64 65 void _loginFunc() async { 66 // Authentication and access, ID, and refresh token acquisition all at once 67 // 認証とアクセス、ID、リフレッシュトークン取得を一度にやる場合 68 print('1'); 69 try { 70 print('2'); 71 // It flows up to this point and the print statement is displayed. Then it doesn't go into try catch. 72 // ここまで流れてprint文が表示されている。その後 try catch には入らない 73 final AuthorizationTokenResponse result = 74 await _appAuth.authorizeAndExchangeCode( 75 AuthorizationTokenRequest( 76 _clientId, 77 _redirectUrl, 78 serviceConfiguration: _serviceConfiguration, 79 scopes: _scopes), 80 ); 81 82 print('3'); 83 // Stores access, ID, and refresh token. 84 // アクセス、ID、リフレッシュトークン格納 85 if (result != null) { 86 _accessToken = _accessTokenTextController.text = result.accessToken; 87 _idTokenTextController.text = result.idToken; 88 _refreshToken = _refreshTokenTextController.text = result.refreshToken; 89 _accessTokenExpirationTextController.text = result.accessTokenExpirationDateTime?.toIso8601String(); 90 } 91 92 // Get the API. 93 // API取得 94 print('4=$result'); 95 if (result != null) { 96 print('4 in'); 97 await _testApi(result); 98 } 99 100 // Screen transition 101 // 画面遷移 102 print('5'); 103 _gotoScreen1(); 104 105 // Error handling 106 // エラー処理 107 } catch(e) { 108 print('e=$e'); //エラー時のメッセージ出力 109 } 110 } 111 112 // Function to get API 113 // API取得 114 Future<void> _testApi(TokenResponse response) async { 115 final http.Response httpResponse = await http.get( 116 'http://10.0.2.2:18082/…/data', // APIのエンドポイント 117 headers: <String, String>{'Authorization': 'Bearer $_accessToken'}); 118 setState(() { 119 _userInfo = httpResponse.statusCode == 200 ? httpResponse.body : ''; 120 }); 121 } 122 123 // Function for screen transition 124 // 画面遷移 screen1 API取得後に遷移する画面 125 void _gotoScreen1() { 126 Navigator.pushReplacement( 127 context, 128 new MaterialPageRoute<Null>( 129 settings: const RouteSettings(name: "/screen1"), 130 builder: (BuildContext context) => Screen1(api:_userInfo), 131 ), 132 ); 133 } 134 135 // widget 136 137 Widget build(BuildContext context) { 138 139 return Scaffold( 140 appBar: AppBar(title: Text(widget.title),), 141 body: Center( 142 143 child: Column( 144 mainAxisAlignment: MainAxisAlignment.center, 145 children: <Widget>[ 146 147 Padding( 148 padding: EdgeInsets.only(bottom: 40), 149 child: Text('アプリ初期画面'), 150 ), 151 152 FlatButton(key:null, onPressed: _loginFunc, 153 shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(3.0)), 154 color: Color(0xFF4c6cb3), // 群青色 155 child: Text('ログインページへ',), 156 ) 157 ], 158 ), 159 ), 160 ); 161 } 162} 163
試したこと What I tried to do.
If I change the specified part of the authentication server with the same source code, it will fall, so
I was wondering if there is something missing from the value returned from the server to the app.
I am in trouble because no error message appears.
同じソースコードで、認証サーバの指定部分を変えたら落ちるので、
サーバからアプリに返す値に過不足があるのかと思ったのですが
エラーメッセージが出ないため困っています。
補足情報(FW/ツールのバージョンなど) Supplementary information (e.g. FW/tool version)
macOS Mojave
Flutter 1.12.13+hotfix.5
Tools • Dart 2.7.0
The explanation has become long, but I would appreciate your favor.
説明が長くなってしまいましたが、どうぞよろしくお願いいたします。
あなたの回答
tips
プレビュー