自己証明適用手順
Nginxのインストール
sudo apt update
sudo apt install nginx -y
sudo systemctl enable nginx
sudo systemctl start nginx
自己証明書作成
※参考
https://qiita.com/ohakutsu/items/814825a76b5299a96661
$ mkdir -p /etc/nginx/certs
$ openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -aes-256-cbc -out privkey.pem
Enter PEM pass phrase: (パスフレーズを入力)
Verifying - Enter PEM pass phrase: (パスフレーズを再度入力)
$ openssl req -new -key privkey.pem -out csr.pem
-----
Country Name (2 letter code) [AU]:JP <-入力
State or Province Name (full name) [Some-State]:Tokyo <-入力
Locality Name (eg, city) []:Shibuya-ku <-入力
Organization Name (eg, company) [Internet Widgits Pty Ltd]:ohakutsu <-入力
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:localhost:443 <-入力
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
$ openssl x509 -req -in csr.pem -signkey privkey.pem -days 90 -out crt.pem
Enter pass phrase for privkey.pem:
Certificate request self-signature ok
subject=C=JP, ST=Tokyo, L=Shinagawa, O=Sky, CN=myssl.test
$ touch passwd
$ echo 'パスフレーズ' > passwd
$ sudo cp ./crt.pem /etc/nginx/certs/cert.pem
$ sudo cp ./privkey.pem /etc/nginx/certs/key.pem
$ sudo cp ./passwd /etc/nginx/certs/passwd
$ chmod 600 /etc/nginx/ssl/passwd
※上の設定の場合、Azure上のリダイレクト URIは下記としておく
https://localhost:443/oauth2/callback
Nginxの設定
sudo vi /etc/nginx/sites-available/local
server {
# SSLポートでリッスン (標準は443)
listen 443 ssl;
# ドメイン名設定
server_name localhost;
# 証明書の設定 (手順1で作ったファイルのパス)
ssl_certificate /etc/nginx/certs/cert.pem;
ssl_certificate_key /etc/nginx/certs/key.pem;
ssl_password_file /etc/nginx/certs/passwd;
location / {
# バックエンドアプリへの転送
proxy_pass http://127.0.0.1:8080;
# --- 重要: Azure AD 認証に必要なヘッダー設定 ---
# クライアントがアクセスしてきたホスト名 (localhost) を維持する
proxy_set_header Host $host;
# クライアントの実IPアドレスを転送する
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# プロトコルが HTTPS であることをバックエンドに伝える
# (これがないと、バックエンドが redirect_uri を http://... で生成してしまい、Azureでエラーになる場合があります)
proxy_set_header X-Forwarded-Proto https;
}
}
sudo ln -s /etc/nginx/sites-available/local /etc/nginx/sites-enabled/
sudo systemctl restart nginx
EntraID認証適用
oauth2-proxyのインストールと設定
wget https://github.com/oauth2-proxy/oauth2-proxy/releases/download/v7.10.0/oauth2-proxy-v7.10.0.linux-amd64.tar.gz
tar -xvf oauth2-proxy-v7.10.0.linux-amd64.tar.gz
sudo mv oauth2-proxy-v7.10.0.linux-amd64/oauth2-proxy /usr/local/bin/
sudo rm -rf oauth2-proxy-v7.10.0.linux-amd64 oauth2-proxy-v7.10.0.linux-amd64.tar.gz
Cookie シークレットの生成
python3 -c 'import os; print(os.urandom(16).hex())'
systemd サービスの作成
sudo vi /etc/systemd/system/oauth2-proxy.service
[Unit]
Description=OAuth2 Proxy for Entra ID
After=network.target
[Service]
ExecStart=/usr/local/bin/oauth2-proxy \
--http-address="0.0.0.0:4180" \
--upstream="http://localhost:8080" \
--provider="azure" \
--client-id="正しく設定" \
--client-secret="正しく設定" \
--redirect-url="https://localhost:443/oauth2/callback" \
--oidc-issuer-url="https://login.microsoftonline.com/正しく設定/v2.0" \
--cookie-secret="正しく設定" \
--cookie-domain="localhost:443" \
--cookie-secure=true \
--cookie-expire=24h \
--set-xauthrequest=true \
--email-domain="*"
Environment="GOMAXPROCS=1" # 必要に応じて調整
Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=oauth2-proxy
[Install]
WantedBy=multi-user.target
oauth2-proxy サービスの有効化と起動
sudo systemctl daemon-reload
sudo systemctl enable oauth2-proxy
sudo systemctl start oauth2-proxy
sudo systemctl status oauth2-proxy
sudo journalctl -u oauth2-proxy -f
※修正時
sudo systemctl daemon-reload
sudo systemctl restart oauth2-proxy.service
sudo vi /etc/nginx/sites-available/localhost
server {
# SSLポートでリッスン (標準は443)
listen 443 ssl;
# ドメイン名設定
server_name localhost;
# 証明書の設定 (手順1で作ったファイルのパス)
ssl_certificate /etc/nginx/certs/cert.pem;
ssl_certificate_key /etc/nginx/certs/key.pem;
ssl_password_file /etc/nginx/certs/passwd;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1h;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE';
ssl_prefer_server_ciphers on;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
# oauth2-proxy の認証エンドポイント
location /oauth2 {
proxy_pass http://localhost:4180; # oauth2-proxy がリッスンしているアドレスとポート
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Scheme $scheme; # oauth2-proxy が HTTPS を認識できるように
proxy_set_header Cookie $http_cookie; # クッキーを転送
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_buffering off;
}
# Web アプリケーションへのリバースプロキシと認証
location / {
auth_request /oauth2/auth; # oauth2-proxy に認証を要求
error_page 401 = /oauth2/start?rd=$request_uri; # 認証失敗時に oauth2-proxy のログインページへリダイレクト
# oauth2-proxy から受け取ったユーザー情報を Web アプリケーションに転送
auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
proxy_set_header X-Auth-Request-User $user;
proxy_set_header X-Auth-Request-Email $email;
# Web アプリケーションへのプロキシ設定
# proxy_pass http://localhost:8080; # Web アプリケーションのポート
proxy_pass http://127.0.0.1:8080;
proxy_buffering off; # 重要:回答のタイピング表示をなめらかにする
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket対応(将来的な安定性のため)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
sudo nginx -t
sudo systemctl restart nginx
※参考
https://qiita.com/tksugar/items/361f77a762e79957bd58
サーバー基本設定 / SSL設定
サーバー全体に関わるリッスンポート、ドメイン、およびSSL/TLSセキュリティに関する設定です。
| パラメータ項目 | 設定値 | 説明・備考 |
|---|---|---|
| listen | 443 ssl |
SSLポートでの待ち受けを有効化 |
| server_name | localhost |
サーバーのドメイン名 |
| ssl_certificate | /etc/nginx/certs/cert.pem |
公開鍵証明書ファイルのパス |
| ssl_certificate_key | /etc/nginx/certs/key.pem |
秘密鍵ファイルのパス |
| ssl_password_file | /etc/nginx/certs/passwd |
秘密鍵のパスフレーズファイル(暗号化されている場合) |
| ssl_session_cache | shared:SSL:10m |
SSLセッションキャッシュ(共有メモリ10MB)。 クライアントが同じセッションID(またはセッションチケット)を提示して再接続を試みた際、サーバーは保存されているキャッシュ内のマスターシークレットキーを使用して通信を確立します。これにより、**鍵交換(Key Exchange)や検証(Verification)を含む完全なハンドシェイクプロセス(約2〜3往復)が省略され、**初回接続よりもはるかに高速に通信を開始できます。 |
| ssl_session_timeout | 1h |
SSLセッションのタイムアウト時間 キャッシュの失効: 設定されたタイムアウト時間内にクライアントが再接続した場合、セッション再開が成功し、セッション情報が更新されます(タイムアウト時間がリセットされます)。 再ハンドシェイク: 設定されたタイムアウト時間を経過した後、クライアントがセッションIDを提示して再接続を試みても、キャッシュ内の情報は**無効(失効)**と見なされます。この場合、クライアントとサーバーはセッション再開を諦め、完全なSSL/TLSハンドシェイクを最初からやり直す必要があります。 |
| ssl_protocols | TLSv1.2 TLSv1.3 |
許可するTLSプロトコルのバージョン |
| ssl_ciphers |
TLS_AES_256_GCM_SHA384... (※1) |
使用する暗号化スイートのリスト(高強度なものを指定)。サーバーはこのリストで定義された暗号スイートのみを、SSL/TLSハンドシェイク時にクライアントに提示します。クライアントから提示された暗号スイートが、このリストに含まれていない場合、サーバーはその暗号スイートを選択肢として考慮しません。 |
| ssl_prefer_server_ciphers | on |
サーバー側の暗号化スイート優先度を優先する。 on:サーバー側が持つ暗号スイートのリスト(ssl_ciphersで定義されたもの)の優先順位に従って、クライアントとサーバーの共通する暗号スイートの中から一つが選択されます。サーバーの優先順位が採用されます。 off:クライアント側が提示した暗号スイートのリストの優先順位に従って、クライアントとサーバーの共通する暗号スイートの中から一つが選択されます。クライアントの優先順位が採用されます。(多くのサーバーでのデフォルト設定) |
(※1) 設定値詳細: TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE
oauth2-proxy 構成定義
Unitファイルの起動パラメータに基づく設計値です。
| カテゴリ | パラメータ引数 | 設定値 | 設計内容・役割 |
|---|---|---|---|
| 基本動作 | --http-address |
0.0.0.0:4180 |
リッスンアドレス 全インターフェースのポート4180で待受 |
--upstream |
http://localhost:8080 |
アップストリーム(バックエンド) ※本構成ではNGINXが直接バックエンドへ転送するため、oauth2-proxy側では形式的な設定、あるいは直接アクセス時の転送先となる |
|
--redirect-url |
https://localhost:443/oauth2/callback |
コールバックURL 認証完了後にAzure ADから戻ってくる先 (NGINX経由で受ける) |
|
| IdP連携 (Azure) | --provider |
azure |
認証プロバイダ Microsoft Entra ID (旧 Azure AD) を使用 |
--client-id |
(正しく設定) |
アプリケーションID Azure側で発行されたクライアントID |
|
--client-secret |
(正しく設定) |
シークレット Azure側で発行されたクライアントシークレット |
|
--oidc-issuer-url |
https://login.microsoftonline.com/.../v2.0 |
OIDC発行者URL テナントIDを含むOpenID Connectのエンドポイント |
|
| セッション管理 | --cookie-secret |
(正しく設定) |
クッキー暗号化キー ブラウザに保存するクッキーを暗号化するためのシード |
--cookie-domain |
localhost:443 |
クッキーの有効ドメイン ブラウザがクッキーを送信するスコープ |
|
--cookie-secure |
true |
Secure属性 HTTPS通信時のみクッキーを送信する(必須設定) |
|
--cookie-expire |
24h |
有効期限 認証セッションの有効期間を24時間とする |
|
| 連携制御 | --set-xauthrequest |
true |
NGINX連携フラグ (重要) 認証成功時、レスポンスヘッダに X-Auth-Request-User/Email を付与してNGINXへ返す設定 |
--email-domain |
* |
許可メールドメイン プロバイダ側で認証できればドメインによる制限を行わない |
|
| システム環境 | GOMAXPROCS |
1 |
CPU使用制限 Go言語ランタイムが使用するCPUコア数を1に制限 |
2. 通信・稼働フロー設計
ユーザーがブラウザでアクセスした際、NGINXとoauth2-proxyがどのように連携して動作するかを時系列で記述します。
2.1. シーケンス概略
この構成では、NGINXが「関所」となり、oauth2-proxyは「通行手形(クッキー)の確認係」として動作します。
-
【未認証時】
- ユーザー → NGINX (
/) - NGINX → oauth2-proxy (
/oauth2/auth) へ問い合わせ - oauth2-proxy → 401 Unauthorized を返却
- NGINX → ユーザーを
https://login.microsoftonline.com/...(Azure AD) へ誘導
- ユーザー → NGINX (
-
【認証・コールバック】
- ユーザー → Azure ADでログイン
- Azure AD → NGINX (
/oauth2/callback) へリダイレクト - NGINX → oauth2-proxy へ転送
- oauth2-proxy → トークン検証・Cookie発行 → 元のURLへリダイレクト
-
【認証済み(通常利用)】
- ユーザー → NGINX (
/) ※Cookieあり - NGINX → oauth2-proxy (
/oauth2/auth) へ問い合わせ - oauth2-proxy → Cookie検証 → 202 Accepted + ユーザー情報ヘッダ を返却
- NGINX → バックエンドアプリ (
localhost:8080) へリクエスト転送
- ユーザー → NGINX (
2.2. 詳細動作仕様 (リクエスト単位)
各フェーズにおけるコンポーネント間の具体的なデータの流れです。
| フェーズ | 通信方向 | 処理内容詳細 |
|---|---|---|
|
A. 初回アクセス (Cookieなし) |
Client -> NGINX | ユーザーが https://localhost/ へアクセス。 |
| NGINX -> oauth2-proxy |
auth_request /oauth2/auth により、リクエストヘッダのみを oauth2-proxy へ内部送信。 |
|
| oauth2-proxy -> NGINX | Cookieが存在しないため、HTTPステータス 401 を返却。 | |
| NGINX -> Client |
error_page 401 設定に基づき、/oauth2/start 経由で Azure AD ログイン画面へ 302 リダイレクト。 |
|
| B. 認証プロセス | Client <-> Azure AD | ユーザーがID/PWを入力し、MFA等を経て認証成功。Azureは /oauth2/callback へリダイレクト指示。 |
| Client -> NGINX |
https://localhost/oauth2/callback?code=... へアクセス。 |
|
| NGINX -> oauth2-proxy |
/oauth2 location設定に基づき、リクエストをそのまま 127.0.0.1:4180 へプロキシ。 |
|
| oauth2-proxy <-> Azure | 受け取った code を使い、Azure ADへアクセストークンを要求・取得・検証。 |
|
| oauth2-proxy -> NGINX | 検証成功。暗号化されたセッションCookie をSet-Cookieヘッダに乗せて、元のURL (/) へのリダイレクトを返却。 |
|
| NGINX -> Client | レスポンスをクライアントへ返す。クライアントはCookieを保存。 | |
|
C. アプリ利用 (Cookieあり) |
Client -> NGINX | クッキーを持った状態で https://localhost/ へアクセス。 |
| NGINX -> oauth2-proxy |
auth_request /oauth2/auth で内部問い合わせ(Cookieも転送)。 |
|
| oauth2-proxy -> NGINX |
【重要】 Cookieを復号し有効性を確認。 OKの場合、ステータス 202 Accepted を返却。 同時にレスポンスヘッダに以下を付与: ・ X-Auth-Request-User: user@example.com・ X-Auth-Request-Email: user@example.com
|
|
| NGINX -> App (8080) | 202を受け取ったNGINXは、上記ヘッダを X-Auth-Request-User 等としてリクエストにコピーし、バックエンドアプリへ送信。 |
|
| App -> NGINX -> Client | アプリケーションが処理を行い、Web画面を表示。 |
※個人用メモ(Keycloak連携試行)
- AzureEntraのリダイレクト URI
https://domain.test.001/realms/myrealm/broker/domainazurearias/endpoint
- Keycloak Version 26.4.7
docker run -d -p 8081:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin -e KC_PROXY=edge -e KC_HTTP_ENABLED=true quay.io/keycloak/keycloak:latest start-dev
Frontend URL : https://domain.test.001/
- Oauth2-Proxy
[Unit]
Description=OAuth2 Proxy for Entra ID
After=network.target
[Service]
ExecStart=/usr/local/bin/oauth2-proxy \
--http-address="0.0.0.0:4180" \
--upstream="http://127.0.0.1:8080" \
--provider="oidc" \
--client-id="oauth2-proxy" \
--client-secret="正しく設定" \
--redirect-url="https://domain.test.001/oauth2/callback" \
--oidc-issuer-url="https://domain.test.001/realms/myrealm" \
--cookie-secret="正しく設定" \
--cookie-domain="domain.test.001" \
--cookie-secure=true \
--cookie-samesite=lax \
--cookie-expire=24h \
--cookie-refresh=1h \
--skip-provider-button=true \
--set-xauthrequest=true \
--email-domain="*" \
--insecure-oidc-allow-unverified-email=true \
--ssl-insecure-skip-verify
Environment="GOMAXPROCS=1" # 必要に応じて調整
Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=oauth2-proxy
[Install]
WantedBy=multi-user.target
※v7.2.0 から下記を設定可能
# 例: oauth2-proxy の起動引数に追加
--redeem-url="http://<nginxの内部IPまたはサービス名>/auth/realms/<realm>/protocol/openid-connect/token"
--oidc-jwks-url="http://<nginxの内部IPまたはサービス名>/auth/realms/<realm>/protocol/openid-connect/certs"
--validate-url="http://<nginxの内部IPまたはサービス名>/auth/realms/<realm>/protocol/openid-connect/userinfo"
また、起動オプションに下記を追加
--insecure-oidc-skip-issuer-verification=true
- Nginx
server {
listen 80;
server_name domain.test.001;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name domain.test.001;
ssl_certificate /etc/nginx/certs/cert.pem;
ssl_certificate_key /etc/nginx/certs/key.pem;
ssl_password_file /etc/nginx/certs/passwd;
# 巨大なトークン対策(これは必須)
proxy_buffer_size 256k;
proxy_buffers 4 512k;
proxy_busy_buffers_size 512k;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
# 認証除外(OAuth2 Proxy, Keycloak, Dify静的ファイル)
location /oauth2/ {
auth_request off;
proxy_pass http://127.0.0.1:4180;
}
location /realms/ {
auth_request off;
proxy_pass http://127.0.0.1:8081;
}
location /resources/ {
auth_request off;
proxy_pass http://127.0.0.1:8081;
}
location ~* ^/(favicon\.ico|robots\.txt|static/|assets/|v1/console/api/setup) {
auth_request off;
proxy_pass http://127.0.0.1:8080;
}
# メインアプリケーション
location / {
auth_request /oauth2/auth;
error_page 401 = /oauth2/start?rd=$request_uri;
auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
proxy_set_header X-Auth-Request-User $user;
proxy_set_header X-Auth-Request-Email $email;
proxy_pass http://127.0.0.1:8080;
}
}
- Nginx(SSLオフロード)
# =========================================================
# 1. 内部アプリケーション役 Nginx (Port 80)
# - 本番環境のNginxと同じ設定
# - AGWから受け取ったリクエストをバックエンドへ流す
# =========================================================
server {
listen 80;
server_name domain.test.001;
# -----------------------------------------------------
# ★重要: 巨大なCookie/トークン対策 (受信側)
# -----------------------------------------------------
proxy_buffer_size 256k;
proxy_buffers 4 512k;
proxy_busy_buffers_size 512k;
# -----------------------------------------------------
# ヘッダー設定
# -----------------------------------------------------
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# ここで強制的に https を指定することで、
# AGWからの転送漏れがあってもバックエンドはHTTPSとして動作します
proxy_set_header X-Forwarded-Proto https;
# -----------------------------------------------------
# 各種ルーティング
# -----------------------------------------------------
# 認証除外(OAuth2 Proxy)
location /oauth2/ {
auth_request off;
proxy_pass http://127.0.0.1:4180;
}
# 認証除外(Keycloak等のIDP)
location /realms/ {
auth_request off;
proxy_pass http://127.0.0.1:8081;
}
location /resources/ {
auth_request off;
proxy_pass http://127.0.0.1:8081;
}
# 静的ファイル・API除外
location ~* ^/(favicon\.ico|robots\.txt|static/|assets/|v1/console/api/setup) {
auth_request off;
proxy_pass http://127.0.0.1:8080;
}
# メインアプリケーション (要認証)
location / {
auth_request /oauth2/auth;
error_page 401 = /oauth2/start?rd=$request_uri;
# 認証情報の引き渡し
auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
proxy_set_header X-Auth-Request-User $user;
proxy_set_header X-Auth-Request-Email $email;
proxy_pass http://127.0.0.1:8080;
}
}
# =========================================================
# 2. AGW (SSLオフロード) 模倣用 Nginx (Port 443)
# - クライアントとはHTTPSで通信
# - 裏側のNginx(Port 80)へはHTTPで転送
# =========================================================
server {
listen 443 ssl;
server_name domain.test.001;
ssl_certificate /etc/nginx/certs/cert.pem;
ssl_certificate_key /etc/nginx/certs/key.pem;
ssl_password_file /etc/nginx/certs/passwd;
# -----------------------------------------------------
# ★修正ポイント: 巨大なCookie/トークン対策 (中継側)
# これがないと、80番から返ってきた巨大ヘッダーを受け取れずエラーになります
# -----------------------------------------------------
proxy_buffer_size 256k;
proxy_buffers 4 512k;
proxy_busy_buffers_size 512k;
location / {
# 自分自身の80番ポート(本番Nginx役)へ転送
proxy_pass http://127.0.0.1:80;
# -------------------------------------------------
# AGWの挙動を模倣するためのヘッダー付与
# -------------------------------------------------
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# ★最重要: 「元はHTTPS・ポート443でした」と伝える
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Port 443;
# -------------------------------------------------
# WebSocket対応 (Dify等のAIアプリで推奨)
# -------------------------------------------------
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# タイムアウト設定(生成待ちなどの長時間接続用)
proxy_read_timeout 300s;
}
}
情報連携用設定
[Unit]
Description=OAuth2 Proxy for Entra ID
After=network.target
[Service]
ExecStart=/usr/local/bin/oauth2-proxy \
--http-address="0.0.0.0:4180" \
--upstream="http://127.0.0.1:8080" \
--provider="oidc" \
--client-id="oauth2-proxy" \
--client-secret="A9ouGj26faCMjQxz5I7euMLpRltxNrNW" \
--redirect-url="https://domain.test.001/oauth2/callback" \
--oidc-issuer-url="https://domain.test.001/realms/myrealm" \
--cookie-secret="dfd5b7eefe822e3caf0bad6133e2349e" \
--cookie-domain="domain.test.001" \
--cookie-secure=true \
--cookie-samesite=lax \
--cookie-expire=24h \
--cookie-refresh=1h \
--skip-provider-button=true \
--set-xauthrequest=true \
--email-domain="*" \
--insecure-oidc-allow-unverified-email=true \
--ssl-insecure-skip-verify=true \
--pass-authorization-header=true \
--set-xauthrequest=true \
--pass-user-headers=true \
--user-id-claim="email" \
--pass-access-token=true
Environment="GOMAXPROCS=1" # 必要に応じて調整
Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=oauth2-proxy
[Install]
WantedBy=multi-user.target
# ---------------------------------------------------------
map $host $token { default ""; }
map $host $user { default ""; }
map $host $email { default ""; }
# ---------------------------------------------------------
# ログフォーマット定義 (既存の記述)
# ---------------------------------------------------------
log_format oidc_debug '$remote_addr - [$time_local] "$request" '
'Status:$status '
'User:"$user" '
'Email:"$email" '
'Token:"$token"';
# =========================================================
# 1. 内部アプリケーション役 Nginx (Port 80)
# - 本番環境のNginxと同じ設定
# - AGWから受け取ったリクエストをバックエンドへ流す
# =========================================================
server {
listen 80;
server_name domain.test.001;
# 定義したフォーマット "oidc_debug" を適用
#access_log /var/log/nginx/access_oidc_debug.log oidc_debug;
# -----------------------------------------------------
# ★重要: 巨大なCookie/トークン対策 (受信側)
# -----------------------------------------------------
proxy_buffer_size 256k;
proxy_buffers 4 512k;
proxy_busy_buffers_size 512k;
# -----------------------------------------------------
# ヘッダー設定
# -----------------------------------------------------
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# ここで強制的に https を指定することで、
# AGWからの転送漏れがあってもバックエンドはHTTPSとして動作します
proxy_set_header X-Forwarded-Proto https;
# -----------------------------------------------------
# 各種ルーティング
# -----------------------------------------------------
# 認証除外(OAuth2 Proxy)
location /oauth2/ {
auth_request off;
proxy_pass http://127.0.0.1:4180;
}
# 認証除外(Keycloak等のIDP)
location /realms/ {
auth_request off;
proxy_pass http://127.0.0.1:8081;
}
location /resources/ {
auth_request off;
proxy_pass http://127.0.0.1:8081;
}
# 静的ファイル・API除外
location ~* ^/(favicon\.ico|robots\.txt|static/|assets/|v1/console/api/setup) {
auth_request off;
proxy_pass http://127.0.0.1:8080;
}
# メインアプリケーション (要認証)
location / {
auth_request /oauth2/auth;
error_page 401 = /oauth2/start?rd=$request_uri;
# -----------------------------------------------------
# 認証情報の引き渡し
# -----------------------------------------------------
auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
auth_request_set $token $upstream_http_x_auth_request_access_token;
proxy_set_header X-Auth-Request-User $user;
proxy_set_header X-Auth-Request-Email $email;
proxy_set_header X-Access-Token $token;
proxy_pass http://127.0.0.1:8080;
}
}
# =========================================================
# 2. AGW (SSLオフロード) 模倣用 Nginx (Port 443)
# - クライアントとはHTTPSで通信
# - 裏側のNginx(Port 80)へはHTTPで転送
# =========================================================
server {
listen 443 ssl;
server_name domain.test.001;
ssl_certificate /etc/nginx/certs/cert.pem;
ssl_certificate_key /etc/nginx/certs/key.pem;
ssl_password_file /etc/nginx/certs/passwd;
# -----------------------------------------------------
# ★修正ポイント: 巨大なCookie/トークン対策 (中継側)
# これがないと、80番から返ってきた巨大ヘッダーを受け取れずエラーになります
# -----------------------------------------------------
proxy_buffer_size 256k;
proxy_buffers 4 512k;
proxy_busy_buffers_size 512k;
location / {
# 自分自身の80番ポート(本番Nginx役)へ転送
proxy_pass http://127.0.0.1:80;
# -------------------------------------------------
# AGWの挙動を模倣するためのヘッダー付与
# -------------------------------------------------
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# ★最重要: 「元はHTTPS・ポート443でした」と伝える
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Port 443;
# -------------------------------------------------
# WebSocket対応 (Dify等のAIアプリで推奨)
# -------------------------------------------------
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# タイムアウト設定(生成待ちなどの長時間接続用)
proxy_read_timeout 300s;
}
}
Keycloak マッパーの再確認
Azure の設定が終わったら、Keycloak のマッパーがそれを受け取れるようになっているか確認します。
Keycloak 管理画面 > Identity Providers > Azure Entra ID > Mappers。
Email 用のマッパー:
Name: email-map
Mapper Type: Attribute Importer
Claim: email
User Attribute Name: email
Username 用のマッパー:
Name: username-map
Mapper Type: Username Template Importer
Template: ${CLAIM.email}
Target: LOCAL
パラメータ消失対策
server {
listen 80;
server_name domain.test.001;
# ログ設定(必要に応じてコメントアウトを解除)
# access_log /var/log/nginx/access_oidc_debug.log oidc_debug;
# -----------------------------------------------------
# バッファ設定
# -----------------------------------------------------
proxy_buffer_size 256k;
proxy_buffers 4 512k;
proxy_busy_buffers_size 512k;
# -----------------------------------------------------
# ヘッダー設定 (全体共通)
# -----------------------------------------------------
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
# -----------------------------------------------------
# 除外ルーティング
# -----------------------------------------------------
# 認証除外(OAuth2 Proxy)
location /oauth2/ {
auth_request off;
proxy_pass http://127.0.0.1:4180;
}
# 認証除外(Keycloak等のIDP)
location /realms/ {
auth_request off;
proxy_pass http://127.0.0.1:8081;
}
location /resources/ {
auth_request off;
proxy_pass http://127.0.0.1:8081;
}
# 静的ファイル・API除外
location ~* ^/(favicon\.ico|robots\.txt|static/|assets/|v1/console/api/setup) {
auth_request off;
proxy_pass http://127.0.0.1:8080;
}
# -----------------------------------------------------
# メインアプリケーション (要認証)
# -----------------------------------------------------
location / {
auth_request /oauth2/auth;
# 【変更点】401エラー時はJSリダイレクト用のロケーションへ飛ばす
error_page 401 = @oauth2_start;
# -----------------------------------------------------
# 認証情報の引き渡し
# -----------------------------------------------------
auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
auth_request_set $token $upstream_http_x_auth_request_access_token;
proxy_set_header X-Auth-Request-User $user;
proxy_set_header X-Auth-Request-Email $email;
proxy_set_header X-Access-Token $token;
proxy_pass http://127.0.0.1:8080;
}
# -----------------------------------------------------
# 【追加・重要】JSリダイレクト処理
# -----------------------------------------------------
location @oauth2_start {
# ブラウザにHTMLを返し、JSでURLエンコードさせてからOAuth2 Proxyへ遷移させます。
# これにより "&" がURLの区切りとして誤認識されるのを防ぎます。
default_type text/html;
# リダイレクト用HTMLがキャッシュされないように設定
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
# JavaScriptを含むHTMLを返却
return 200 '<html>
<head><title>Redirecting...</title></head>
<body>
<script>
// 現在のパスとクエリパラメータ(?email=...&token=...)を取得
var currentPath = window.location.pathname + window.location.search;
// URLエンコードを行って rd パラメータに設定
// encodeURIComponentを使うことで & は %26 に変換され、安全に渡されます
var targetUrl = "/oauth2/start?rd=" + encodeURIComponent(currentPath);
// リダイレクト実行
window.location.href = targetUrl;
</script>
</body>
</html>';
}
}
/usr/share/nginx/html/redirect_oauth2.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Redirecting to Authentication...</title>
</head>
<body>
<script>
/**
* 現在のパスとクエリパラメータを取得し、URLエンコードを行う。
* これにより "&" や "=" が区切り文字として誤認識されるのを防ぎ、
* OAuth2 Proxy へパラメータを完全に渡すことができる。
*/
var currentPath = window.location.pathname + window.location.search;
var targetUrl = "/oauth2/start?rd=" + encodeURIComponent(currentPath);
window.location.href = targetUrl;
</script>
<noscript>
<p>JavaScript is required to proceed to authentication.</p>
</noscript>
</body>
</html>
server {
listen 80;
server_name domain.test.001;
# ログ設定(必要に応じてコメントアウトを解除)
# access_log /var/log/nginx/access_oidc_debug.log oidc_debug;
# -----------------------------------------------------
# バッファ設定
# -----------------------------------------------------
proxy_buffer_size 256k;
proxy_buffers 4 512k;
proxy_busy_buffers_size 512k;
# -----------------------------------------------------
# ヘッダー設定 (全体共通)
# -----------------------------------------------------
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
# -----------------------------------------------------
# 除外ルーティング
# -----------------------------------------------------
# 認証除外(OAuth2 Proxy)
location /oauth2/ {
auth_request off;
proxy_pass http://127.0.0.1:4180;
}
# 認証除外(Keycloak等のIDP)
location /realms/ {
auth_request off;
proxy_pass http://127.0.0.1:8081;
}
location /resources/ {
auth_request off;
proxy_pass http://127.0.0.1:8081;
}
# 静的ファイル・API除外
location ~* ^/(favicon\.ico|robots\.txt|static/|assets/|v1/console/api/setup) {
auth_request off;
proxy_pass http://127.0.0.1:8080;
}
# -----------------------------------------------------
# メインアプリケーション (要認証)
# -----------------------------------------------------
location / {
auth_request /oauth2/auth;
# 【変更点】
# 401エラー時は、サーバー内部で作成した外部HTMLファイルを表示します。
# "=200" を指定することで、ブラウザに正常なページとしてHTMLを処理させます。
error_page 401 =200 /redirect_oauth2.html;
# -----------------------------------------------------
# 認証情報の引き渡し
# -----------------------------------------------------
auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
auth_request_set $token $upstream_http_x_auth_request_access_token;
proxy_set_header X-Auth-Request-User $user;
proxy_set_header X-Auth-Request-Email $email;
proxy_set_header X-Access-Token $token;
proxy_pass http://127.0.0.1:8080;
}
# -----------------------------------------------------
# 【追加】リダイレクト用HTMLファイルの配信設定
# -----------------------------------------------------
location = /redirect_oauth2.html {
# 作成したHTMLファイルがあるディレクトリを指定
# (ステップ1で作成した場所に合わせてください)
root /usr/share/nginx/html;
# 内部リダイレクト専用にする(直接URLを叩かせないセキュリティ対策)
internal;
# HTML自体がキャッシュされないようにヘッダーを付与
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
}