Firebaseの電話番号認証の代わりにAuthyを使う
こちらの記事でFirebaseの電話番号認証を使用してみましたが、SMSの送信に関してどうにも不安定なので、代替策としてTwilioのAuthyを使ってみます。
Firebase Authenticationでのユーザー管理は別に実装するとして、SMSの送信・トークンの認証までをCloud Functions上で簡単に動作確認してみました。
なお、Cloud Functionsで外部APIを叩くため、FirebaseプロジェクトはFlameプラン($25/月)かBlazeプラン(従量制)である必要があります。
ソースコードやスクリーンショットはExpo・ReactNativeでのアプリ開発を想定していますが、本質的な部分はなんでも共通なはずなので、画面の構築に関するコードは省略しています。
AuthyのAPI Keyを取得
Twilioのアカウント、プロジェクトを作成後、開発者ページの左のメニューからAuthyを選択し、プロジェクトに導入します。
最初は500円の無料枠があり、一回SMSを送るたびに10円前後減っていきます。
この後チュートリアルのようなページになりますが、APIキーがコピーできた段階で中断してOKです。
Cloud Functionsに関数を追加
AuthyのAPIを使うためのパッケージはいくつかあり、
公式のドキュメントではauthy
が使われているのですが、
Cloud FunctionsのPromiseチェーンで扱いやすいためauthy-client
を使用してみます。
$ cd functions
$ npm install --save authy-client
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const AuthyClient = require("authy-client").Client;
admin.initializeApp();
const db = admin.firestore();
const authy = new AuthyClient({ key: "ここに APIキー" });
Cloud Functionsのセットアップについては省略します。
まずFirestoreを扱うための準備と、authy-client
にAPIキーを渡してAuthyクライアントを初期化します。
SMS送信・DBに保存する関数
verifyPhoneNumber
関数を追加します。国コード、メールアドレス、電話番号からAuthyにユーザーを追加して、AuthyでのユーザーIDを含めてFirestoreのmembers
コレクションにユーザー情報を保存します。
クライアント側にはmember
ドキュメントのIDを返して、あとから認証コードと照らし合わせるためのIDとして使います。
exports.verifyPhoneNumber = functions.https.onCall(
({ countryCode, email, phoneNumber }) => {
return authy
.registerUser({
countryCode,
email,
phone: phoneNumber
})
.then(response => {
return response.user.id;
})
.then(authyId => {
return Promise.all([
db.collection("members").add({
authyId,
email,
countryCode,
phoneNumber,
phoneNumberVerification: false,
createdAt: admin.firestore.Timestamp.now()
}),
authy.requestSms({ authyId })
]);
})
.then(([docRef]) => {
return docRef.id;
});
}
);
認証コードと照らし合わせる関数
クライアント側からはmember
ドキュメントのIDと、SMSで送られてきた認証コードを渡して、functionsでこれを照らし合わせます。
認証が成功したら、member
ドキュメントのphoneNumberVerification
フラグをtrue
にするなど、適宜処理します。
exports.verifyPhoneNumberToken = functions.https.onCall(({ id, token }) => {
const docRef = db.collection("members").doc(id);
return docRef
.get()
.then(docSnapshot => {
return authy.verifyToken({
authyId: docSnapshot.data().authyId,
token
});
})
.then(() => {
return docRef.update({
phoneNumberVerification: true
});
})
.then(() => {
return docRef.get();
});
});
クライアント側の処理
このように電話番号を入力する画面を用意し、
Cloud Functionsの関数(verifyPhoneNumber
)を叩きます。countryCode
やemail
はひとまず固定で。
関数から返ってきたIDはstateに保持しておきます。
verifyPhoneNumber = async values => {
const { phoneNumber } = values;
try {
const {
data: verificationId
} = await firebase.functions().httpsCallable("verifyPhoneNumber")({
countryCode: "81",
phoneNumber,
email: "[email protected]"
});
console.log("verificationId", verificationId);
this.setState({ verificationId });
} catch (e) {
console.log(e);
}
};
Authy APIが無事に通ったら、入力した電話番号にSMSが届くはずです。画像のauth-test
の部分はTwilioで設定したAuthyのプロジェクト名が入ります。
stateにverificationId
がセットされたら認証コードの入力欄を表示するようにします。
あとは、再びCloud Functionsの関数(verifyPhoneNumberToken
)を叩き、入力された認証コードを照らし合わせます。
verifyPhoneNumberToken = async values => {
const { verificationId } = this.state;
const { verificationCode } = values;
try {
const { data: member } = await firebase
.functions()
.httpsCallable("verifyPhoneNumberToken")({
id: verificationId,
token: verificationCode
});
console.log(member);
Alert.alert("成功", "認証が完了しました");
} catch (e) {
console.log(e);
}
};
Firestoreにmember
ドキュメントが追加されており、phoneNumberVerification
フラグがtrue
になっているのが確認できました。
Author And Source
この問題について(Firebaseの電話番号認証の代わりにAuthyを使う), 我々は、より多くの情報をここで見つけました https://qiita.com/mildsummer/items/5a3892435debd76529ef著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .