Closed5

keycloakについてまとめる : 認証認可

ebi_yuebi_yu

Keycloakとは

  • ユーザやサーバリソースの認証/認可/管理の機能を提供するOSSソフトウェア。
  • 2023/4にCloud Native Computing Foundation(CNCF)のプロジェクトに追加され、OSSの定番になることが期待されている。

https://www.hitachi.co.jp/products/it/oss/efforts/keycloak/index.html

提供機能

  • ユーザー認証
    ユーザーが本人であることを確認する。
  • ユーザー認可
    ユーザが特定のリソースにアクセスできる権限を与える。
  • シングルサインオン(SSO)
    一度のログインで複数の関連サービスにアクセスを許可する。
  • ユーザーフェデレーション
    異なるデータソースからのユーザー情報を統合します。
  • ソーシャルログイン
    外部サービス(Google/FaceBookなど)を使用したログインをサポートします。

https://www.keycloak.org/documentation

用語解説

  • Identity
    特定のユーザーやリソースを識別する一意な情報(ユーザの身元情報)。
  • ユーザーフェデレーション
    複数の外部データベースのユーザー情報をKeycloakにおいて統合し一元的なユーザー管理を可能にする。
  • SSO
    ユーザーが一度の認証で複数の関連サービスに認証済みとしてアクセスできるようにする仕組み。
  • Idp(Identity Provider )
    ユーザーのIdentityを管理し、認証サービスを提供するシステム。
  • sp(Service Provider)
    ユーザーがIdp経由でアクセスしようとしているサービスやアプリケーション。
  • AD連携
    Windowsで提供しているユーザーアカウントや端末情報を管理する機能(Active Directory)とユーザ情報を連携すること。
ebi_yuebi_yu

Keycloakの認可方式

OAuth(OAuth2.0)

  • 認可のための手順を定めたプロトコル。
  • 認可の過程でアクセストークンを発行する。

アクセストークンとは

  • 特定のユーザがどのリソースにアクセスする権限をもっているかの情報を含むトークン。
  • JSON Web Tokenと呼ばれる、JSONデータを暗号化した形式で発行される。
  • アクセストークンには有効期限が存在し、認可サーバ(keycloak)上で設定できる。

アクセストークン発行プロセス

  1. ユーザがクライアントアプリにアクセスする
  2. クライアントアプリはユーザをKeycloakにリダイレクトさせる
  3. ユーザはKeycloak上でユーザID/PWを使ってログインをする。
  4. アクセストークンが発行され、クライアントアプリに渡させる。
  5. アクセストークンを使ってクライアントアプリはリソースサーバ(API/DB)にアクセスする。
  6. ユーザがアクセス権限を持たないリソースにはアクセストークンを使ってもアクセスできない。

https://www.redhat.com/architect/oauth-20-authentication-keycloak

アクセストークン検証プロセス

アクセストークンの検証は、リソースサーバ(APIやDB)が有効であることを確認するプロセスです。

  • 署名の検証
    アクセストークンはJSON Web Token(JWT)形式で、デジタル署名が付いています。
    リソースサーバ(APIやDB)は公開鍵を使用してこの署名を検証し、トークンが信頼できる認証サーバ(Keycloak)によって発行されたものであることを確認します。
  • クレームの検証
    トークンには「クレーム」と呼ばれる一連の情報が含まれています。
    リソースサーバ(APIやDB)は、トークンの有効期限(exp)、発行者(iss)、対象者(aud)などのクレームを検証して、トークンが有効であることを確認します。

OAuthの注意点

  • OAuthで発行されるアクセストークンにはログインしたユーザの情報が限定的にしか含まれておらず、 誰に対して発行されたアクセストークンか確認できない。

具体的な問題になるケース : OAuthを認証で使った場合

(前提)

  1. サイトAにKeycloakでログインするとアクセストークンが発行される。
  2. サイトAはアクセストークンがサイトAのどのユーザと結びついてるのかわからない。(誰かがログインに成功したことはわかるが、誰がログインしたかわからない。)
  3. そのため、アクセストークンを使ってユーザ情報をサーバから取得する必要がある。

(本題)

  1. 悪意ユーザがサービスAにアクセス
  2. サービスAがKeycloakに悪意ユーザをリダイレクト
  3. 悪意ユーザがKeycloak上で自身のアカウントでログイン
  4. KeycloakがサービスAにアクセストークンを渡す。
  5. このタイミングで悪意ユーザが発行されたアクセストークンを、管理者ユーザのアクセストークンに置き換える。
  6. サービスAは管理者ユーザのアクセストークンに管理者ユーザのログイン情報をサーバから取得する。
  7. 悪意ユーザは管理者ユーザとしてログインされる。
ebi_yuebi_yu

Keycloakの認証方式

認証方式 : OIDC(OpenID Connect)

  • OAuth 2.0をベースにした認証プロトコル。
  • アクセストークンとIDトークンを発行する。
  • IDトークンにはユーザの識別情報が含まれている。

