Dioを使ってAPIリクエストをする際、
APIトークンやJWTなどを自動で設定したいなと思い、
いろいろ調べたときの備忘録(*´ω`*)
Interceptorというrequest/response/errorをinterceptする
機能があるっぽいので、そこで追加するようにすればいいっぽい
認証用のInterceptor
独自のInterceptorクラスを作る場合には、
Interceptor
かQueuedInterceptor
を継承すればOK
Interceptorは並列に実行されるので、
順序性がある場合には、QueuedInterceptor
を利用する。
import "package:dio/dio.dart"; /// 現在のアクセストークンの取得 Future<String?> getAccessToken() async { return ... } /// リフレッシュトークンの取得 Future<String?> getRefreshToken() async { return ... } /// 認証用のInterceptor class AuthInterceptor extends QueuedInterceptor { AuthInterceptor(this.dio); final Dio dio; @override Future<void> onRequest( RequestOptions options, RequestInterceptorHandler handler, ) async { // Authorizationヘッダーが空のときのみ、自動で設定する if (options.headers['Authorization']?.isEmpty ?? true) { final accessToken = await getCurrentToken(); options.headers['Authorization'] = `Bearer $accessToken`; } return handler.next(options); } @override Future<void> onError( DioException err, ErrorInterceptorHandler handler, ) async { // 期限切れの場合は、強制更新してリトライ // 条件はステータスコードで判定(仮) if (err.response?.statusCode == 401) { final newAccessToken = await getRefreshToken(); err.requestOptions.headers['Authorization'] = `Bearer $newAccessToken`; return handler.resolve(await dio.fetch(err.requestOptions)); } return handler.next(err); } }
Interceptorの使い方
あとは作ったカスタムInterceptorをaddすればOK
import "package:dio/dio.dart"; /// Dioインスタンスの作成 Dio createApiClient() { final dio = Dio(); dio.interceptors.add(AuthInterceptor(dio)); return dio; }
Firebase AuthのidTokenを利用する場合
Firebase AuthのidTokenを利用する場合は、こんな感じにすればOK
import 'package:firebase_auth/firebase_auth.dart'; /// 現在のアクセストークンの取得 Future<String?> getAccessToken() async { return await FirebaseAuth.instance.currentUser?.getIdToken() } /// リフレッシュトークンの取得 Future<String?> getRefreshToken() async { return await FirebaseAuth.instance.currentUser?.getIdToken(true) }
以上!! 便利(*´ω`*)