【Supabase】Flutter + Supabase Authentication で Magic Link のサインアップ・サインイン処理のサンプル作った【Flutter】
こんにちは。pregum_foxです。
今回はFlutterでEmailを用いたMagic Linkのサンプルを作成します。
前回はEmail + password(確認メールありver)のサンプルを作成しました。
今回は下記のMagic Linkのサンプルを作成します。
Login With Magic Link | Supabase Docs
他の認証サンプルを見たい場合は下記から確認できます。
それでは目次です。
- ポイント
- 完成版
- 開発端末
- 検証端末
- Supabaseプロジェクトの作成
- API Keyの取得・設定
- Emailプロバイダの設定
- Magic Linkでのサインイン・サインアップ処理の実装
- 完成
- ローカルサーバの場合
- まとめ
- 雑感
- 参考URL
ポイント
Magic Linkのポイントは以下の4点です。
- アプリ内のsignInWithOtpの引数に設定するRedirect URLとサーバー側に設定するRedirect URLsを 完全に 一致させること
- 末尾の
/の有無だけでも処理が失敗する為、完全に一致させるようにコピー&ペーストで設定することをお勧めします。
- 末尾の
- マジックリンクでは新規ユーザーを作りたくない(サインインだけ通したい)場合は、signInWithOtpメソッドの
shouldCreateUserをfalseにすれば良い- メソッドのデフォルト値はtrue
- 認証フローにPKCE(ピクシーと呼称)フローを使用する場合は、同じ送信元と同じブラウザからのみ開くことができる(PKCEの仕様)
- 可能ならPKCEフローを選択する方がセキュリティ的には堅牢になる
- 例)DesktopのChoromeから送られたマジックリンクは、モバイル端末から使用不可
- 参考: Supabase Auth: SSO, Mobile, and Server-side support
- 一般公開するアプリのDeep linkのURLにはhttpsのschemeを使用する
- 偽アプリの乗っ取りを防ぐ為
- 参考:カスタムURLスキームの乗っ取りとその対策 - Akaki I/O
完成版
完成版は下記tagのリビジョンから確認できます。
下記リビジョンを使用している想定で、以下説明していきます。
開発端末
| 項目 | 内容 |
|---|---|
| OS | M1 Mac |
| Flutter | 3.13.17 |
fvm flutter doctor Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel stable, 3.13.7, on macOS 14.1 23B74 darwin-arm64, locale ja-JP) [✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0) [✓] Xcode - develop for iOS and macOS (Xcode 15.0) [✓] Chrome - develop for the web [✓] Android Studio (version 2022.3) [✓] VS Code (version 1.83.1) [✓] Connected device (4 available) [✓] Network resources • No issues found!
検証端末
| 端末名 | version |
|---|---|
| Google Pixel 3a | Android 12 |
| iPhone X | iOS 16.6 |
Supabaseプロジェクトの作成
下記記事の「Supabaseプロジェクト作成」の段落に記載されている手順に沿ってSupabaseプロジェクトを作成します。
【Supabase】Flutter + Supabase Authでソーシャルログイン(GitHub)のサンプルを作った【Flutter】 - 狐好きぷろぐらまー
API Keyの取得・設定
API Keyの取得
下記記事の「API Keyの取得」の段落に記載されている手順に沿ってURLとanonを取得します。
【Supabase】Flutter + Supabase Authでソーシャルログイン(GitHub)のサンプルを作った【Flutter】 - 狐好きぷろぐらまー
API Keyの設定
下記記事の「API Keyの設定」の段落に記載されている手順に沿ってURLとanonを取得します。
【Supabase】Flutter + Supabase Authでソーシャルログイン(GitHub)のサンプルを作った【Flutter】 - 狐好きぷろぐらまー
Emailプロバイダの設定
Email認証 の有効化の確認
下記記事の「Emailプロバイダの設定」の段落に記載されている手順に沿ってEmail認証が有効になっていることを確認します。
Redirect URLsとアプリ側のカスタムURLの設定の確認
それでは、マジックリンクのURLをクリックして、サンプルアプリへ自動的に遷移するようにします。
とはいえ、完成版ではすでに設定している為ここでは確認だけします。
sehemeとhostについては、下記ページなどで解説されていますので、ちょっと分からないよ、という方はご覧ください。
Android
Androidは、リポジトリ直下のディレクトリからandroid/app/src/main/AndroidManifest.xml に記載しています。
こちらのintent-filter > data タグ にscheme(https: や io.supabase.flutterquickstart:)とhost(login-callbackやcallback) が記載されています。

iOS
iOSは、リポジトリ直下のディレクトリからios/Runner/Info.plist に記載されています。
ちなみにDeep Linkに独自機能を盛り込んだものにiOSはUniversal Links、AndroidはApp Linksという機能がありますが、細かい違いとしては下記機能が含まれています。
- ブラウザで特定のドメインのサイトを開いた時、自動的にアプリへ遷移させる機能も含まれています。
違いについて説明されているサイトがありましたのでこちらに記載します。
ディープリンク、ユニバーサルリンク、アプリリンクとかの話 | am10ぶろぐ

