Magic Link を実装するとわかる、ハマりやすいポイント
パスワードレス認証
あけましておめでとうございます。
今年こそは色々手を動かして学ぼうと考えている方も多いのではないでしょうか。
そんな方にぜひ一度触ってみてほしいのが 「パスワードレス認証の実装」 です。
いわゆる従来型の「ユーザー名」と「パスワード」を入力してのログインからの脱却ということで、最近は目にする機会も多くなりました。
ユーザー側にとっても覚える内容が減るのはいいことですし、提供社側にとっても管理すべき内容が減るのは喜ばしいことです。
実現のための方法としては
-
ワンタイムパスワードの発行
-
Magic Linkの送信
-
Passkey
などなど、様々な手段がありますが、今回はその中でも「Magic Link」を 実装してみる上でよくあるハマりポイントについてまとめていきます。
Magic Link の仕組み
Magic Link の動作手順としては下記の通りです。
-
ユーザーがメールアドレスを入力
-
メールにてログイン用のリンクを送付
-
ユーザーがそれをクリックするとログイン出来る
とてもシンプルですよね。
しかも、BaaSを使えば割と簡単に実装できます。たとえば、 Supabaseの場合、メールのテンプレートを下記のようにすればよいと 公式ドキュメントの「Passwordless email logins」 に記載があります。
<h2>Magic Link</h2> <p>Follow this link to login:</p> <p><a href="{{ .SiteURL }}/auth/confirm?token_hash={{ .TokenHash }}&type=magiclink">Log In</a></p>
要するに、一時パスワードの役割を果たすハッシュ化されたトークンをURLパラメータ ( token_hash
)にもたせて、
そのURLにアクセスされた場合には、URLパラメータをバラしてログインリクエストを送る…ということですね。
もちろん上記の例で言うところの /auth/confirm
にはログインの仕組みを実装する必要がありますが、それもかなりシンプルに出来るようになっています。
しかも、Supabaseの場合、まだ登録されていないユーザーの場合はユーザーを作成する機能までついていたりします。
まだ実装したことのない方も、シンプルでとても実装しやすそうという印象を持たれるのではないでしょうか。
Magic Link の罠
そんなMagic Linkですが、これが実際にやってみると気にしないといけないポイントがいくつかあります。
localhost での検証が通るがWEB上に展開すると動かない?
まず最初に躓く可能性が高いのはこれです。
ローカル環境でのログイン試行は通っているのに、WEB上に展開した瞬間にログインできない… 😩 というやつで、これを最初から回避できている方はなかなか強者だと思います。
このようなことが起こる原因ですが、 メールサーバ側での検閲などの際にURLを開いてしまっていて、すでにトークンが「使用済み」として無効化されていることが多いです。
localhost へのリンクであれば、当該端末以外でのプリフェッチは行えないので問題は起きなかった、というわけですね。
対策としては
-
User Agent等によるアクセス元ベースでの処理の仕分け
-
トークンを何度か使えるようにする(一度限りで無効化しない)
などが考えられますが、処理の仕分けはアクセス元環境によってはログインできない状況を引き起こしかねませんし、トークンの無効化を行わないのもセキュリティリスクが気になるところです。
「なんかログインできないんだけど」への対応
先述の通り、一回でも開いてしまうと無効化されるリンクとしている場合は、どうしても意図せぬ無効化を生みがちで、それがユーザーからの「なんかログインできないんだけど」に繋がります。。
たとえば、Safari等でリンクを長押ししてしまうとそれだけでプレビューウィンドウが開いてしまってトークンが使用済みになってしまったり…
他の例としては、In-App Browserで開いてしまって最初にログイン試行したブラウザ側にログイン情報が渡らないパターンも厄介だったりします。。
そもそもメールが到達しない
これもリスクとしてはあり得てしまいます。
メール自体を迷惑メールとみなされないように構成するのはもちろん、SPF, DKIM, DMARCといった送信者側の情報を正しく構成することも重要です。
と、こんな感じで、基本的にはめちゃくちゃ便利なのですが、Magic Linkのみでログインの仕組みを構築するとなかなか検証や対応に骨が折れることも多いように思います。
結局、ワンタイムパスワード(OTP)を送付して入力して貰う形式のほうが確実かつラクだと判断する方も多いのではないかという所感です。。
まとめ
今回はMagic Linkでのパスワード認証がシンプルそうに見えて懸念すべき内容もあるというところをまとめてみました。
個人的に利用しているサービスの中にも、URLが記載されているもののリンクにはなっておらず、「URLをコピーしてアドレスバーに入力してください」と記述した上でMagic Linkが送られてくるものがあるのですが、
アレは確実にユーザーが最初にそのURLをブラウザで開けるように…という配慮だったのか、とわかったり、やっぱり実際に実装してみると発見することは多いですね。
今年も色々手を動かして知見を得ていければと思います。