MessageBirdで電話番号による認証
概要
このガイドでは、SMSベースのOTP(ワンタイム・パスワード)トークンでユーザーを認証する方法を紹介します。
SupabaseのSMS OTPトークンを使用する理由は2つあります。
- 携帯電話 + パスワードでログインし、携帯電話をSMSで認証したい
- 携帯電話のみでログインさせたい場合(パスワードなしでのログイン)
以下の内容を説明します。
必要なもの次の通りです。
- MessageBirdアカウント(サインアップはこちら:https://dashboard.messagebird.com/en/sign-up)
- Supabaseプロジェクト(ここで作成してください:https://app.supabase.com)
- SMSを受信できる携帯電話
手順
MessageBirdの認証情報を取得
まず、MessageBirdアカウントにログインし、テストに使用する携帯電話番号を確認します。https://dashboard.messagebird.com/en/getting-started/sms
この番号は、SMS OTPを受信する番号です。
ダッシュボードの設定に移動して、デフォルトのOriginatorを設定します。MessageBirdのOriginatorとは、メッセージの送信元となる名前または番号のことです。詳しくはこちらでOriginatorの選択に関するMessageBirdの記事をご覧ください。
はじめるにあたって、以下の値が必要です。
- 本番用APIキーとテスト用APIキー(Live API Key / Test API Key)
- MessageBird originator
SupabaseのダッシュボードのAuth → Settingsページに移動します(https://app.supabase.com/project/YOUR-PROJECT-REF/auth/settings)。
Phone Signup(電話による登録)を有効にするオプションがあります。
これをオンにして、messagebirdのダッシュボードから2つの値をコピーします。「Sava」をクリックします。
注意:テスト用APIキーを使用した場合、OTPは指定された携帯電話番号に配信されませんが、messagebirdは応答をダッシュボードに記録します。代わりに本番用APIキーを使用した場合、OTPは配信されますが、無料クレジットが差し引かれます。
MessageBirdの認証情報がはいります。
これでバックエンドの設定が完了したので、クライアント側のコードを追加していきましょう。
SMSカスタム・テンプレート
OTPコードを含む電話に送信されるSMSメッセージをカスタマイズできます。これは、ブランド名を記載したり、ウェブサイトのアドレスを表示したりする場合に便利です。
SupabaseのダッシュボードのAuth → Templatesページにアクセスします(https://app.supabase.com/project/YOUR-PROJECT-REF/auth/templates)。
コードを表示するには、テンプレートで変数.Code
を使用します。
パスワード・ベースのログインにOTPを使用
この使用例では、ユーザーの携帯電話番号をEメールアドレスの代わりに使用して、パスワードと一緒にサインアップします。しかし、この保持の仕方についてはよく考えた方がよいでしょう。携帯電話番号は、ユーザーが携帯電話の契約を解除したり、国を移動したりする際に、電話会社によって再利用されることがよくあります。近日中に多要素認証を追加し、このリスクを軽減する予定ですが、現時点では、緊急時にユーザーが他の方法でアカウントを回復できるようにすることを検討してみてはいかがでしょうか。
supabase-jsをクライアントで使用する場合、Eメールベースのサインアップに使用するのと同じsignUp
メソッドを使用します。その際に、email
の代わりにphone
パラメーターを使用します。
- JavaScript
- HTTP
let { user, error } = await supabase.auth.signUp({
phone: '+13334445555',
password: 'some-password',
})
curl -X POST 'https://cvwawazfelidkloqmbma.supabase.co/auth/v1/signup' \
-H "apikey: SUPABASE_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone": "+13334445555",
"password": "some-password"
}'
これで、ユーザーはSMSで6桁のピンを受け取ります。このピンは、ユーザーが自分のアカウントへログインする前の、60秒以内にユーザーから受け取る必要があります。
ユーザーが6桁のピンを入力できるようにフォームを表示し、電話番号と一緒に送信してVerifyOTP
を行う必要があります。
- JavaScript
- HTTP
let { session, error } = await supabase.auth.verifyOTP({
phone: '+13334445555',
token: '123456',
})
curl -X POST 'https://cvwawazfelidkloqmbma.supabase.co/auth/v1/verify' \
-H "apikey: SUPABASE_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "sms",
"phone": "+13334445555",
"token": "123456"
}'
成功した場合、ユーザーはログインし、有効な次のようなセッションを受け取ります。
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhdXRoZW50aWNhdGVkIiwiZXhwIjoxNjI3MjkxNTc3LCJzdWIiOiJmYTA2NTQ1Zi1kYmI1LTQxY2EtYjk1NC1kOGUyOTg4YzcxOTEiLCJlbWFpbCI6IiIsInBob25lIjoiNjU4NzUyMjAyOSIsImFwcF9tZXRhZGF0YSI6eyJwcm92aWRlciI6InBob25lIn0sInVzZXJfbWV0YWRhdGEiOnt9LCJyb2xlIjoiYXV0aGVudGljYXRlZCJ9.1BqRi0NbS_yr1f6hnr4q3s1ylMR3c1vkiJ4e_N55dhM",
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "LSp8LglPPvf0DxGMSj-vaQ"
}
supabase-jsでCRUD操作する際、AuthorizationヘッダーのBearerトークンとしてアクセス・トークンを送信できます。ユーザー単位でのアクセス制限については、「行単位セキュリティー」をご参照ください。
また、携帯電話が認証されたことで、ユーザーは毎回番号を認証する必要がなり、携帯番号とパスワードを使ってサインインできるようになります。
- JavaScript
- HTTP
let { user, error } = await supabase.auth.signIn({
phone: '+13334445555',
password: 'some-password',
})
curl -X POST 'https://cvwawazfelidkloqmbma.supabase.co/auth/v1/token?grant_type=password' \
-H "apikey: SUPABASE_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone": "+13334445555",
"password": "some-password"
}'
パスワード・レスのサインインの仕組みとしてOTPを使用する場合
このシナリオでは、ユーザーにパスワードを設定することなく、自分のアカウントにログインする機能を提供します。ユーザーは、ワンタイムパスワードを使って毎回携帯電話を認証するだけで、ログインできます。
javascriptでは、signIn
メソッドにphone
という1つのパラメーターを指定して使用します。
- JavaScript
- HTTP
let { user, error } = await supabase.auth.signIn({
phone: '+13334445555',
})
curl -X POST 'https://cvwawazfelidkloqmbma.supabase.co/auth/v1/otp' \
-H "apikey: SUPABASE_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone": "+13334445555"
}'
2番目の手順は、前のセクションと同じで、ユーザーから6桁のピンを収集し、電話番号と一緒にverifyメソッドへ渡す必要があります。
- JavaScript
- HTTP
let { session, error } = await supabase.auth.verifyOTP({
phone: '+13334445555',
token: '123456',
})
curl -X POST 'https://cvwawazfelidkloqmbma.supabase.co/auth/v1/verify' \
-H "apikey: SUPABASE_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "sms",
"phone": "+13334445555",
"token": "123456"
}'
と入力すると、上記のようなレスポンスが返ってきます。
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhdXRoZW50aWNhdGVkIiwiZXhwIjoxNjI3MjkxNTc3LCJzdWIiOiJmYTA2NTQ1Zi1kYmI1LTQxY2EtYjk1NC1kOGUyOTg4YzcxOTEiLCJlbWFpbCI6IiIsInBob25lIjoiNjU4NzUyMjAyOSIsImFwcF9tZXRhZGF0YSI6eyJwcm92aWRlciI6InBob25lIn0sInVzZXJfbWV0YWRhdGEiOnt9LCJyb2xlIjoiYXV0aGVudGljYXRlZCJ9.1BqRi0NbS_yr1f6hnr4q3s1ylMR3c1vkiJ4e_N55dhM",
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "LSp8LglPPvf0DxGMSj-vaQ"
}
このユーザーはパスワードを持っていないため、サービスを利用する際には毎回この方法でサインインする必要があります。