IDトークンとは

  • ログインしたユーザの識別情報を含む。
    • 誰が : ログインユーザ
    • いつ : ログイン日
    • どこで : Keycloakの識別情報
    • 誰に : Keycloakを介してログインしたいクライアントアプリ
    • どれぐらいのリソースに対して : アクセス対象となるユーザーの権限範囲
  • JSON Web Tokenと呼ばれる、JSONデータを暗号化した形式で発行される。
  • IDトークンにどのような情報を持たせるかはID プロバイダー(keycloak)で設定できる。

IDトークン発行プロセス

  • アクセストークン発行プロセスとほぼ一緒
  • Keycloakではアクセストークンを発行する際に、IDトークンも一緒に返ってくる。

IDトークンを使った認証プロセスによる不正アクセス防止

(前提)

  1. ユーザがサイトAにKeycloakでログインするとアクセストークンとIDトークンが発行される。
  2. サイトAはアクセストークンがサイトAのどのユーザと結びついてるのかをIDトークンをもって確認する。

(本題)

  1. 悪意ユーザがサービスAにアクセス
  2. サービスAがKeycloakに悪意ユーザをリダイレクト
  3. 悪意ユーザがKeycloak上で自身のアカウントでログイン
  4. KeycloakがサービスAにアクセストークンとIDトークンを渡す。
  5. このタイミングで悪意ユーザが発行されたアクセストークンを、管理者ユーザのアクセストークンに置き換える。
  6. サービスAはIDトークンをもってユーザを確認するので、悪意ユーザは悪意ユーザのユーザ情報でログインされる。
  7. またIDトークンにはいつどこで発行されたのかがのっているので、IDトークンを置き換えたとしてもサービスAハそれを検知できる。

IDトークンとSSO

  1. ユーザがサイトAにKeycloakでログイン済みだとする
  2. ユーザがサイトBにアクセスし、Keycloakにリダイレクトされる
  3. Keycloakはブラウザのセッションをみて、ユーザがKeycloakにログイン済みだということを確認する
  4. ユーザはログインすることなく、サイトBに返される
  5. サイトBにはKeycloakからアクセストークンとIDトークンが渡される。
  6. IDトークンによってログインユーザを確認する。
ebi_yuebi_yu

実践してみる

  • KeycloakとKeycloakを介してログインしたいクライアントアプリをローカルに立てる。
  • Keycloakは公式のDockerイメージを使う
  • ログイン用のアプリは Next.js + NextAuth.js を使う。

https://github.com/ebi-yu/playground/tree/main/packages/keycloak

1. Keycloakでクライアントアプリ用の情報を登録する。

2. クライアントアプリ(nextauth-example)の設定

NEXTAUTH_URL : http://localhost:3000
KEYCLOAK_ID : test-client
KEYCLOAK_SECRET : Client設定のCredentialsのClient Secret
KEYCLOAK_ISSUER : http://localhost:8080/realms/develop

3. ログインしてみる。

4. アクセストークン/IDトークンの中身

https://jwt.io/

  • なんかアクセストークンにもユーザ判別情報が含まれている?
  • → クライアントスコープでどの情報をトークンに含めるか設定できるらしい
  • → そもそもアクセストークンはクライアントアプリ側で検査されるべきではないらしい(後述)

アクセス トークン側では、リソースへのアクセス (API の呼び出しなど) が許可されていることを示すために考えられました。
クライアント アプリケーションは、この理由のためにのみこれを使用する必要があります。言い換えれば、アクセス トークンはクライアント アプリケーションによって検査されるべきではありません。これはリソース サーバーを対象としており、クライアント アプリケーションはアクセス トークンを不透明な文字列、つまり特定の意味を持たない文字列として扱う必要があります。アクセス トークンの形式を知っている場合でも、クライアント アプリケーションでその内容を解釈しようとしないでください。前述したように、アクセス トークンの形式は認可サーバーとリソース サーバーの間の合意であり、クライアント アプリケーションが侵入すべきではありません。ある日、アクセス トークンの形式が変更された場合に何が起こるかを考えてみましょう。クライアント コードがそのアクセス トークンを検査していた場合、予期せず壊れてしまいます。

https://auth0.com/blog/id-token-access-token-what-is-the-difference/

アクセストークン

IDトークン

ebi_yuebi_yu

リフレッシュトークン

  • アクセストークンの有効期限が切れた後でも、ユーザーを再認証することなく新しいアクセストークンを取得できるようにするためのトークン
  • OIDC認証時にIDトークン/アクセストークンとともに返される

なぜ必要か

  • アクセストークンの有効期限を長くすれば、必要ないのではないか
    • → アクセストークンはり万が一トークンが漏洩した場合に備えて、有効期限は短く設定するべき
    • → リフレッシュトークンの有効期限は少し長めに設定する。

オフライントークン

  • ユーザーがオフラインの状態でもアプリケーションがユーザーの代わりにリソースサーバーにアクセスできるようにするための特別な種類のリフレッシトークン
  • 主に、ユーザーが直接アクティブに操作していないときや、アプリケーションがバックグラウンドで動作しているときにリソースへのアクセスを継続的に保証するために使用される。
  • オフライントークンは不正アクセスやトークンの漏洩があると、攻撃者が長期間にわたってユーザーのリソースにアクセスできる可能性がある。そのため、アクセスできるリソースのスコープは制限しておく必要がある。
このスクラップは2ヶ月前にクローズされました