やりたいこと
Firebase Auth では認証ユーザーに対してトークン(JWT)が発行でき、これを用いることで API Gateway にて正しいトークンか確認することができる。(JWT認証)
これを使い、Firebase Auth で認証されているユーザーしかアクセスできない API を作成しよう。
動作の流れ
- Firebase Auth によりトークンを発行
- トークンを入れ込んで API にアクセス
- API Gateway は受け取ったトークンが正しいかを Firebase Auth に対して確認する
- 認証が通ったやつだけ Lambda へアクセス
実装
アクセス成功確認用の Lambda を作成する
アクセス成功の確認がしたいだけなので、実質何でも OK。
exports.handler = async (event, context, callback) => {
const { jwt } = event.requestContext.authorizer;
let response = {
statusCode: 200,
body: JSON.stringify({
jwt: jwt,
}),
headers: {
'Content-Type': 'application/json',
}
};
callback(null, response);
};
API Gateway で Lambda 設定
JWT 認証を使うため、API タイプ は HTTP API
を選択する。
エンドポイントができたら適当にルートを作って、統合からさっき作った Lambda に接続する。
API Gateway で JWT 認証を設定する
AWS コンソールの API Gateway のページへ。
左の認可タブを開き、さっき作ったルートを選んで「オーソライザーを作成してアタッチ」をクリックする。設定が開くので以下を入力して保存すれば OK。
- 名前: FirebaseAuthorizer
- ID ソース: $request.header.Authorization
- 発行者 URL:
https://securetoken.google.com/FirebaseのプロジェクトID
- プロジェクトIDは Firebase コンソールのプロジェクトの設定から見れる
- 対象者: プロジェクトID をそのまま入れる
これだけで終わり。
Dart でアクセスしてみる
getIdToken()
でトークンが取得できるので、それを使ってアクセスしてみよう。
import 'package:http/http.dart' as http;
final user = FirebaseAuth.instance.currentUser!;
final token = await user.getIdToken();
final headers = {
'Authorization': 'Bearer ' + token // Bearer の後のスペースが大事
};
final url = Uri.parse('https://hogehogeapi...');
final response = await http.get(url, headers: headers);
if (response.statusCode == 200) {
debugPrint(response.body);
} else {
debugPrint(response.reasonPhrase);
}
ただ、いちいち getIdToken()
のリクエストを送るのはもったいない。idTokenChanges()
でトークンが変更をリッスンできるので、これで変更次第どっかに保存して使いまわす感じにするのが良さそう。
FirebaseAuth.instance
.idTokenChanges()
.listen((User? user) {
// トークン取得してどっかに保存するとか
});