狐好きぷろぐらまー

狐好きプログラマーのブログです。

【Supabase】Flutter + Supabase Authentication で Magic Link のサインアップ・サインイン処理のサンプル作った【Flutter】

こんにちは。pregum_foxです。

今回はFlutterでEmailを用いたMagic Linkのサンプルを作成します。

前回はEmail + password(確認メールありver)のサンプルを作成しました。

pregum-fox.hatenablog.jp

今回は下記のMagic Linkのサンプルを作成します。

Login With Magic Link | Supabase Docs

他の認証サンプルを見たい場合は下記から確認できます。

pregum-fox.hatenablog.jp

それでは目次です。

ポイント

Magic Linkのポイントは以下の4点です。

  • アプリ内のsignInWithOtpの引数に設定するRedirect URLとサーバー側に設定するRedirect URLsを 完全に 一致させること
    • 末尾の/の有無だけでも処理が失敗する為、完全に一致させるようにコピー&ペーストで設定することをお勧めします。
  • マジックリンクでは新規ユーザーを作りたくない(サインインだけ通したい)場合は、signInWithOtpメソッドのshouldCreateUserfalse にすれば良い
    • メソッドのデフォルト値はtrue
  • 認証フローにPKCE(ピクシーと呼称)フローを使用する場合は、同じ送信元と同じブラウザからのみ開くことができる(PKCEの仕様)
    • 可能ならPKCEフローを選択する方がセキュリティ的には堅牢になる
    • 例)DesktopのChoromeから送られたマジックリンクは、モバイル端末から使用不可
    • 参考: Supabase Auth: SSO, Mobile, and Server-side support
  • 一般公開するアプリのDeep linkのURLにはhttpsschemeを使用する

完成版

完成版は下記tagのリビジョンから確認できます。

下記リビジョンを使用している想定で、以下説明していきます。

github.com

開発端末

項目 内容
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認証が有効になっていることを確認します。

【Supabase】Flutter + Supabase AuthでEmail + passowrd(確認メールありver)のサインアップ・サインイン処理のサンプルを作った(ローカル環境もあるよ)【Flutter】 - 狐好きぷろぐらまー

Redirect URLsとアプリ側のカスタムURLの設定の確認

それでは、マジックリンクのURLをクリックして、サンプルアプリへ自動的に遷移するようにします。

とはいえ、完成版ではすでに設定している為ここでは確認だけします。

sehemeとhostについては、下記ページなどで解説されていますので、ちょっと分からないよ、という方はご覧ください。

webtan.impress.co.jp

Android

Androidは、リポジトリ直下のディレクトリからandroid/app/src/main/AndroidManifest.xml に記載しています。

こちらのintent-filter > data タグ にscheme(https:io.supabase.flutterquickstart:)とhost(login-callbackcallback) が記載されています。

カスタムURLの設定箇所(Android)

iOS

iOSは、リポジトリ直下のディレクトリからios/Runner/Info.plist に記載されています。

ちなみにDeep Linkに独自機能を盛り込んだものにiOSはUniversal Links、AndroidはApp Linksという機能がありますが、細かい違いとしては下記機能が含まれています。

  • ブラウザで特定のドメインのサイトを開いた時、自動的にアプリへ遷移させる機能も含まれています。

違いについて説明されているサイトがありましたのでこちらに記載します。

ディープリンク、ユニバーサルリンク、アプリリンクとかの話 | am10ぶろぐ

Deep Linkの設定箇所(ios)

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も手順通りにいじる必要があります。

pregum-fox.hatenablog.jp

additional_redirect_urls の設定

Magic Linkではリダイレクト先のURLを設定する必要があります。

アプリのリポジトリ直下のsupabase/config.toml ファイルの [auth] の下にあるadditional_redirect_urls の値にコールバックのURLを設定してください。

配列ですので、複数設定することは可能です。

リダイレクト先のURLの設定確認

Inbucket上でメール確認

上記の設定ができましたら、環境変数のURLとanonkeyをローカル環境のURLとanonkeyを使用して、アプリを起動します。

その後Magic linkの場合は、iOSAndroid端末から開く必要がありますが、http://localhost:54324 のようにlocalhostでアクセスしようとすると、「見つかりません」のようなメッセージが表示される場合は、localhostの箇所をローカルサーバを立てているPCのプライベートIPアドレスに変更する必要があります。

調べ方はmaclinuxではターミナル上でifconfigと入力し、表示された文字列のen0の項目にIPv4の値がありますので、その値を入れれば良いです。

プライベートIPの確認方法

上記のプライベートIPアドレスの場合は、http://192.168.0.9:54324 というURLでInbucketにアクセスできます。

特にiOSの場合は確認メールをタップした後、リンク先のURLがlocalhostドメインになっている為、自分でプライベートIPアドレスに打ち直してアプリへリダイレクトするという力技で確認することになります...悲しい🫠

Androidの場合は、PC側でChromechrome://inspect/#devices のページ上でlocalhostのport forwarding を設定することで自分で打ち直さなくても自動的に遷移できるようになっていますので、リンク先にプライベートIPアドレスを入れられるまでは上記のような回避策で対応することになりそうです。

おそらく、self-hostingで使用するsupabaseのdockerイメージである下記リポジトリdocker-compose.yml.env.exampleをいじれば良さそうなのですが、知識不足で他にも調べたいことがあったので、一旦調査はやめました。

github.com

ただ、上記はローカル環境でのみの話で、通常本番環境などで使用する場合は関係ない話なので一般ユーザーへ公開する場合は問題なくリダイレクトしてくれます。

まとめ

Flutter + SupabaseでのMagic Linkでのサインイン・サインアップの手順は以下の通りです。

  1. Supabaseプロジェクトの作成
  2. API Keyの取得・設定
  3. メール認証のプロバイダの有効化
  4. 対象のSupabaseプロジェクトのRedirect URLsの設定
  5. アプリ側でRedirect URLsで設定したURLでの遷移用にカスタムURLを設定
  6. 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についてあまり理解できていなかったので、記事を書いていく上で調べて違いについてはっきりわかるようになったのはよかったです。

ここまで読んでいただきありがとうございます。

参考URL