#1. はじめに
アプリケーションを作成していると複数のアカウント種別(何と表現していいのかわからない)を作成したくなることがあると思う。つまり、管理者アカウントと一般アカウントだったり、先生アカウントと生徒アカウントなど異なる属性のuserを作成するシチュエーションである。
Flutter×Firebaseの技術構成で上記のことを実現する方法を記事にする。
#目次
1.はじめに
2.前提
3.今回採用した方法
#2. 前提
まず前提として今回は先生アカウントと生徒アカウントが存在するアプリケーションを考える。
アカウントはFirebaseAuthを使って作成し、情報をFirestoreに保存する。
ここで、先生アカウントと生徒アカウントに持たせたい情報が同じであれば、/users/{id}などとし、documentのfieldにフラグを持たせて先生か生徒かを判別すれば良い。
しかし、先生と生徒に持たせる情報が大きく異なる場合、同じ階層のdocumentに違うスキームのdocumentが混ざってしまう。そこで、/teachers/{id}や/students/{id}などとしてデータを扱いたい。
しかし、上記のようにデータを格納するとauthで手に入れれる情報(userId)からでは先生か生徒か判断できないため、ユーザの情報を取得できない。一つの手段としては/users/{id}も作成し、そちらには先生と生徒の両方に共通するデータを保持し、さらに先生か生徒かを判別するフラグを立てることが考えられる。そうすることで、ログインした後に、/users/{id}から先生か生徒かを取得することができる。
デメリットとして考えられるのは、データが散らばってしまうことと、user情報を取得するために2回アクセスする必要があることなどが考えられる。2回アクセスしたら時間もかかりそう(知らんけど)
#3. 今回採用した方法
最近実践Firestoreを読んでいて知ったのですが、FirebaseAuthのCustomClaimsには任意のデータを置くことができるそう。つまりFirebaseAuthに先生か生徒かの情報を入れとけば、Authから判断してどちらのデータにアクセスするかを決めれる。さらに、CustomClaimsの値はセキュリティールールにも使えるため先生か生徒かという情報を使ってアクセスを制限することもできるようになる。一石二鳥である。
ただし、一つ注意が必要なのがCustomClaimsはAdmin SDKでアクセスしなければならない。
そこで、今回はCloudFunctionsを使ってCustomClaimsを設定する方法を取る。
CustomClaimsを設定する流れ
1.FirebaseAuthでアカウント作成
2.Firestoreにデータを保存(この際/teachers/{id}, /students/{id}のどちらかにdocumentを作成)
3.CloudFunctionsでdocumentの作成をトリガーにFirebaseAuthのアカウントにCustomClaimsを設定
1と2は今回の内容とは関係ないので3についてどのようなコードを書いたかを記載する。
exports.signUpAsATeacher = functions.region("asia-northeast1")
.firestore.document("teachers/{id}").onCreate(async (snap, context) =>{
const uid = snap.id;
console.log(uid);
firebaseAdmin.auth().setCustomUserClaims(uid, {
role: "teacher",
});
});
exports.signUpAsAStudent = functions.region("asia-northeast1")
.firestore.document("students/{id}").onCreate(async (snap, context) =>{
const uid = snap.id;
console.log(uid);
firebaseAdmin.auth().setCustomUserClaims(uid, {
role: "student",
});
});
上記の関数はそれぞれ/teachers/{id}もしくは/students/{id}にdocumentが生成された時に呼ばれる。
snap.idで生成されたdocumentIDを取得している。(これはauthのuserIDと一致させている。)
setCustomUserClaims()でCustomClaimsを設定する。
これで先生アカウントが作成された時には上の関数が、生徒アカウントが作成された時には下の関数が呼ばれ、それぞれCustomClaimsが適切に設定される。
設定されたCustomClaimsはFlutter側でどう取得するのって人のためにFlutter側のコードも少しだけ記述する。
final _auth = FIrebaseAuth.instance;
final userInfo = _auth.currentUser.getIdTokenResult(true);
String role = userInfo.claims["role"];
こんな感じでCustomClaimsは取得できる。
あとは取得したroleからfirestoreのデータを取得したり、画面遷移を変えるなりできる。
複数アカウント種別を管理するもっといい方法があるよという方がいらっしゃれば教えていただけると幸いです。