2026年10月21日
2026年10月21日
Nginxのauth_requestで外部の認証サーバーに判定を任せる方法
Nginx の auth_request は、リクエストを処理する前に別の URL へ「サブリクエスト」を送り、その応答コードを見てアクセスを許可するかどうかを決める機能です。ログインの判定そのものは、アプリケーションや認証専用のサーバー(以下「認証サーバー」)に任せ、Nginx はその結果に従って通すか止めるかだけを行います。
この記事の設定は nginx.org の公式ドキュメント(ngx_http_auth_request_module)で2026年10月時点の内容を確認し、nginx 1.30 の検証環境で動作を確かめています。
仕組み
- 利用者が保護されたURL(例:
/private/)にアクセスする。 - Nginx は、利用者のリクエストヘッダー(Cookie や
Authorizationなど)を付けて、認証サーバーにサブリクエストを送る。 - 認証サーバーの応答コードで結果が決まる。
| 認証サーバーの応答 | Nginx の動作 |
|---|---|
| 2xx(200・204 など) | アクセスを許可し、本来のコンテンツを返す |
| 401 | 401 で拒否する。認証サーバーの応答の WWW-Authenticate ヘッダーも利用者に渡す |
| 403 | 403 で拒否する |
| それ以外 | エラーとして扱う(500 が返る) |
認証サーバーの応答本文は利用者には返りません。判定に使われるのは応答コードとヘッダーだけです。
手順1: モジュールが使えるか確認する
ngx_http_auth_request_module は、ソースからビルドする場合は既定で組み込まれず、--with-http_auth_request_module を付けてビルドする必要があります。nginx.org の公式パッケージや、多くのディストリビューションのパッケージには組み込まれています。次のコマンドで確認できます。
nginx -V 2>&1 | grep -o with-http_auth_request_module
with-http_auth_request_module と表示されれば使えます。何も表示されない場合は、組み込まれたパッケージに入れ替えるか、ビルドし直す必要があります。
手順2: 認証サーバーを用意する
認証サーバーは、リクエストを見て「許可なら 2xx、未ログインなら 401、権限不足なら 403」を返す HTTP のエンドポイントであれば、言語や製品は問いません。既存の Web アプリケーションのセッション確認用URL を使うこともできます。
この記事では、127.0.0.1:9000 の /auth で認証サーバーが動いている前提で説明します。
手順3: Nginx の設定を書く
server {
listen 443 ssl;
server_name example.com;
root /var/www/example.com;
# 保護する範囲
location /private/ {
auth_request /_auth;
# 認証サーバーが返したヘッダー X-Auth-User を変数に入れる
auth_request_set $auth_user $upstream_http_x_auth_user;
# 後ろのアプリケーションにユーザー名を渡す場合(proxy_pass を使うとき)
# proxy_set_header X-Auth-User $auth_user;
try_files $uri $uri/ =404;
}
# 認証サーバーへの問い合わせ用(外部からは開けない)
location = /_auth {
internal;
proxy_pass http://127.0.0.1:9000/auth;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
proxy_set_header X-Original-Method $request_method;
}
}
| 設定 | 意味 |
|---|---|
auth_request /_auth; |
このURIへのサブリクエストで許可を判定する |
auth_request_set $変数 値; |
判定が終わった後で変数に値を入れる。$upstream_http_ヘッダー名 で認証サーバーの応答ヘッダーを受け取れる |
internal; |
このlocation を内部リクエスト専用にし、外部から直接開くと 404 にする |
proxy_pass_request_body off; |
利用者が送った本文(POSTのデータなど)を認証サーバーに送らない |
proxy_set_header Content-Length ""; |
本文を送らないので、Content-Length ヘッダーを外す |
X-Original-URI など |
元のリクエストのURIやメソッドを認証サーバーに伝える(ヘッダー名は認証サーバーに合わせる) |
auth_request と auth_request_set は http・server・location に書けます。保護を外したい場所では auth_request off; を書きます。
手順4: 反映して動作を確かめる
sudo nginx -t
sudo systemctl reload nginx
curl で応答コードを見ます。下の例は、認証サーバーが X-Api-Key ヘッダーの値で判定する場合です。
# 認証情報なし → 認証サーバーが 401 を返すので 401
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/private/
# 正しい認証情報 → 200
curl -s -o /dev/null -w '%{http_code}\n' -H 'X-Api-Key: test-key' https://example.com/private/
# 問い合わせ用のURLを直接開く → internal なので 404
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/_auth
動作確認用の仮の認証サーバー
認証サーバーがまだ無い段階で設定を試すときは、Nginx 自身に仮の認証サーバーを作れます。X-Api-Key ヘッダーが test-key のときだけ許可し、X-Auth-User ヘッダーでユーザー名を返します。動作確認専用で、本番の認証には使わないでください。
server {
listen 127.0.0.1:9000;
location = /auth {
if ($http_x_api_key = "test-key") {
add_header X-Auth-User "alice" always;
return 204;
}
return 401;
}
}
検証環境ではこの組み合わせで、認証情報なしは 401、正しいヘッダー付きは 200、/_auth の直接アクセスは 404 になり、auth_request_set で受け取った変数にユーザー名が入ることを確認しました。
注意点
認証サーバーが止まると保護対象が開けなくなる
認証サーバーに接続できない、または 2xx・401・403 以外を返した場合はエラーになり、利用者には 500 が返ります。検証環境で認証サーバーを止めたところ、エラーログに auth request unexpected status: 502 と記録され、利用者には 500 が返りました。認証サーバーの監視と、エラーログ(/var/log/nginx/error.log)の確認方法を決めておいてください。
リクエストごとに問い合わせが発生する
既定では、保護対象へのリクエストのたびに認証サーバーへ問い合わせます。index によるディレクトリのインデックスや try_files の内部リダイレクトがあると、1回のアクセスで複数回問い合わせることもあります。負荷が問題になる場合は、/_auth の location で proxy_cache を使って判定結果をキャッシュできます(nginx 1.7.3 以降)。その場合は、キャッシュのキーに Cookie など利用者を区別する値を含めないと、ほかの利用者の判定結果が使い回されます。
認証サーバーとの通信を守る
認証サーバーを別のマシンに置く場合は、通信経路を HTTPS にするか、閉じたネットワークに置いてください。認証サーバーのURL を外部から直接開けないようにしておくことも必要です。
ほかのアクセス制限との組み合わせ
auth_request は、IPアドレスによる制限(allow・deny)や Basic認証(auth_basic)と satisfy ディレクティブで組み合わせられます。Basic認証そのものはNginxでBasic認証を設定する方法で説明しています。WordPress の管理画面や REST API を保護する例はNginx auth_requestで外部認証と連携する設定を参照してください。
まとめ
auth_requestは、認証サーバーへのサブリクエストの応答コード(2xx・401・403)で許可を決める。- 問い合わせ用の location には
internal、proxy_pass_request_body off、proxy_set_header Content-Length ""を書く。 - 認証サーバーが返したヘッダーは
auth_request_setと$upstream_http_*で受け取れる。 - 認証サーバーが止まると 500 になるため、監視と問い合わせの負荷を考えて運用する。