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 を作ろうと思う。