空谷に吼える

ブロックチェーン/DLTまわりのなにかしらを書いていく所存

Auth0のPasswordlessログインで"Something Went Wrong: The link must be opened on the same device and browser from which you submitted your email address."エラーが出たので対処した

とある技術書のチュートリアルをやっていたところAuth0を使っているところでエラーに遭遇し、Auth0サポートに問い合わせたところ一旦の解消方法を教えてもらいました。

エラーに遭遇した時点(2023/6/4)ではエラー内容でググってもぜんぜん情報がないな~と思ったら最近のアップデートでの仕様変更によって発生した事象らしく、今まさに同じエラーで困っているひとがいるかも知れないので、一部断片的、不確実かつ解決方法がいつまで有効なのかわからないところもあるんですがとりいそぎ書いておきます。

Auth0は今回が初の利用で、また、↓で書いていることくらいしか使っていないのでぜんぜんわかっておらず変なこと書いてるかもしれないんですがご容赦ください。

事象

Auth0の…/passowordless/startAPIを呼んでEメールでのMagic Link通知によるPasswordless認証を使ったところ、送られてきたMagic Linkを開くと以下の画面のエラーが発生しました。なお期待していた正常な振る舞いは、Passwordless認証が成功して認証をリクエストされたアプリの画面にリダイレクトされるという動きです。

Auth0が出しているエラーメッセージは、"Something Went Wrong: The link must be opened on the same device and browser from which you submitted your email address."とのことです(また、HTMLソースを見たところdata-event-id="passwordless-no-session"というエラーコードっぽいものもありました)。

エラーメッセージによれば「リンクはEメールアドレスを送ったのと同じデバイス、同じブラウザで開かないといけないよ」ということなんですが、自作のWebアプリの画面でEメールアドレスを入力したのと同じデバイス、同じブラウザでリンクを開いているんですよね。また、Eメールアドレスを入力したまさにそのタブのURL欄にリンクをペーストして移動しても同じエラーになりました。なんだなんだ。困っちゃうね。

なおPasswordless認証をリクエストしている箇所はこんな感じ↓です。

async function sendPasswordlessLink(email, state, redirectUri) {
    const res = await fetch(`https://${env.AUTH0_DOMAIN}/passwordless/start`, {
        method: "POST",
        headers: {
            'content-type': 'application/json'
        },
        body: JSON.stringify({
            client_id: env.AUTH0_CLIENT_ID,
            client_secret: env.AUTH0_CLIENT_SECRET,
            connection: 'email',
            email,
            send: 'link',
            authParams: {
                scope: 'openid profile email',
                state,
                response_type: 'code',
                redirect_uri: redirectUri
            }
        })
    });

なお、エラー発生を確認しているのは上記の通りEメール送信によるMagic Linkの通知の方法でですが、判明した原因からすると…/passowordless/startを呼んでいるのであればSMS送信やコード通知でも同じエラーになるのかもしれません。

原因

Auth0サポートに問い合わせてみたところ、最近のPasswordless認証のアップデート(セキュリティ強化)により、直接…/passowordless/startAPIを呼ぶフローがエラーになるようになったそうで、それに引っかかっているとのことでした。【→2023/6/9追記】当該アップデート以降に作成されたテナントのみに影響し、それ以前に作成済みだったテナントには影響しないとのことです。気になる方はテナント設定の確認のAPIを実行してみると、"allow_magiclink_verify_without_session": false|trueの設定も見えるかもしれません(古いテナントでは項目自体見えないかも)。

Auth0のアップデート履歴を見てみたところ、ちょっと該当しそうなアップデートが見つけられてないです。この点はサポートに聞いてみているので回答があれば追記します。【→2023/6/9追記】いまのところこの変更に関しての公開のドキュメントなどはないそうです。

また、直接APIを呼ぶやり方ではない、新しい仕様に則った正しいフローってどういうものなのかはぜんぜん把握できていません。この点も聞いてみているので回答があれば追記します。【→2023/6/9追記】Embedded LoginではなくCentralized Universal Loginを使いましょうとのことらしいです。

解決方法

サポートからは、Auth0のテナント設定を変更して、↑の直接API呼び出しのフローを許容する古い挙動に戻せば解決するよと回答がありました。試したところ実際にエラーが解消し、Passwordless認証でのログインができるようになったことを確認しています。

この設定変更はGUI(Auth0のDashboard)ではできないっぽく、Management APIでしかできなそうです。また、どうもドキュメントにも記載がなく、いわゆる隠しパラメータっぽいですね。セキュリティ強化のアップデートによりNGになったということは、直接API呼び出しのフローはセキュリティ的に懸念があるということなのかもしれません。

以下に設定変更のやり方を記載しています。ただし応急処置的なワークアラウンドっぽい&経緯的にいつまでも有効なものではないだろうという気がするので、商用のアプリなどで本格的にAuth0を使っている場合は別の方法を頼ったほうがいいと思われます。

なお、トライアルの無料ユーザーであるにも関わらず、Auth0のサポートはタイムリーで正確に対応してくれたのでとても好感を持っています。

設定変更のやり方

Management APIUpdate Tenant Settingsに以下のBodyでリクエストを行い設定変更を行えとのことでした。

{
    "universal_login": {
        "passwordless": {
            "allow_magiclink_verify_without_session": true
        }
    }
}

Management APIの利用にはManagement API Access Tokenによる認証が必要です。取得方法はこちらに記載があります。

わたしの場合は学習用サンプルアプリにAuth0を使っていたため、手っ取り早いTestingのやり方でトークンを取得しました。DashboardからApplications>APIs>Auth0 Management API>API Explorerタブからトークンを生成して取得できます。

そうしたらあとはUpdate Tenant SettingsのAPIにリクエストを送るだけです。わたしはPostmanでリクエストを送りましたが、cURLだとこんな感じのようです。

curl --location --request PATCH 'https://{Auth0ドメイン}/api/v2/tenants/settings' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {取得したManagement API Access Token} \
--data '{
    "universal_login": {
        "passwordless": {
            "allow_magiclink_verify_without_session": true
        }
    }
}'

レスポンスで更新後の設定が返ってくるので、allow~~がtrueになっていることが確認できればOKです。