作成日:2024年2月1日
過去に私が参画したプロジェクトでSSOを使用したログインの実装をすることがありましたが、
OpenIDConnectを使ったSSOについてのイメージやフローについてなんとなくの理解で実装に入ってしまい、
思わぬ不具合や手戻りが発生することがありました。
OpenIDConnectを使ったSSOクライアントを実装する上で、今後同じ過ちが起きないようにするための備忘録を残しておこうと思います。
そもそもSSOとは何かについて軽く触れておきます。
SSO(Single Sign-On)は、ユーザーが複数の関連するシステムやサービスに対して、1度の認証操作でアクセスできる仕組みです。
1つの認証情報(ユーザー名とパスワード、または他の認証手段)を使用して、複数のシステムにログインできるようになります。
SSOを導入することで、ユーザーは複数のアカウントを持つ必要がなくなり、ログインの手間が省けます。また、管理者側もユーザーの認証情報を1箇所で管理することができ、セキュリティを向上させることができます。
InstagramにGoogleでログインできたりするのをイメージしてもらうとわかりやすいです。
SSO認証を利用する側のアプリケーションを「サービスプロバイダ」「SSOクライアント」といい、
ユーザー認証を提供するサーバー側を「IDp(IDプロバイダー)」と言ったりします。
OpenID Connect は OAuth 2.0 認可プロセスを拡張し, 認証目的で利用できるようにする. 本拡張を利用する場合, Client は openid
scope を指定して Authorization Request を送信する. 認証結果は ID Token (Section 2
参照) と呼ばれる JSON Web Token (JWT)
[JWT] として返される. OpenID Connect をサポートする OAuth 2.0 Authentication Server は, OpenID Provider (OP) とも呼ばれる. OpenID Connect を利用する OAuth 2.0 Client は Relying Party (RP) とも呼ばれる.
(OpenID Connect Core 1.0 incorporating errata set 1より引用)
OpenID Connect(OpenIDConnect、OIDC)は、先ほど説明したSSOログインの認証プロトコルの一種です。
OAuth 2.0プロトコルをベースにしていますが、認証に特化しており、認証と認可の両方をサポートしています。
具体的には、OpenID Connectでは以下のような流れで認証が行われます。
SSO全般の部分とOpenIDConnectについて勘違いしがちなことをまとめます。
SSOを導入すると、1つの認証情報で複数のサービスにアクセスできるため、セキュリティ上の懸念があると考える人もいます。
しかし、適切に実装されたSSOはむしろセキュリティを強化することができます。
例えば、たいていのSSO認証プロバイダーは多要素認証に対応しており、WAFのチューニングも適切に行われています。
その認証方式を丸々利用できると考えると、通常のパスワードIDのログインよりセキュリティリスクの軽減が見込まれます。
SSOはセキュリティのリスクが、、という不安で敬遠する方は、逆にSSOを使わなかった場合の認証方式のセキュリティリスクについても考えてみたほうが良いと思います。
※かといってSSOのデメリットの一つとして、認証情報が洩れるだけですべてのアプリケーションにアクセス可能になる等といった問題もあります。ここではメリデリを考えて導入を決定するべきということを主張しています。
意外と勘違いしていた人が多い印象だったのが、ログイン後のサービスプロバイダの認証方法。
下図はOAuth+OpenIDConnectを使用したSSOのフローです。
この図自体はググってもよく出てくるありきたりなフロー図ですが、皆さん勘違いしているのはログインしたその後。
アクセストークンを利用したリソースの取得以外で、サービスプロバイダはIDpのAPIを叩きません。
OpenIDConnectは認証のプロトコルであり、認証後のセッション管理やアクセス制御とは無関係です。
当然、IDトークン取得後の認証はサービスプロバイダーにゆだねられており、
IDトークンをクライアントで保存してJWT認証するか、はたまたログインセッションを発行するかは実装者次第です。
ログアウト処理、ログアウト後のフローって結構後々になって考え出すこと多いですよね。
SSOログインを導入する場合は、ログアウトのフローについても必ず考慮する必要があります。
SSOを導入したアプリケーション開発では、ここら辺で多分揉めます(実体験)。
特に以下の点については要件定義時に必ず調査して方針を定めておくべきです。
勘違いというよりか、よく理解しないまま実装する人が多い印象です。
OAuthとOpenIDConnectの違いとしてよく「OAuthが認可のプロトコルであるのに対して、OpenIDは認証のプロトコルである」と説明されています。
OpenIDConnectは認証プロトコルであり、ユーザーが本人であることを証明するためのフローです。具体的には、OpenIDConnectを利用することによって得られるIDトークンにユーザーに関する基本的な情報が含まれており、その内容と署名によって改ざんを検知することにより認証を担保しています。
一方OAuthは認可プロトコルであり、ユーザーが本人であるかという確認(認証)ではなく、ユーザーが自分のリソースに対してアプリケーションのアクセスを許可するためのフローです。Oauthではリソースにアクセスするためのアクセストークンを取得できますが、アクセストークンはOpenIDConnectのIDトークンのように、取得したトークンの改ざんを検証することはできないので、そのアクセストークンがユーザー本人のものかという認証部分は担保できません。
アクセストークンは発行元が制御するサービスによって発行されるため、第三者がアクセストークンを入手した場合には、リソースに不正アクセスできる可能性があります。また、アクセストークンは有効期限があるため、認証情報として使用すると期限切れのアクセストークンが悪用される可能性もあります。
今回はOpenIDConnectを使ったSSOで勘違いしがちなことを実体験を元にまとめました。
認証認可、暗号化プロトコルは学べは学ぶほど面白くて夜も眠れなくなりますよね、今後もこういった知識系の記事もまとめていこうと思います!