はじめに
FirebaseAuthを利用してWebサービスを作成している際
同一アカウントへの同時ログイン(二重ログイン)を制限したい要望がありました。
テスト的に(少々強引に)実装してみた手法についてのメモです
記事の対象の環境について
サーバサイド処理はcloud functionsにて
クライアントサイドはVue.js + firebaseにて構築しています。
方針
revokerefreshtokensを呼び出して、ログインの処理を行うときに過去にログインしていた状態を破棄するようにしてみる
サーバサイド実装
const admin = require('firebase-admin');
admin.initializeApp();
export const func1 = functions.region('asia-northeast1').https.onCall(async (data, context) => {
const uid = data.uid
await admin.auth().revokeRefreshTokens(uid)
return 'OK'
});
クライアント実装
<template>
<div>
<input type="email" v-model="email"/>
<input type="password" v-model="password"/>
<button @click="login">login</button>
</div>
</template>
<script>
import firebase from "firebase";
async function sleep(sec) {
return new Promise(resolve => setTimeout(resolve, sec * 1000));
}
export default {
name: "SignIn",
data: [
email: "",
password: ""
},
methods: {
async login() {
try {
// ログイン処理1回目
const result = await firebase
.auth()
.signInWithEmailAndPassword(this.email, this.password);
// cloud functionに定義したfunc1を呼び出す
const func1 = firebase.app().functions("asia-northeast1").httpsCallable('func1');
await func1(result.user.uid);
// @todo クラウドファンクションの処理を待つためにsleepさせている
await sleep(2);
// ログイン処理2回目
const result2 = await firebase
.auth()
.signInWithEmailAndPassword(this.email, this.password);
this.$router.push('/private/space');
}
} catch (e) {
alert("ログインに失敗しました");
}
}
}
最後に
これらの方法でとりあえずの同時ログインの禁止(以前にログインしたセッションは強制ログアウトする)を実装することはできました。
sleepさせている処理など、タイミングによって問題になりそうな処理ではあるので
なにかいい方法があればいいのですが。