[Firebase v9] [Nuxt3] [LIFF]LINE アカウントでカスタム認証
⓪ログインしているユーザーを取得する
現在ログインしているユーザーの情報を取得する方法は2つある。
前提
まずは Firebase アプリを initializeApp()
で初期化する。
const config = useRuntimeConfig()
const firebaseConfig = {
apiKey: config.public.apiKey,
authDomain: config.public.authDomain,
projectId: config.public.projectId,
appId: config.public.appId,
}
const app = initializeApp(firebaseConfig)
const auth = getAuth(app)
初期化したFirebase アプリを引数に getAuth()
で生成した auth
オブジェクトに、auth 周りの全てが格納されている。
auth.currentUser
現在ログインしているユーザーの情報は単純に auth.currentUser で取得できる。
onAuthStateChanged(auth, (user) => ... )
auth
オブジェクトを監視するオブザーバを設置して、現在ログインしているユーザー情報を取得することもできる。
トリガーはログイン/ログアウトのみ。ログインを感知したら情報の詰まった user
が、ログアウトを感知したら null の user
が返ってくる。
オブザーバは1つで十分なので、アプリ起動時に実行される plugin に処理を記述する。plugin はSSRだとサーバサイドとクライアントサイドで二回実行されてしまうため、.client というサフィックス付与でクライアント側のみの1回だけ実行。
アプリ内で2つ以上オブザーバを設置してしまう場合は、重複してしまうため、きちんとオブザーバを解除する必要がある。
const unsubscribe = onAuthStateChanged(auth, (user) => ... )
unsubscribe()
これだと「オブザーバ」という役割を果たしてないし、使用するケースは今のところ思いつかない。多分コンポーネント単位で監視したいときかなと思う。
プロフィール情報を更新したとき
updateProfile(auth.currentUser, updateData)
でプロフィールを更新できるが、onAuthStateChanged()
はこの変更は感知しない。そのためこのままだと firebase上で更新されただけなので、auth.currentUser.reload()
でアプリ内の auth オブジェクトも強制的に最新にする。
updateProfile(auth.currentUser, updateData).then(async () => {
await auth.currentUser.reload()
// その他処理
})
①未ログインの場合、LINE アカウントを使用して Firebase にログインする
具体的には、LINEアカウントの uid を使って Firebase のカスタム認証を行っていく。
頭の整理
Firebase カスタム認証を実行するためには、firebase-admin の createCustomToken() で発行するカスタムトークンが必要。
そのカスタムトークンを発行するためには、LINE アカウントの uid の文字列が必要。
LINE アカウントの uid を取得するためには、LINE Platform からプロフィール情報の取得が必要。
LINE Platform からプロフィール情報を取得するためには、ログインしている LINE アカウントによって LINE SDK で発行されたアクセストークンが必要。
LIINE SDK で発行されたアクセストークンは、LIFFアプリの初期化時に取得できる。
主な関数とフロー
参考: アプリとサーバーの間で安全なログインプロセスを構築する
- LIFFの初期化
liff.init({ liffId })
- LINE SDK からアクセストークンを取得
liff.getAccessToken()
- アクセストークンをサーバに送り、LINE Platform と通信してそのトークンが安全で有効なものなのかを検証(ステータス、チャンネルID、期限、の3点チェック)
- 有効なら、そのトークンを使って LINE Platform からユーザーのプロフィール情報(uid、表示名, 画像URL, 一言)を取得
- 取得した uid を引数に firebase-admin の createCustomToken() でカスタムトークンを生成
- 取得したプロフィール情報と発行したカスタムトークンをクライアントに返し、カスタムトークンを引数として
signInWithCustomToken()
で Firebase カスタム認証をクライアント上で行う - ⓪のオブザーバが感知する
脆弱性のある危険なフロー
- LIFFの初期化
liff.init({ liffId })
- LINE SDK からアクセストークンを取得
liff.getAccessToken()
- アクセストークンを用いて LINE Platform からプロフィール情報を取得する
- その取得した uid をサーバーに渡す
- 渡された uid を用いて
createCustomToken()
を実行 <- この渡された uid は信用できない!
...つまり、クライアント上で取得したプロフィール情報は偽装できてしまうのでサーバには送るな、サーバサイドでプロフィール情報を取得せよ、取得するにはクライアント側で発行したアクセストークンをサーバに送って用いてね、使う前にそれが信用できるものか検証してから使ってね、ということ。
Discussion