結論から言うと、リバースプロキシでのSSOは
「認証はプロキシで一元化し、バックエンドには“認証済みユーザ情報”だけを渡す」
という形で実現します。
nginx単体で完結するというより、外部の認証基盤(OIDC/OAuth2)+nginxの連携が実務の定番です。
ここでは一番現実的な構成として
**nginx + oauth2-proxy(OIDC連携)**で説明します。
全体構成
[User] ↓[nginx (reverse proxy)] ↓(未認証ならリダイレクト)[oauth2-proxy] ←→ [IdP(認証サーバ)] ↓(認証済み)[nginx] ↓(ヘッダ付与)[Backend Apps]
流れ(SSOの本質)
ユーザがアプリにアクセス
nginxが認証チェック
未認証 → oauth2-proxyへリダイレクト
IdPでログイン
Cookie発行(セッション)
nginxはそのCookieを見て「認証済み」と判断
バックエンドにユーザ情報をヘッダで渡す
→ 他のアプリでも同じCookieを使うのでSSO成立
nginx設定例
1. auth_requestを使う
server { listen 80; server_name example.com; location / { auth_request /auth; error_page 401 = @error401; proxy_set_header X-User $upstream_http_x_auth_request_user; proxy_set_header X-Email $upstream_http_x_auth_request_email; proxy_pass http://backend; } location = /auth { internal; proxy_pass http://oauth2-proxy/auth; proxy_pass_request_body off; proxy_set_header Content-Length ""; proxy_set_header X-Original-URI $request_uri; } location @error401 { return 302 http://oauth2-proxy/sign_in; }}
2. oauth2-proxy側(例)
起動例:
oauth2-proxy \ --provider=oidc \ --client-id=CLIENT_ID \ --client-secret=CLIENT_SECRET \ --cookie-secret=RANDOM_SECRET \ --redirect-url=http://example.com/oauth2/callback \ --oidc-issuer-url=https://idp.example.com \ --email-domain=* \ --http-address=0.0.0.0:4180
ポイント解説
① auth_requestがキモ
nginxがサブリクエストで /auth を叩く
200 → OK
401 → 未認証
② ヘッダでユーザ情報を渡す
バックエンドはこれを信頼して認可処理。
③ CookieでSSO成立
oauth2-proxyがCookieを発行
ドメイン共通なら複数アプリで使い回し可能
nginx単体でやれないの?
正直に言うと:
nginx単体でSSOはかなり厳しい
理由:
認証フロー(OAuth/OIDC)が複雑
トークン管理が必要
セッション管理が必要
そのため現実は:
oauth2-proxy
Keycloak
Authentik
などと組み合わせる
応用パターン
複数アプリSSO
app1.example.comapp2.example.com
同一Cookieドメインにする
nginxはそれぞれ同じauth_request
APIの場合
CookieではなくBearerトークン
nginxでJWT検証(lua / njsなど)
セキュリティ注意点
バックエンドは直接公開しない
X-Userヘッダを外部から受けない
HTTPS必須
CookieはSecure / HttpOnly
まとめ
この記事へのコメント