OAuth2 の認証を実装するときに、認証ロジックをアプリケーション自体に組み込んでしまうケースと、プロキシで認証してしまうケースがあります。私はこれまで組み込み型での実装を中心としていたのですが、認証機能を分離してしまいたいと考えた為、今回プロキシ型の認証へ取り組んでみました。
前提
- oidc
- docker-compose
- nginx
- oauth2-proxy
結果だけ欲しい方へ
以下ソースコードをクローン頂ければ
コード
traefik config
traefik.yml
entryPoints:
web:
address: ":80"
api:
insecure: true
dashboard: true
providers:
file:
filename: /etc/traefik/traefik-rule.yml
log:
level: INFO
traefik-ruke.yml
http:
routers:
express1:
rule: "Host(`localhost`)"
service: node
middlewares:
- oauth-auth
- autodetect
oauth:
rule: "Host(`localhost`) && PathPrefix(`/oauth2/`)"
middlewares:
- auth-headers
service: auth
services:
node:
loadBalancer:
passHostHeader: true
servers:
- url: "http://server:3001"
auth:
loadBalancer:
servers:
- url: http://auth:4180
middlewares:
autodetect:
contentType:
autoDetect: true
auth-headers:
headers:
stsSeconds: 315360000
browserXssFilter: true
contentTypeNosniff: true
forceSTSHeader: true
stsIncludeSubdomains: true
stsPreload: true
frameDeny: true
oauth-auth:
forwardAuth:
address: http://auth:4180/
trustForwardHeader: true
authResponseHeaders:
- X-Auth-Request-Access-Token
- Authorization
docker compose
docker-compose.yml
version: "3"
services:
proxy:
image: traefik
ports:
- "80:80"
- "8080:8080"
volumes:
- ./configs:/etc/traefik:ro
server:
build:
context: ./node
dockerfile: ./Dockerfile
auth:
image: quay.io/oauth2-proxy/oauth2-proxy:v7.5.0
env_file:
- .env.local
ports:
- "4180:4180"
environment:
OAUTH2_PROXY_PROVIDER: oidc
OAUTH2_PROXY_REDIRECT_URL: http://localhost/oauth2/callback
OAUTH2_PROXY_COOKIE_SECURE: "false"
OAUTH2_PROXY_COOKIE_NAME: "auth"
OAUTH2_PROXY_EMAIL_DOMAINS: "*"
OAUTH2_PROXY_HTTP_ADDRESS: 0.0.0.0:4180
OAUTH2_PROXY_UPSTREAMS: static://202
OAUTH2_PROXY_REVERSE_PROXY: true
OAUTH2_PROXY_SCOPE: email profile openid
OAUTH2_PROXY_SKIP_PROVIDER_BUTTON: true
OAUTH2_PROXY_SET_AUTHORIZATION_HEADER: true
OAUTH2_PROXY_SET_XAUTHREQUEST: true
OAUTH2_PROXY_PASS_ACCESS_TOKEN: true
ドキュメントを参照しながらより詳しい説明が必要な場合は、以下を参照して下さい。
OAuth2-Proxy Overview
解説
ポイント
- JWT を Authorization から取得し、ユーザー情報を利用します
- oauth2-proxy は OP とのやりとりを担当し、認証済みの場合は nginx に202 を返却します
- nginx は oauth2-proxy と upstream 先のアプリケーション の間に入り、リクエストのヘッダーを書き換えて JWT を渡します
- upstream 先のアプリケーションは JWT を検証し、ユーザー情報を取り出してアプリケーションのロジックに利用します
まとめ
このような実装方法でプロキシ型の認証を実装することが出来ました。勿論、アプリケーションに認証ロジックを組み込んでしまうことは悪いことではありません。寧ろ、クイックにシンプルなインフラ構成でアプリケーションを構築する必要があるのなら、このようなプロキシ型の構成は逆効果でもあると思います。あくまでも一例としてプロキシ型認証が必要になった時に、参考になれば幸いです(後、コードのご指摘歓迎)。
当方ブロックチェーン関連も活動しているので、もし何か実装してみたいと思っている方がいましたら、是非プロフィールから過去記事も是非閲覧下さい。