Magic Linkでのサインイン・サインアップ処理の実装
ソースコードとしては下記の部分がマジックリンクでのサインイン・サインアップ処理になります。
// login_page.dart 133行付近 await supabase.auth.signInWithOtp( email: _magicLinkEmailController.text, // magic linkのメールを飛ばすurl shouldCreateUser: _shouldCreateUser, // サインアップ時のuser作成フラグ(default: true) // 下記URLがsupabase projectのRedirect URLsと一致していないと、リダイレクト後サインインできない(仕様) // ref: https://github.com/supabase/supabase/issues/11995#issuecomment-1647874100 emailRedirectTo: 'io.supabase.flutterquickstart://login-callback/', );
emailは上記に書いている通り、emailのメールアドレスにマジックリンクを送ります。shouldCreateUserはまだ登録されていないメールアドレスでサインアップを許可するかのフラグです。falseであれば、サインインのみ可能でサインアップはエラーになります。 その場合は、パスワード認証などでサインアップさせ、それ以降はマジックリンクというユースケースで役立つと思います。trueであれば、サインイン・サインアップどちらも許可されます。
emailRedirectToについては、supabaseプロジェクトの「URL Configurations 」>「Redirect URLs」に設定したURLと 完全に 一致させる必要があります。- この値が未記入だったり、異なっているとエラーが出ますので、エラーが返ってきましたら、この値が合っているか確認してください。
他のパラメータについては下記を参照ください。
signInWithOtp method - GoTrueClient class - supabase_flutter library - Dart API
完成
上記の設定でMagic Link処理を実行するための準備が完了しました。
お疲れ様でした。
ローカルサーバの場合
前回から引き続きローカル環境でも動作を確認します。
Supabaseのローカルサーバを立ち上げる
まずは、下記記事の「ローカルにメールサーバを立てて、検証する」のところから「ローカルサーバのEmailプロバイダの設定(確認メール有効化)」までを手順に沿って進めてもらい、ローカル環境でサーバを立てます。
- Magic linkでもメールの確認は必要なので、config.tomlも手順通りにいじる必要があります。
additional_redirect_urls の設定
Magic Linkではリダイレクト先のURLを設定する必要があります。
アプリのリポジトリ直下のsupabase/config.toml ファイルの [auth] の下にあるadditional_redirect_urls の値にコールバックのURLを設定してください。
配列ですので、複数設定することは可能です。

Inbucket上でメール確認
上記の設定ができましたら、環境変数のURLとanonkeyをローカル環境のURLとanonkeyを使用して、アプリを起動します。
その後Magic linkの場合は、iOS・Android端末から開く必要がありますが、http://localhost:54324 のようにlocalhostでアクセスしようとすると、「見つかりません」のようなメッセージが表示される場合は、localhostの箇所をローカルサーバを立てているPCのプライベートIPアドレスに変更する必要があります。
調べ方はmacやlinuxではターミナル上でifconfigと入力し、表示された文字列のen0の項目にIPv4の値がありますので、その値を入れれば良いです。

上記のプライベートIPアドレスの場合は、http://192.168.0.9:54324 というURLでInbucketにアクセスできます。
特にiOSの場合は確認メールをタップした後、リンク先のURLがlocalhostのドメインになっている為、自分でプライベートIPアドレスに打ち直してアプリへリダイレクトするという力技で確認することになります...悲しい🫠
Androidの場合は、PC側でChromeのchrome://inspect/#devices のページ上でlocalhostのport forwarding を設定することで自分で打ち直さなくても自動的に遷移できるようになっていますので、リンク先にプライベートIPアドレスを入れられるまでは上記のような回避策で対応することになりそうです。
おそらく、self-hostingで使用するsupabaseのdockerイメージである下記リポジトリのdocker-compose.ymlか.env.exampleをいじれば良さそうなのですが、知識不足で他にも調べたいことがあったので、一旦調査はやめました。
ただ、上記はローカル環境でのみの話で、通常本番環境などで使用する場合は関係ない話なので一般ユーザーへ公開する場合は問題なくリダイレクトしてくれます。
まとめ
Flutter + SupabaseでのMagic Linkでのサインイン・サインアップの手順は以下の通りです。
- Supabaseプロジェクトの作成
- API Keyの取得・設定
- メール認証のプロバイダの有効化
- 対象のSupabaseプロジェクトのRedirect URLsの設定
- アプリ側でRedirect URLsで設定したURLでの遷移用にカスタムURLを設定
- Magic Linkでのサインイン・サインアップ処理の実装
難所は、4.と5.のDeep LinkのURL設定かと思います。
また、ローカル環境での認証処理の検証はどうしてもlocalhostへのアクセスがうまくできない場合がある為、手入力で切り替えるかPC側の設定でlocalhostのport forwarding を設定する必要があります。
雑感
iOSではlocalhostがアクセスできると思っていましたが、うまくいかない時があり開発する上では、httpとモバイルの相性があんまり良くないのかなと思いました。
localhostについては、dockerがチョットデキル 方ならささっと解決できそうな問題である分Docker周りはGitと同じレベルで空である程度使えるようになりたいなと思いました。
またDeep LinkとUniversal LinksやApp Linksについてあまり理解できていなかったので、記事を書いていく上で調べて違いについてはっきりわかるようになったのはよかったです。
ここまで読んでいただきありがとうございます。