はじめに
OpenID ConnectとKeycloakの勉強をかねて、今回は「OAuth2 Proxy」+「Keycloak」を構築してみました。
全く知識がないのでお試し程度に考えていただければと思います。
構成
今回は、oauth2-proxyに渡ってきたhttpリクエストに認証情報がなかった際に、Keycloakを利用して認証、何かしらのウェブページを表示させることを目標にします。
構成の中のanyには実際に認証したいコンテンツを設置します。
今回はこちらを利用し、リクエストを可視化できるようにしておきます。
作成したdocker-compose
今回作成したdokcer-composeは以下の通りです。
oauth2-proxyの環境変数にあるXXXXXXXXXXXXXXXXXXX
については、Keycloakを設定後に取得できる内容となっているので、
ここについては一旦上記の形で書いてあります。
また、keycloakのデータや設定値の永続化は設定しておらず、設定用コンテナを起動し、設定値をexport、コンテナ起動時に自動的にimportさせるようにもできますが、今回は認証を動かすことを目的にしているため、そのような形の構成にはしていません。
version: '3.9'
services:
keycloak:
image: quay.io/keycloak/keycloak:20.0.1
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: Pa55w0rd
PROXY_ADDRESS_FORWARDING: "true"
ports:
- 8080:8080
- 8443:8443
entrypoint: ["/opt/keycloak/bin/kc.sh", "start-dev"]
any:
image: kennethreitz/httpbin:latest
ports:
- "3000:80"
oauth2-proxy:
image: quay.io/oauth2-proxy/oauth2-proxy:v7.4.0-amd64
ports:
- 80:4180
environment:
OAUTH2_PROXY_PROVIDER: oidc
OAUTH2_PROXY_CLIENT_ID: oauth2-proxy
OAUTH2_PROXY_CLIENT_SECRET: XXXXXXXXXXXXXXXXXXX
OAUTH2_PROXY_REDIRECT_URL: http://localhost/oauth2/callback
OAUTH2_PROXY_OIDC_ISSUER_URL: http://keycloak:8080/realms/DemoRealm
OAUTH2_PROXY_COOKIE_SECRET: "01234567890123456789012345678901"
OAUTH2_PROXY_COOKIE_SECURE: "false"
OAUTH2_PROXY_COOKIE_NAME: "demo_cookie"
OAUTH2_PROXY_EMAIL_DOMAINS: "*"
OAUTH2_PROXY_HTTP_ADDRESS: 0.0.0.0:4180
OAUTH2_PROXY_UPSTREAMS: http://any/
OAUTH2_PROXY_PASS_AUTHORIZATION_HEADER: "true"
また、Dockerネットワークの名前解決を利用していますが、うまくいかなかったため、/etc/hosts
を設定しています。
127.0.0.1 localhost keycloak
準備
認証ができているか確認するためには、Keycloakの設定を先に行っておく必要があります。
そのため、keycloakのみを起動し、設定を行います。
docker-compose up -d keycloak
1.Realmを作成する
起動ができたら、http://localhost:8080/
のkeycloakにアクセスします。
Administration Console
からログインを行います。
今回は環境変数で下記の通り指定していますので、こちらがadmin ユーザーのIDとパスワードになります。
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: Pa55w0rd
ログインができたら、realmを作成する作業になります。
Create Realm
からrealmを作成していきます。
Realm nameにはDemoRealm
と入力してCreate
を押します。
これでRealmが作成することができました。
2.Client IDとClient Secretを設定、確認する
次にoidc周りの設定(Client ID
Client Secret
の発行)を行っていきます。
まず、Clients
にあるCreate client
からClientを作成します。
Client ID
にoauth2-proxy
と入力し、Next
を押します。
これが、Client IDとなります。
Client authentication
にチェックを入れ、Save
を押します。
そうすると、Client secret
が確認できるようになりますので、Credentials
タブのClient secret
を確認します。
ここの値をdocker-compose.yml
のOAUTH2_PROXY_CLIENT_SECRET
に入力します。
3.Valid redirect URIs を設定する
Clients
のSettings
にあるValid redirect URIs
を設定します。
http://localhost/*
4.ログインを行うテストアカウントを作成する
ログインを行うテストアカウントを作成します。
Users
のCreate new user
からアカウントを作成します。
必要事項を入力し、Create
を押します。
Email verified
はOn
にしておきます。
テストアカウントのパスワードを設定します。
Credentials
のSet password
からパスワードを設定します。
パスワードを設定します。
今回はpassword
とし、Temporary
はOffにします。
これで、準備は完了です。
動作確認
Keycloak以外を起動し、動作の確認を行います。
docker-compose up -d any oauth2-proxy
起動ができたら、http://localhost/
にアクセスします。
Sign in with OpenID Connect
を押してログインを行います
http://localhost/bearer
にアクセスしてみます。
{
"authenticated": true,
"token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJoQTNFY2Q0aFRJQVMwOHRNUng4dnJCZnBHSmppcHd0VFZNSDRnWTV0a09NIn0.eyJleHAiOjE2NzAzMjcxMDcsImlhdCI6MTY3MDMyNjgwNywiYXV0aF90aW1lIjoxNjcwMzI2NjE4LCJqdGkiOiJkZjEzYmQ4OS03MjA4LTQwYTEtYWU0Yi1lN2YwMmUyZWNlZWIiLCJpc3MiOiJodHRwOi8va2V5Y2xvYWs6ODA4MC9yZWFsbXMvRGVtb1JlYWxtIiwiYXVkIjoib2F1dGgyLXByb3h5Iiwic3ViIjoiNzk0YzMxZGYtZTI1MC00NmQ4LWE2OTUtZWJkNGZlNDJiYTNiIiwidHlwIjoiSUQiLCJhenAiOiJvYXV0aDItcHJveHkiLCJzZXNzaW9uX3N0YXRlIjoiY2M4OWM5NTYtMzdiZS00MTBlLTgzNGEtYjExYmY1YjgxMGI0IiwiYXRfaGFzaCI6InpKOWs3X01XMXRQUmlBR0ZGWjc0TkEiLCJhY3IiOiIwIiwic2lkIjoiY2M4OWM5NTYtMzdiZS00MTBlLTgzNGEtYjExYmY1YjgxMGI0IiwiZW1haWxfdmVyaWZpZWQiOnRydWUsInByZWZlcnJlZF91c2VybmFtZSI6IuOBpuOBmeOBqOOChuODvOOBluODvCIsImdpdmVuX25hbWUiOiIiLCJmYW1pbHlfbmFtZSI6IiIsImVtYWlsIjoidGVzdEB0ZXN0LmFhYSJ9.AvRU4LPjTqYqmXVSeHAmkruNemKJHNtYrmF8tEzh6XLHt-NOKK2ezy9GgoJSN-UKEqKXXu1kYgo2D5PtZG4l31Uio0i-pCo227iXcEUelp6aZevL5YFVnvN7iEvZ1pC5F3jtDhmrgbQ1j01Pxept_OKWYaGKQKsA-DDCgj4ryrxW3cS6qkYuxfg360_NpH-h2ieIp60lFB_GcaVrmynDJ1ZRCh-S3EayWD7e8D14aAWS8Dj_9XvtVJ48tAyRRJ7-SJjEtkhmZcyA7ATWYOlLOezWSEN0LYZmfgKwATfBUy04fN02nOR2s3Gu9UHnANsThXDWcD9zzT5_Is0Er5qIIA"
}
jwtのデコードをしてみます。
{
"exp": 1670327107,
"iat": 1670326807,
"auth_time": 1670326618,
"jti": "df13bd89-7208-40a1-ae4b-e7f02e2eceeb",
"iss": "http://keycloak:8080/realms/DemoRealm",
"aud": "oauth2-proxy",
"sub": "794c31df-e250-46d8-a695-ebd4fe42ba3b",
"typ": "ID",
"azp": "oauth2-proxy",
"session_state": "cc89c956-37be-410e-834a-b11bf5b810b4",
"at_hash": "zJ9k7_MW1tPRiAGFFZ74NA",
"acr": "0",
"sid": "cc89c956-37be-410e-834a-b11bf5b810b4",
"email_verified": true,
"preferred_username": "てすとゆーざー",
"given_name": "",
"family_name": "",
"email": "test@test.aaa"
}
正しく発行されているようです。
http://localhost/cookies
にもアクセスしてみます。
{
"cookies": {
"demo_cookie": "xDN81GmyNvGWXI4-h0qSh6BVqdehbnhoejp5_DY0hlJW6m3-GzN_3gr_OVNboHtHDa05-AZrqXlUPnbAWsho24Hu5Ov6T-oMdTjGUTfjsldKRemfRPeViB95rfrUqtRzu-03joF7X1DSbayJ8nxdKMrwDcwvLpfCkWkQss1PYtY-Q09GW9dXTdxuO9GhhMPZqkvK3C2bZOgotrL8scvEe4ei_VHkXZ7nZThPC1b_J685JS3GwVi_u9eZ58rPx_FdZcs4oWxxh83NfDDMmgNzyUk2k1TK3NuCx7wQw32anzY9XmspKIEjWsy2PJXF9-zx1UVVoPunuPkDU2H9E8WHYSEJFVXOcHblLtYn7ocgoSk3ud_2s1ygSTUplLYEG1-RmlZoL8__WjH7xNPD3UUXDrBNv02_G6D-LsBnM1aXQ6SCFpGGgAg3bST88p_nBn6VR2iu7SrSJUYkv4eH_0_y_42-sfHM9cyxmaKupI1LWA5HXl3NrdyDMV7K13_XCq2L3IOALiUQro0AAsAtu8z_OucxWRp_ctvQFuLdnL50GgIl3M05a2FDV7vxVP7HbYiEXp_ZXF9XlxzjbAx-Xe04l3SCOFWGukpaxHBKeLx3xDBuwprRrqEpsfdE8o9zLGs2vfVSjsoydDaC1pFOwR205WonMv8u0wRXu3Fs_wFPuYt_2y31dHjOvULHkV0vKtZ90bzDKmNhORByJfvLJohDruZtd0KNUUXkuam4EpIIEr04FjDobR786nsIvuEahF-JQmVRV_1j5K3Aa7AKF5-RiwMqCAHsLpe-a7uvg18qf9AZBgLkkZPFfv3U8jOV_m3ibM1oJ4mqOAgv3hgurVb0lGpJegr3UxsgOwyw57DXbRNpYwa9PmtC2rGahIAFXaG7_KO8eGcrdM204SmXQ3gMuE7VszGVcL7msljP37N1ThwLlciQhZM2gaQDxWf52QPtCfuZ8-Ez4LVCw4tk5_8hkwyfq3NxNMcmZiylIRoO2jzD-iyiWfoQ5mldBwIhtge8k65nReDsU94zm223MH1cA_xglWGI8mWQd3iMvGmkStpvdSAZx2d88YiUQXJW_gV0vADWzYNv7XWsV1T5F4rn6eeqDKqt__8s5v1w7O7N88R28cFOk4qqJMq2Vz8UncuB0M7M5gjt5dos9DULayu_ij4HqTNqaCGIa2S-wrUfBmyZpljp7xrSMzK96dbFHy3RO9X5t2AjcaWXnXaraFBob7ttgHwUUiJjoDRe41o5m4JGh1OkjjaJnahUP4_LGdbsRmbcWtY6WSt8-1dhHSnw7wUShxLEf9hZksFpV4So62hLCBAbbammaMDn4wpZY6h8g4Ks7CJ5KXxtFP-pQ7SlIn_ZtUNOmYZUxckAr2fkjwPl4vNgjWsokUA57VnTfsYlqA2svB1IYn4fPQUvU0pOgiDL1Sm-xb71N7acY4ZER_ApxYxiQQthwS5JYLjoBXI3b3bJ8ACa1YicIxXRdcR9gLVf8nQ6g2Yo66LFFUHbAsQ8xev924uoD67rz67Fs-NQ53MneI0U1hFXFWO_9MTq7aNHTKCYeHhqdMYjGnis9B49G-rmHglTeBWEAFszMwW32bHvoK-lLg9jL2KvEXhEePV6KQZqsqOxxClHdjygpSlRWo7o8fRSs7dllRR016GnYNftVJ3T29dD6EjyFuKvT0Xfwt5R-bvzzIL8XH6bYFkmysg41a5wxQKHkS3uWlvhc126W5Z-XLnhLxDre_k0honG7dtAVaavx7DAJTVsmbJo2Xarv800NJO4OCkFjnnHLvenImKzmdqz4MpZeVs-kaQVT0sQB5SpuTqiAQHz_of3HZ0xIMSBUciLdZp0jQqChPPDRld0m9LHXylruVj9JS9FcETzI7WW4gKY0Wv1UhowMvboL2XJDvNCkCoVzWUO3kgOE2wVmaC4Z1TfehqOoYh8AJL-pEpSWOCzt8p8T35fXtEfWzajq9kiYG6ayjnyoDjYyHKAvEqyHWHy0h3WUWiwYCAEIF-UjEPI8SvrhuJUkDgAltmLTRs8dNsdWl7PKT_P7EhwyU7Sn-ZiJJpQk6qfd6tCgK3C24JLs6WqTlTNpBUxSV3EHDwAhLrzUegjzQJBxJ6kfsw3a0T-MMWM2Q-58h1JWRtcINLelJn9OjKb2T50WrKl_JttvBIn51yK6fCcQdOW91Dc4jLVj_7_WXKA9wAYaan0D2C3P5YXaagJIJlfWv6ZuYYInDyby79aN-XxUQKar1DYJdu0H-RaUkg-eWXqdEJJYo6GFYE8yIzs1-tTZdR6Dx-U49p_mM0R7W1OuRFui9wPGhn_lMSrTizDoFmlK-NVfGsUj2RMl36kJf1O8V7Ex0tz2goS-ZcJ3-yj8dKHebVImrjiXmHKH1v5Z43gmplEvJhke7I5GivaiDVUSUDJlWmggGuac5-FXGqobqJ5Sa10lZF7xK21aYN-2WGRINJqREOaCawYIDuOgc213kbu7LVuV91AwWHd2n2Wq7xp2-fAdNTUCH7lSriCEBrEhq0cMchWGWyKEn7hQtEYa88rYqKS_KkIvfMRxZUgzySH38Htjib4XijkcpygwQfStUzP6LTyR3h7Dysx721XcQiWajIVMnygtLtf6vwrD_Rh3LrrbkbUuzDXrT_cj52ITa1mYOVXciMK7L7s-CROQF1_KgOg6k4kj67u7s2stVIgMHnybsyDw03_AotBfZSan5ELLtINYNKgWiXxw1B7mZu_gDp7SEMVt7Y0ThqDTUUHqqJcwIx0MSRHZqoiR6iXQLH9OVIuWCuR4f5hlhROPDJjF86uQTva9pzawuI7tUUGvEsV8zfXnYM3oE8VipvrDdY6VI5u1-sKGOzNDte5tIpGztwR4QXw4W4J3J9CSdqd_qdf2ZRHm06u0ixY4bapJLd6A1wnfC3ikQpbEo3cd9CJrcvQ8xK0exBMlhIXq9MRvF0yo3jz4viQXplOCpwwOqmadAbtynoMUSw-8z5bEO_SEOLvir_p49CcGOm9dY674Uz2Ors9iowB_FuTUznejLxMhe11kLfWEYLBVLSXKYGi7EOpLjg1vqUBpPisdT0S_hQX09OEQEamzOPZwM_1qzpLhwik6Aag99sP32Pz1cqfScqPww2pJgM9Z0PmoWukq0kGaYbk4k3kX7Qg9_UK1DOWvUq-xKLUCw_3mRfUus07nUVfAA6LP2SjhxlAxWfEwV5HWnBTDp8wiVpQ2vIlsCZuxAtTiJxgDBO2wBh8pglTz3F4eHmDnT20hevhxEgbg-qh2faq-hVWbdrRSjLESAshAbNkEGV6W0b6iAfrXnO7AZyTQFLE3kzM-sj0355SJRJPjcUazmofjWfeUiDCSmMpViN0iZOXmc8pZe0odXnul7Bf09OsFm5kNZ1G_PJgOZExtpCk05incuX7c2DTNIOTn1BBI7Xw6p8Syo_iZF997850Czt8smB8sXzW5hiJwfvheJeyfJbuYpqq_u6txbjs6DVQ2irQAo6OmOYxJnx5wHU2vwtb5QLtxXjlMLw7X_DXvMmAkKXInsrCKQHXMMEV-ed1rAE5wd1YRZLGj5lmV1RUbNqUcHYXE3D5LV-eAFhZvaGWrz8GsSFPHwtMxHjNb74zuHXgLWE5hDcS4UW4jt3MsDYNFljybe2zsPrrO3uewM7PEsZs|1670326807|K9mF97EVHUEyWCNwStiX9rSmH4tN-_RXYsXAOx9u33M="
}
}
設定したOAUTH2_PROXY_COOKIE_NAME: "demo_cookie"
で発行されてることがわかりました。
感想
簡単に認証に触れることができて、とても勉強になりました。
また、控えているコンテナに対して手を加えず、認証・認可が行えるため、簡易的ではありますが、いろいろな場面で使用できると感じました。
参考
https://redj.hatenablog.com/entry/2022/03/19/231840
https://qiita.com/inajob/items/7099e539078c38c60844
https://qiita.com/tosier/items/c6f64811fde067bfd3c3