Firebase がデフォルトで対応してない OAuth2 Provider に Firebase でログイン できたら便利だなと思ったのでやってみる。今回僕が扱いたい「Firebase がデフォルトで対応してない OAuth2 Provider」というのは今働いている会社であるところのユビレジです。
カスタム認証というのが提供されていて、そういうことをしたい時これを利用すればよいのだと思われる。ところが、これは基本的にはサーバーサイドで Firebase とやり取りして認証用トークンを作成する必要がある。
今回いじりたいのは自社サービスなので、そっちをいじってもいいのだろうと思う。ただまあめんどうなのでクライアントサイドと Cloud Functions だけで問題を解決したい。
というわけで CloudFunctions 側に以下のようなものを実装した。ここにある oauth2 というのは simple-oauth2 というライブラリのアレです、アレ。 redirect_uri はとりあえず http://localhost:5000/callback を指定している。
exports.auth = functions.https.onRequest((req, res) => {
const authorizationUri = oauth2.authorizationCode.authorizeURL({ redirect_uri: redirect_uri });
res.redirect(authorizationUri);
});
exports.callback = functions.https.onRequest((req, res) => {
const tokenConfig = {
code: req.query.code,
redirect_uri: redirect_uri
};
// ユビレジの accessToken を取得
oauth2.authorizationCode.getToken(tokenConfig).then((result)=>{
const accessToken = oauth2.accessToken.create(result);
const account_id = String(accessToken.token.account_id);
// カスタムトークンを生成
admin.auth().createCustomToken(account_id).then((customToken)=>{
// ユビレジの accessToken を firestore に保存しておく
const db = admin.firestore()
const ref = db.collection('credentials').doc(account_id)
ref.set(accessToken.token).then(()=>{
ref.update(accessToken.token).then(()=>{
res.redirect(`/?customToken=${customToken}`);
});
});
});
});
});
ルーティングは以下のように
- / は index.html を普通に返す
- /auth で ↑ の auth
- /callback で ↑ の callback
を使う。
で index.html 側では location.search を見て customeToken があれば
firebase.auth().signInWithCustomToken
で認証してやっていく。たぶんこれでセキュリティ上の問題もない、よね?
これで Firebase Hosting と Firebase Cloud Functions だけで Firebase がデフォルトで対応していない OAuth2 Provider にログインが出来た。
サーバサイドで accessToken などを Cloud Firestore に入れているので、認証後はそこから accessToken をとってきてユビレジ API にアクセスできる。
というつもりだったのだが、ここまで作って気付いたことがあり、なんとユビレジ API は CORS 対応してないので、 Cloud Functions でプロキシしてあげないといまのままだと動かない、、、
というわけなので CORS 対応 Pull Request を作ろうと思う。