This episode explains HTTP Basic Authentication with htpasswd, subrequest authentication using auth_request for delegation to an auth API, and the JWT token validation approach in NGINX.

Rate limiting in episode 11 protects against volume attacks, but it doesn't answer the fundamental question: who is allowed in? This Episode 12 covers authentication and authorization in NGINX, from the simplest approach to enterprise patterns.
You'll secure internal areas with HTTP Basic Authentication, delegate authentication to a backend auth API using auth_request, and understand the JWT validation approach. After this episode, you'll be able to decide which authentication layer fits each part of your application.
The fastest way to secure a location: ask for a username and password through a browser dialog. First, create a password file using the htpasswd utility from the apache2-utils package:
sudo apt install apache2-utils -y
sudo htpasswd -c /etc/nginx/.htpasswd armanThe htpasswd -c /etc/nginx/.htpasswd arman command creates a new file and adds the user arman, then prompts for the password twice. To add more users, drop the -c option.
Enable authentication in the location you want to protect:
location /admin {
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/.htpasswd;
}When accessing /admin, the browser prompts for credentials. NGINX verifies against the auth_basic_user_file file and rejects with status 401 on failure. Simple and effective for internal dashboards.
Basic auth isn't flexible enough for modern applications that need accounts, sessions, and roles. The industry pattern: auth_request. NGINX sends a subrequest to an auth endpoint before forwarding the original request to the backend.
location /api/secure {
auth_request /auth-check;
auth_request_set $auth_user $upstream_http_x_auth_user;
proxy_pass http://backend_app;
proxy_set_header X-Auth-User $auth_user;
}
location = /auth-check {
internal;
proxy_pass http://auth_service:8080/validate;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
}The flow: a request to /api/secure triggers a subrequest to the internal /auth-check, which calls auth_service for validation. If the response is 2xx, the request is forwarded; if 401, NGINX rejects the request. Headers from the auth service can be captured with auth_request_set.
auth_request is the standard way to integrate with OAuth2 Proxy, Keycloak, or a custom auth service without changing a single line of application code.
JWT validation requires code: verifying the signature, checking expiry, and reading claims. NGINX open source has no built-in JWT module, but it supports extensions. Two popular approaches:
location via the js_content or auth_request directives.lua-resty-jwt library to validate tokens and forward claims as headers.A conceptual example using auth_request for token validation:
location /api/secure {
auth_request /jwt-check;
proxy_pass http://backend_app;
proxy_set_header Authorization $http_authorization;
}
location = /jwt-check {
internal;
js_content jwt_validator.check;
}The auth service handles decryption and signature validation, while NGINX stays responsible for routing and access control. With this pattern, authentication logic is centralized and can be shared by many services at once.
auth_request to an auth service (OAuth2, Keycloak, custom).There's no single right answer. Start from the simplest need, then increase complexity as the system grows.
Episode 12 opened the door to access control: you can lock down areas with Basic Authentication, delegate authentication to an external service via auth_request, and understand JWT validation patterns with njs or Lua.
Key takeaways:
htpasswd creates a user and password file for Basic Authentication.auth_basic and auth_basic_user_file enable it in a location.auth_request delegates authentication to a backend auth API via subrequest.internal so it can't be accessed directly.In the next episode we'll discuss WebSocket, Server-Sent Events (SSE), and gRPC proxying — upgrading headers for WebSocket, disabling buffering for realtime SSE, and proxying high-performance gRPC services.