本稿は Ateam Finergy Inc. Advent Calendar 2020 の 5 日目の記事です。本稿では Rails + Next.js + Firebase Authentication を使ってサンプルアプリを作成します。
- ソースはこちら:https://github.com/kmgk/rails-next-firebaseauth-sample
- デモページ:https://rails-next-firebaseauth-sample-private.vercel.app/
動機
firebase authentication はいいぞという記事を見かけて、最近触り始めた Next.js と Rails を使って素振りしてみるかと思ったのがきっかけです。ちなみに firebase は flutter でモバイルアプリを開発していたときに使ったことがありますが、そのときはバックエンドを完全に firebase に任せっきりだったので、認証部分だけ使うというのは初めてです。
firebase プロジェクトを作成する
firebase プロジェクトを作成して、自分が使いたいプロバイダを有効にします。また、この少し下に認証済みドメインを設定する場所があるので、適宜設定してください。
また、トップページから web アプリを作成し、Firebase SDK snippet が参照できる状態にしておきます。これは Rails 側でも Next.js 側でも使います。
バックエンド(Rails)の実装
認証に関して Rails でやることは、Next.js から送られてきた jwt を検証するだけです。
Firebase Admin SDK を使用すると簡単に jwt を検証することができるのですが、残念ながら Ruby はサポートされていません。
しかし検証部分を Ruby で実装されている方がいたのでありがたく使わせてもらいました。
トークンは Authorization
ヘッダーに Bearer ${token}
という形で送られてくるので、そのトークンを検証することになります。この検証を認証が必要な操作の前に行い、token の検証に失敗すると 401 Unauthorized を返すようにします。具体的な実装は app/controllers/concerns/api/v1/firebase_auth_concern.rb
にあります。
def authenticate_token_by_firebase
# Authorization: Token ${token} or Bearer ${token}がない場合スキップされる
authenticate_with_http_token do |token, _|
# tokenを検証する。
end
{ error: 'token invalid' }
end
フロントエンド(Next.js)の実装
Next.js で firebase を使う方法は詳しい記事がたくさんあると思うのでそちらを参考にしてもらって、ここではトークンを送るところのコードだけ載せます。ここでは axios を使用しています。
const currentUser = auth.currentUser;
// トークンを取得
const token = await currentUser.getIdToken(true);
// Authorization: Bearerヘッダでトークンを送信する
const config = { headers: { authorization: `Bearer ${token}` } };
try {
await axios.get('/users/new', config);
} catch (error) {
console.log(error);
}
また、ここには書いていませんが現在ログイン済みかどうかを判断するために、react-firebase-hooksを使用しています。非常に使い勝手がよかったので(auth しか使っていませんが)ぜひ使ってみてください。
最後に
本当はもっと解説しようかと思っていたのですが、調べていたら Next.js 側も Rails 側にもほとんど実装されているものが存在していたので結局それらの切り貼りをしただけになってしまいました。せっかく作ったので半分供養みたいな形で記事にしました。
firebase authentication は本当に楽だったのでこれからも個人で開発するときは使っていこうかなと思います。