Firebase Authentication に備わっている匿名ユーザーを作成する機能についてのメモ。
※ Firebaseの覚書には連番が付いてますが内容は繋がっていません。
永久アカウントと匿名アカウントの違い
匿名認証を利用すると、アカウント作成時にメールアドレスや他サービスの資格情報を利用しないので、認証後のユーザー情報で空になるものがいくつかある。
firebase.User
User {
refreshToken: "..."
uid: "..."
displayName: null //←①
photoURL: null
email: null
emailVerified: false
phoneNumber: null
isAnonymous: true //←②
tenantId: null
metadata: UserMetadata
providerData: [] //←③
}
displayName
は OAuth系認証であればサービスで利用中の名前が設定されるが、匿名認証の場合は空になる。これはメールアドレス認証と同じで、アカウント作成時に名前を得る方法がないので設定されない。デフォルトのユーザー名を入れておきたいなら匿名認証後にユーザー情報を更新して設定しなければならない。
認証プロバイダを利用しないので providerData
は空配列になる。
一番の違いは isAnonymous
プロパティが true
になることである。
admin.auth.UserRecord
匿名認証のアカウントに対して admin.auth().getUser()を使用した場合、戻り値の UserRecord も似たような感じで殆ど空になるが、
このデータには isAnonymous
フラグが存在しない。
UserRecord {
uid: '...',
email: undefined,
emailVerified: false,
displayName: null,
photoURL: undefined,
phoneNumber: undefined,
disabled: false,
metadata: UserMetadata,
passwordHash: undefined,
passwordSalt: undefined,
customClaims: undefined,
tokensValidAfterTime: undefined,
providerData: []
}
ProviderDataが空配列の時点で匿名認証だと判断できるが、
DecodedIdToken の firebase プロパティが 何で認証したかの情報を持っているので、verifyIdToken() などDecodedIdTokenが戻り値になる関数を利用するならプロパイダ名がanonymous
かどうかで判断できる。
const decodedClaims = await admin.auth().verifyIdToken(idToken);
const isAnonymous = decodedClaims.firebase.sign_in_provider === 'anonymous';
匿名認証の利用
signInAnonymously を叩くだけ。これで匿名ユーザーが作成される。
const userCredential = await firebase.auth().signInAnonymously();
戻り値の UserCredential は次の通り。
{
user: User,
credential: null,
additionalUserInfo: {
providerId: null,
isNewUser: true
},
operationType: "signIn"
}
匿名認証もFirebase的には他の認証方法でログインしたアカウントと同じ権限を持っている。
他の認証方法でログインしたユーザーと差別化を図るなら、User.isAnonymous
プロパティがtrueかどうかで切り替えることになる。
匿名認証を永久アカウントに変換する
公式のドキュメントが妙に難解な書き方してあるが、要するに他の認証方法でログインさせてUserのlinkWith系メソッドで匿名アカウントにリンクさせれば良いだけのことである。
OAuth認証を利用する例
// @type {AuthCredential}
let provider;
switch (providerName) {
case 'google.com':
provider = new firebase.auth.GoogleAuthProvider();
break;
case 'twitter.com':
provider = new firebase.auth.TwitterAuthProvider();
break;
case 'facebook.com':
provider = new firebase.auth.FacebookAuthProvider();
break;
}
try {
// @type {UserCredential}
const { user } = auth.currentUser.linkWithPopup(provider);
} catch(e) {
console.error(e);
}
メールアドレス・パスワード認証を利用する例
// @type {AuthCredential}
const credential = firebase.auth.EmailAuthProvider.credential(email, password);
try {
// @type {UserCredential}
const { user } = await firebase.auth().currentUser.linkWithCredential(credential);
// 確認メールの送信
await firebase.auth().currentUser.sendEmailVerification({
handleCodeInApp: false
});
} catch (e) {
console.error(e);
}