これ
問題
ログアウトしてもログアウトしてない。
下の画像のようにAuth0はデフォルトでsessionを永続化するので、ログアウトしても再ログイン時にIDとパスワードの再入力が求められずいきなりログインできる。
携帯などの個々人保有端末なら問題ないが、公共のパソコンなどでログインしたりするとかなりマズい。
(パソコン1台で家族間で同じサイトにログインするとかもあるし)
ログアウトしてもログアウト出来てないから、別IDでログイン出来ないのはすごく非直感的動作。
解決
上の画像の設定をNon-Persistent Session
にすれば解決しそうだが、そうでもない。
Browser Limitations
In some cases, non-persistent sessions cannot be enforced by tenant settings. Examples include:
The user has a session restore setting on the browser enabled; restoring the session also restores the session cookie.
The user closes a tab but not the browser window; the session cookie is not cleared until the session ends based on Idle or Absolute Expiration.
要はブラウザーによりけりでこの動作は保証されない。
Auth0の中の人も
この設定があったとしてもOSXだとcommand + Qで確実にアプリケーションを落とさないとセッションが維持される
とも言ってる。
どうするのか?
auth0 api /v2/logout
を叩けと言ってる。
GET https://{yourDomain}/v2/logout?client_id={yourClientId}&returnTo=LOGOUT_URL
- client_id
- returnTo
これら2つの有無パターンがある。
- If the client_id parameter is included, the returnTo URL must be listed in the Allowed Logout URLs set at the application level (see Setting Allowed Logout URLs at the App Level).
- If the client_id parameter is NOT included, the returnTo URL must be listed in the Allowed Logout URLs set at the tenant level (see Setting Allowed Logout URLs at the Tenant Level).
- If the client_id parameter is included and the returnTo URL is NOT set, the server returns the user to the first Allowed Logout URLs set in the Dashboard (see Setting Allowed Logout URLs at the Tenant Level).
-
client_id
を含めるなら、returnTo
はテナント内のApp内のAllowed Logout URLs
で設定したURLしかだめ -
client_id
を含めないなら、returnTo
はテナントのSettings > Advanced
のAllowed Logout URLs
で設定したURLしかだめ -
client_id
があって、returnTo
が無いならテナント内のApp内のAllowed Logout URLs
で設定した最初のURLに飛ばす
client_id
をユーザー側(ブラウザ側)から見えるのはなんとなくモヤモヤするので、
GET https://{yourDomain}/v2/logout?returnTo=LOGOUT_URL
(client_id削除)
こう呼ぶとして、returnTo
はテナントのSettings > Advanced
のAllowed Logout URLs
で設定したURLにする。
NextAuth.jsからだとどうするか?
自分はNextAuth.js
からAuth0をProviderとして使っているので、更に問題が厄介で
// ログアウトしたら完全にログアウトするためにAuth0のlogoutAPIを叩く
signOut({
callbackUrl: "https://{yourDomain}/v2/logout?returnTo=LOGOUT_URL",
})
と単純にしても機能しない。
By default only URLs on the same URL as the site are allowed, you can use the redirect callback to customise that behaviour.
デフォルトだと、callbackUrlは同じサイト内のURLにしか飛ばさないよ。
なので、違うサイトのやつは無視してbaseUrl
(トップページ)へ飛ばされる。
callbacks: {
async redirect({ url, baseUrl }) {
// こういったものを追加する
if (url.includes("auth0.com/v2/logout")) {
return url
}
// https://next-auth.js.org/configuration/callbacks#redirect-callback
// のコピー
// Allows relative callback URLs
if (url.startsWith("/")) return `${baseUrl}${url}`
// Allows callback URLs on the same origin
else if (new URL(url).origin === baseUrl) return url
return baseUrl
},
}
ここまでするとやっと再ログイン時にID、パスワードを聞かれるようになる...
- サインアウトボタンを押す
- signOut()を呼ぶ
- callbackUrlへ行こうとする
- redirectでurlが処理される
- 自分が追加したコード部分
url.includes("auth0.com/v2/logout")
により直接urlへリダイレクト出来る - Auth0のログアウトAPIを叩く
- 完全にAuth0からログアウト出来る
- returnToへ移動する
まとめ(NextAuth.js + Auth0 provider)
- Non-Persistent Sessionにする必要は特にない
- テナントの
Settings > Advanced
のAllowed Logout URLs
を設定する(ログアウトして戻る場所) - Redirect callbackを書き換える
-
singOutのcallbackUrlを追加し、Auth0のLogout APIを叩くようにする
- returnToは2.で設定したもの