メインコンテンツまでスキップ

Twilioで電話による認証

概要

このガイドでは、SMSベースのOTP(ワンタイム・パスワード)トークンでユーザーを認証する方法を紹介します。

SupabaseのSMS OTPトークンを使用する理由は2つあります。

  • 携帯電話番号 + パスワードでログインし、携帯電話番号をSMSで認証したい
  • 携帯電話番号のみでログインさせたい場合(パスワードなしでのログイン)

以下の内容を説明します。

必要なものは次の通りです。

動画

手順

Twilioの認証情報を取得

まず、Twilioアカウントにログインし、新しいプロジェクトを立ち上げます。https://www.twilio.com/console/projects/create

プロジェクトに名前を付け、テストに使用する携帯電話の番号を確認します。これは、SMSのOTPを受信する番号です。

Name your twilio project verify your own phone number

ウェルカム・フォームの選択肢で、「SMS」、「Identity & Verification」、「With code」を選択します。

Form Fields

[Twilioコンソール画面][https://www.twilio.com/console]に戻ったら、下にスクロールして「Get a trial phone number」をクリックしてください。

Get a trial phone number

Successful phone number

これで、開始するために必要な3つの値がすべて表示されます。

  • Account ID
  • Auth Token
  • Sender Phone Number

All the credentials you'll need

SupabaseのダッシュボードのAuth → Settingsページに移動します(https://app.supabase.com/project/YOUR-PROJECT-REF/auth/settings)。

Phone Signup(電話による登録)を有効にするオプションがあります。

Enable Phone Sign-Up

これをオンにして、twilioダッシュボードから3つの値をコピーします。「Sava」をクリックします。

注:「Twilio Message Service SID」には、上記で作成した送信者の電話番号を使用できます。

Plug in Twilio credentials

これでバックエンドの設定が完了したので、クライアント側のコードを追加していきましょう。

SMSカスタム・テンプレート

OTPコードを含む電話に送信されるSMSメッセージをカスタマイズできます。これは、ブランド名を記載したり、ウェブサイトのアドレスを表示したりする場合に便利です。

SupabaseのダッシュボードのAuth → Templatesページにアクセスします(https://app.supabase.com/project/YOUR-PROJECT-REF/auth/templates)。

OTPコードを表示するには、テンプレートで変数.Codeを使用します。次にSMSテンプレートの例を示します。

example in the SMS template

パスワード・ベースのログインにOTPを使用

この使用例では、ユーザーの携帯電話番号をEメールアドレスの代わりに使用して、パスワードと一緒にサインアップします。しかし、この保持の仕方についてはよく考えた方がよいでしょう。携帯電話番号は、ユーザーが携帯電話の契約を解除したり、国を移動したりする際に、電話会社によって再利用されることがよくあります。近日中に多要素認証を追加し、このリスクを軽減する予定ですが、現時点では、緊急時にユーザーが他の方法でアカウントを回復できるようにすることを検討してみてはいかがでしょうか。

supabase-jsをクライアントで使用する場合、Eメールベースのサインアップに使用するのと同じsignUpメソッドを使用します。その際に、emailの代わりにphoneパラメーターを使用します。

let { user, error } = await supabase.auth.signUp({
phone: '+13334445555',
password: 'some-password',
})

これで、ユーザーはSMSで6桁のピンを受け取ります。このピンは、ユーザーが自分のアカウントへログインする前の、60秒以内にユーザーから受け取る必要があります。

ユーザーが6桁のピンを入力できるようにフォームを表示し、電話番号と一緒に送信してVerifyOTPを行う必要があります。

let { session, error } = await supabase.auth.verifyOTP({
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トークンとしてアクセス・トークンを送信できます。ユーザー単位でのアクセス制限については、「行単位セキュリティー」をご参照ください。

また、携帯電話が認証されたことで、ユーザーは毎回番号を認証する必要がなり、携帯番号とパスワードを使ってサインインできるようになります。

let { user, error } = await supabase.auth.signIn({
phone: '+13334445555',
password: 'some-password',
})

パスワード・レスのサインインの仕組みとしてOTPを使用する場合

このシナリオでは、ユーザーにパスワードを設定することなく、自分のアカウントにログインする機能を提供します。ユーザーは、ワンタイムパスワードを使って毎回携帯電話を認証するだけで、ログインできます。

javascriptでは、signInメソッドにphoneという1つのパラメーターを指定して使用します。

let { user, error } = await supabase.auth.signIn({
phone: '+13334445555',
})

2番目の手順は、前のセクションと同じで、ユーザーから6桁のピンを収集し、電話番号と一緒にverifyメソッドへ渡す必要があります。

let { session, error } = await supabase.auth.verifyOTP({
phone: '+13334445555',
token: '123456',
})

と入力すると、上記のようなレスポンスが返ってきます。

{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhdXRoZW50aWNhdGVkIiwiZXhwIjoxNjI3MjkxNTc3LCJzdWIiOiJmYTA2NTQ1Zi1kYmI1LTQxY2EtYjk1NC1kOGUyOTg4YzcxOTEiLCJlbWFpbCI6IiIsInBob25lIjoiNjU4NzUyMjAyOSIsImFwcF9tZXRhZGF0YSI6eyJwcm92aWRlciI6InBob25lIn0sInVzZXJfbWV0YWRhdGEiOnt9LCJyb2xlIjoiYXV0aGVudGljYXRlZCJ9.1BqRi0NbS_yr1f6hnr4q3s1ylMR3c1vkiJ4e_N55dhM",
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "LSp8LglPPvf0DxGMSj-vaQ"
}

このユーザーはパスワードを持っていないため、サービスを利用する際には毎回この方法でサインインする必要があります。

リソース