認証方法、認証要素、ユーザー ID の保護、パスワードレス、シングルサインオンなど、ログインのステップを重視している事が多いと思います。ログアウトのステップについてはどうでしょうか?ログアウトの実装はとても簡単なので、あまり注意を払う必要はないと思われますか?
ログアウトの実装は一見簡単に見えますが、実際にはそこまで簡単ではないかもしれません。特に Auth0 powered by Okta を使用している時のように、ログインのステップに複数のシステムが関わる時は考慮すべきことがあります。
この記事では、ログアウトのタイプや考慮事項について高レベルの概要を紹介させて頂きます。ログアウトの実装の詳細については説明しませんが、一見単純に見える処理の背景にある複雑さを知って頂けると思います。
もしよければ、同じトピックについての動画もあります(動画は英語のみとなっています)。:
ログアウトについての QA
アラビアのことわざに「入る前に出ることを考えろ」というものがあります。これは、どのような環境であれ、入る前に出口をよく考えておくことの重要性を示唆しています。これはアプリケーションのログアウトにも当てはまると思います。アプリケーションから適切にログアウトする方法を理解することは、ログインすることと同じく重要です。
ログアウトの様々なタイプについて紹介する前に、アプリケーションのログアウトについてのニーズにどう対応するか理解するのに役立つと思われる質問をさせて頂きます。
ログインとログアウトはどのように関係しているでしょうか?
ログインは認証されたユーザが関連付けられたセッションの最初のステップで、ログアウトは最後のステップです。ログインの前やログアウトの後では、アプリケーション上の活動は認証されたユーザに紐づけられず、匿名や不明のユーザ (Unknown User / Anonymous User) として扱われます。
ですので、ログインからログアウトのステップまでの間、アプリケーションはログインしたユーザが誰であるかを知っていると言えます。
ユーザごとに認証済みセッションはいくつあるでしょうか?
Auth0 を使用している場合、ユーザが ユニバーサルログイン を使用してログインすると Auth0 は新しい認証済みセッションを作成します。同様に、アプリケーションは Auth0 からユーザの認証結果を受け取ると、別の新しい認証済みセッションを作成します。
1 つ目のセッションはユーザと Auth0 サーバ間のやりとりを追跡し、これを Auth0 セッション (下図 Auth0 session) と呼びます。2 つ目のセッションはユーザとアプリケーションのやりとりを追跡し、これを アプリケーションセッション (下図 Application session) と呼びます。以下の図は、Auth0 を利用する際のこれらの 2 つのセッションを示したものです。:
Auth0 を通じて、サードパーティのアイデンティティプロバイダ (IdP) でユーザーを認証することができます。例えば、Google、Facebook、X (旧 Twitter) などのソーシャルサービスでユーザを認証することができます。この場合、Auth0 セッションとアプリケーション セッションに加えて、サードパーティ IdP セッション (下図 3d party IdP session) という 3 つ目のセッションが作成されます。次の図はこの新しいシナリオを表しています。:
なぜログアウトする必要があるのでしょうか?
これは奇妙な質問のように思えるかもしれませんが、少し考えてみてください。アプリケーションからログアウトする目的は何でしょうか?ログアウトは基本的に認証されたセッションを終了させることを意味します。セッションに関連するすべての情報を破棄し、権限のない人が引き継ぐことができないようにしなければなりません。言い換えれば、これはセキュリティ対策です。ですが、後で紹介するように、ユーザエクスペリエンスにも影響を与えることを過小評価すべきではありません。
どこからログアウトしたいでしょうか?
これも最初は馬鹿げた質問のように思えるかもしれません。おそらく最も自然な答えは「アプリケーションからログアウトしたい」でしょう。しかし、これまでにご紹介したように複数の認証済みセッションが存在する場合があります。どのセッションを終了させる必要があるでしょうか?アプリケーションのセッションだけでしょうか?すべてのセッションでしょうか?
どんな選択肢があるか後ほど紹介します。
なぜこのような質問が必要なのでしょうか?
これまでの質問 (まだいくつかの質問には回答できていません) は、実際に利用される状況においてユーザをアプリケーションから適切にログアウトさせる方法を考える助けになると思います。ユーザーを適切にログアウトさせる方法を見つけるために、アプリケーションの構成を注意深く分析してください。これまでの質問を念頭に置いて、どのようなタイプのログアウトが利用可能か見てみましょう。
ログアウトのタイプ
アプリケーションにログインする方法が複数あるように、ログアウトする方法も複数あります。それらを見ていきましょう。
アプリケーションのログアウト
アプリケーションからログアウトするということは、アプリケーションのセッションを終了させるということです。どのようにアプリケーションのセッションを終了させるかは、アプリケーションの実装によります。例えば、あなたのアプリケーションが 一般的なウェブアプリケーション であれば、クッキーとサーバ側のセッションストレージを使ってセッションを実装しているのではないかと思います。この場合、ユーザのセッションを終了させるには、アプリケーションはクッキーを無効にし、セッションストレージから削除しなければなりません。アプリケーションがセッションを終了するように実装することは開発者の役割となります。
アプリケーションのセッションを終了させても、Auth0 のセッションは終了されません。Auth0 上のユーザのセッションはアクティブなままです。これは技術的には、Auth0 が発行した有効な認証クッキーをユーザのブラウザが保持したままということです。もし Auth0 セッションが有効な間に、ユーザがユニバーサルログインのページにアクセスしても、認証情報の入力は求められません。認証済みの状態であり、新しい ID トークンが発行されます。
次の図は、アプリケーションからログアウトした後のセッションの状態を表しています。:
このログアウトのタイプがアプリケーションに適しているかはご自身で判断頂く必要があります。ユースケースや提供したいユーザ体験を元に判断してください。
Auth0 のログアウト
ユーザがアプリケーションでログアウトした際に Auth0 のセッションがアクティブなままに残したくない場合、アプリケーションのセッションと Auth0 のセッションの両方を終了させる必要があります。
これまで説明してきた通り、アプリケーションがログアウト処理の実装するのは開発者の役割となります。ユーザの Auth0 セッションを終了させるには、アプリケーションが Auth0 ログアウト エンドポイント を呼び出す必要があります。こうすると、これ以降ユーザがユニバーサルログインのページにアクセスすると、認証情報の入力が求められます。
言い換えると、ユーザがアプリケーションのログアウトボタンをクリックすると、アプリケーションのセッションを終了させて、Auth0 ログアウト エンドポイントを呼び出すことになります。
現在、Auth0 は新しく提供を開始した OIDC ログアウト エンドポイント と従来から提供している Auth0 ログアウト エンドポイント の 2 種類のログアウト エンドポイントをサポートしています。
次の図は、アプリケーションと Auth0 からログアウトした後のセッションの状態を表しています。:
このログアウトタイプがニーズに適しているか確認してください。
フェデレーテッド ログアウト (Federated logout)
Auth0 を使用して Google などのサードパーティの ID プロバイダでユーザがログインできるようにすると、次の図のようなセッションが存在することになります。:
アプリケーションと Auth0 でログアウトを実施しても、IdP のセッションはアクティブなまま残ることになります。
セッションが残ることは問題ないと考えられるケースもあると思います。例えば、多くのユーザが ソーシャルログイン を使って複数のアプリケーションにアクセスしています。ユーザがアプリケーションにアクセスするのに Google を使用する際、既に Gmail やその他の Google を IdP として利用している他のアプリケーションも開いている可能性が高いです。その様な時にユーザがアプリケーションをログアウトしても、アプリケーションのセッションと Auth0 のセッションしか終了させなければ、Gmail や Google を通じてログインした他のアプリケーションを継続して利用できます。
しかしながら、このアプローチが適切ではないケースもあります。サードパーティの IdP がソーシャルプロバイダではなく、企業の IdP である場合を考えてみてください。ユーザーがアプリケーションからログアウトした際に、企業の IdP からもログアウトされることが望ましいとする企業もおられるかもしれません。フェデレーテッド ログアウト はこの要望を実現できます。この場合に、プリケーションからログアウトに関係するセッションは次の図のようになります。:
全てのサードパーティ IdP でフェデレーテッド ログアウトをサポートしているわけではありません。 どの IdP がサポートしているかは こちら を確認してください。
フェデレーテッド ログアウトはユーザ体験を悪化させる場合があります。アプリケーションでログアウト操作をした時に、アプリケーションと Auth0 からログアウトされることはユーザにとって予想される動作ですが、サードパーティの IdP からもログアウトされることはユーザにとって予想しない動作で、迷惑にさえなることもあります。アプリケーションにアクセスするために Google を使用しているユーザがアプリケーションからログアウトすると、Gmail にもアクセスできなくなることを想像してみましょう。ですので、サードパーティの IdP からもログアウトさせる場合は、ユーザが認識できるようにすべきです。例えば、サードパーティ IdP からログアウトする前に確認を求めるようにすることができます。あるいは、ログアウト時にサードパーティ IdP からもログアウトするかどうかユーザーが選択できるように実装することもできます。
グローバル ログアウト あるいは シングルログアウト
これまで紹介したログアウトのシナリオでは、アプリケーションが 1 つでユーザがそのアプリケーションからログアウトすることを想定していました。では同じ認証セッションに複数のアプリケーションが関与している場合はどうなるでしょうか?ユーザがアプリケーションではなくサードパーティの IdP からログアウトした場合はどうなるでしょうか? 望ましい動作は何でしょうか?
次の図は、このシナリオを表しています。:
この図では 2 つのアプリケーション(アプリケーション A とアプリケーション B)が同じ認証セッション(Auth0 セッションとサードパーティ IdP セッション)を共有している状況となっています。
このシナリオは、サードパーティの IdP がなくても同じような状況である。しかし、サードパーティの IdP が含まれることで、ユーザがアプリケーションではなくサードパーティの IdP からログアウトするケースも表しています。
前述のように、ユーザがアプリケーションの 1 つからログアウトしたり IdP からログアウトしたりした時に、どのようにしたいかはユースケースによって異なると思います。何も行わずに他のアプリケーションを使い続けられる様にしたい場合もあれば、ユースケースよっては他のアプリケーションのセッションを終了させたい場合もあると思います。
他のアプリケーションのセッションも終了させるログアウトは通常グローバルログアウト (Global Logout)、あるいは分散ログアウト (Distributed Logout) と呼ばれます。見方によっては、 シングルサインオン (Single Sign-On, SSO) と対になるものととらえることができます。このことから、特に SAML ではシングルログアウト (Single Logout, SLO) としても知られています。
基本的にはユーザが同じ認証セッションを共有するアプリケーションの 1 つからログアウトすると、ログアウト要求が他のアプリケーションに送信されます。これをどのように実現するかは、プロトコル(SAML、OIDC など)、最初のログアウトが行われる場所(アプリケーションの 1 つまたは IdP)、アプリケーションのタイプ(一般的な Web アプリケーション、SPA)によって方法が異なります。この記事では紹介しませんが、もし興味がある場合は以下のドキュメントをご覧ください。:
- OpenID Connect Session Management: ユーザの認証状況を積極的に確認してグローバルログアウトを実装する OIDC 仕様
- OpenID Connect Front-Channel Logout: アプリケーションにセッションを終了させるようにブラウザで通知してグローバルログアウトを実装する OIDC 仕様
- OpenID Connect Back-Channel Logout: アプリケーションにセッションを終了させるように IdP が通知してグローバルログアウトを実装する OIDC 仕様
- Best Practices for Application Session Management: 認証済みセッションを確認したり終了させたりするベストプラクティスについての Auth0 ブログ記事
もちろん、グローバルログアウトはフェデレーテッド ログアウトと同様にユーザ体験の問題を引き起こす可能性があるため、注意が必要です。
訳註: Auth0 は 2023年10月3日 より、OpenID Connect Back-Channel Logout をサポートしました。詳しくは ドキュメント をご覧ください。
ログアウトの後
複雑化するシナリオに対応するために、遭遇する可能性のある様々なタイプのログアウトを紹介してきました。最後に、ユーザがアプリケーションからログアウトした後はどうなるでしょうか? 認証されたセッションは終了するので、ユーザはアプリケーションの保護されたページにアクセスする権限がなくなります。ユーザはどこにリダイレクトされるのでしょうか?
これは主にどのようなユーザー体験にするかの選択です。ユーザーをアプリケーションのホームページ、特定のページ、または認証ページ(すなわちユニバーサルログインのページ)にリダイレクトすることができます。選択の際には考慮すべき点がいくつかあります。:
- Auth0 も含めてログアウトする(つまりアプリケーションだけのログアウトではない)場合は、ユーザをリダイレクトする先を指定する必要があります。指定方法は OIDC ログアウト エンドポイント または Auth0 ログアウト エンドポイント を確認してください。
- Auth0 のアプリケーション設定の Allowed Logout URLs に、ユーザをリダイレクトするページのURLを設定します。これは URL インジェクション攻撃を防ぐためのセキュリティ対策です。
- アプリケーションのログアウトのみを行う、あるいは、サードパーティの IdP を使った認証をユーザに提供するがフェデレーテッドログアウトは使用しない場合。ログアウト後にユーザを保護されていないページにリダイレクトするようにしてください。そうしなければ、残っている Auth0 または IdP のアクティブな認証セッションがユーザを再認証して、アプリケーショ ンの認証済みセッションが自動的に作成されます。こうなってしまうと、ユーザはアプリケーションからログアウトできなくなってしまいます。
まとめ
この記事ではログアウトに関連するいくつかの質問をさせて頂きました。これらの質問はログアウトの実装を選択する際の検討に役立つと思います。単純なアプリケーションのログアウトで十分なシナリオから始まり、複数のアプリケーショ ンがありグローバルログアウトが必要なシナリオを最後に紹介しました。
ログアウトの複雑さを理解していただけたと思います。最初は簡単に思えるかもしれませんが、複数のアプリケーションや複数の IdP が登場するシナリオでは、非常に難しくなります。この複雑さに対処する方法はユーザがアプリケーションからログアウトできなくする (参考: The impossibility of logging off 事ではないと思います。
ぜひ、Auth0 でユーザ体験も重視したログインの実装を試してみてください。
Auth0 を始める →(英語ブログからの翻訳: ソリューションエンジニア 辻 義一)
About the author
Andrea Chiarelli
Principal Developer Advocate
I have over 20 years of experience as a software engineer and technical author. Throughout my career, I've used several programming languages and technologies for the projects I was involved in, ranging from C# to JavaScript, ASP.NET to Node.js, Angular to React, SOAP to REST APIs, etc.
In the last few years, I've been focusing on simplifying the developer experience with Identity and related topics, especially in the .NET ecosystem.