Skip to content

Instantly share code, notes, and snippets.

@bgautrea
Created March 6, 2020 15:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bgautrea/99b3fcb8cd0f321bae875f143da4eeb8 to your computer and use it in GitHub Desktop.
Save bgautrea/99b3fcb8cd0f321bae875f143da4eeb8 to your computer and use it in GitHub Desktop.
server {
listen 8080;
server_name _;
access_log off;
location /api {
api write=off;
}
location = /dashboard.html {
root /usr/share/nginx/html;
}
}
limit_req_zone $uri zone=mylimit:10m rate=10r/s;
# Custom log format to include the 'sub' claim in the REMOTE_USER field
log_format main_jwt '$remote_addr - $jwt_claim_sub [$time_local] "$request" $status '
'$body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"';
# JavaScript code for OpenID Connect
js_include conf.d/openid_connect.js;
js_set $requestid_hash hashRequestId;
auth_jwt_claim_set $jwt_audience aud; # In case aud is an array
keyval_zone zone=opaque_sessions:1M state=conf.d/opaque_sessions.json timeout=1h; # CHANGE timeout to JWT/exp validity period
keyval_zone zone=refresh_tokens:1M state=conf.d/refresh_tokens.json timeout=8h; # CHANGE timeout to refresh validity period
keyval $cookie_auth_token $session_jwt zone=opaque_sessions; # Exchange cookie for JWT
keyval $cookie_auth_token $refresh_token zone=refresh_tokens; # Exchange cookie for refresh token
keyval $request_id $new_session zone=opaque_sessions; # For initial session creation
keyval $request_id $new_refresh zone=refresh_tokens; # "
map $refresh_token $no_refresh {
"" 1; # Before login
"-" 1; # After logout
default 0;
}
# JWK Set will be fetched from $oidc_jwks_uri and cached here - ensure writable by nginx user
proxy_cache_path /var/cache/nginx/jwk levels=1 keys_zone=jwk:64k max_size=1m;
# The frontend server - reverse proxy with OpenID Connect authentication
#
resolver 8.8.8.8 valid=30s;
upstream nodejs {
server <REMOVED>:3000;
zone nodejs 64k;
}
upstream apigw {
server <REMOVED>:443 resolve;
zone apigw 64k;
}
upstream s3 {
server <REMOVED> resolve;
zone s3 64k;
}
upstream mirror {
server <REMOVED>;
zone mirror 64k;
}
server {
listen 80;
server_name <REMOVED>;
status_zone <REMOVED>m;
location / {
status_zone Unsecure_redirect;
return 302 https://$host$request_uri;
}
}
server {
listen 443 ssl http2 ;
server_name <REMOVED>; # managed by Certbot
status_zone <REMOVED>m;
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
ssl_certificate /etc/ssl/nginx/www.crt;
ssl_certificate_key /etc/ssl/nginx/www.key;
mirror /mirror;
limit_req zone=mylimit burst=20 delay=8;
location = /mirror {
internal;
proxy_pass http://mirror$request_uri;
}
location /api/mangos {
add_header 'Access-Control-Allow-Origin' '*';
proxy_set_header Host <REMOVED>;
proxy_http_version 1.1;
proxy_pass https://apigw;
status_zone mango_api;
}
location /api/articles {
status_zone article_api;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_pass http://nodejs;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location / {
status_zone unsecure;
proxy_http_version 1.1;
resolver 8.8.8.8;
proxy_set_header Host <REMOVED>;
proxy_pass http://s3;
proxy_intercept_errors on;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_hide_header x-amz-id-2;
proxy_hide_header x-amz-request-id;
}
include conf.d/openid_connect.server_conf; # Authorization code flow and Relying Party processing
# OpenID Connect Provider (IdP) configuration
resolver 8.8.8.8; # For DNS lookup of IdP endpoints;
subrequest_output_buffer_size 32k; # To fit a complete tokenset response
set $oidc_jwt_keyfile "https://login.microsoftonline.com/<REMOVED>/discovery/v2.0/keys"; # URL when using 'auth_jwt_key_request'
set $oidc_logout_redirect "/_logout"; # Where to send browser after requesting /logout location
set $oidc_authz_endpoint "https://login.microsoftonline.com/<REMOVED>/oauth2/v2.0/authorize";
set $oidc_token_endpoint "https://login.microsoftonline.com/<REMOVED>/oauth2/v2.0/token";
set $oidc_client "<REMOVED>";
set $oidc_client_secret "<REMOVED>";
set $oidc_hmac_key "<REMOVED>"; # This should be unique for every NGINX instance/cluster
location /secure/ {
status_zone secure;
proxy_http_version 1.1;
auth_jwt "" token=$session_jwt;
auth_jwt_key_request /_jwks_uri; # Enable when using URL
error_page 401 = @oidc_auth;
proxy_set_header username $jwt_claim_sub;
access_log /var/log/nginx/access.log main_jwt;
rewrite ^([^.]*[^/])$ $1/ permanent;
proxy_pass http://s3/secure/;
proxy_set_header Host citi-demo1.s3-website-us-east-1.amazonaws.com;
proxy_intercept_errors on;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_hide_header x-amz-id-2;
proxy_hide_header x-amz-request-id;
}
}
load_module modules/ngx_http_js_module.so;
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
location @oidc_auth {
if ($no_refresh) {
# No refresh token so redirect this request to the OpenID Connect identity provider login
# page for this server{} using authorization code flow (nonce sent to IdP is hash of $request_id)
add_header Set-Cookie "auth_nonce=$request_id; Path=/; HttpOnly;"; # Random value
add_header Set-Cookie "auth_redir=$request_uri; Path=/; HttpOnly;"; # So we know where to come back to
# This URL should work for most OpenID Connect providers.
# Adjust the scope or state values as required (offline_access enables refresh tokens)
return 302 "$oidc_authz_endpoint?response_type=code&scope=openid+profile+email+offline_access&client_id=$oidc_client&state=0&redirect_uri=$scheme://$host:$server_port$redir_location&nonce=$requestid_hash";
}
# We have a refresh token so perform refresh operation
js_content oidcRefreshRequest;
# Catch errors from oidcRefreshRequest()
# 500 = token validation error, 502 = error from IdP, 504 = IdP timeout
error_page 500 502 504 @oidc_error;
access_log /var/log/nginx/oidc_auth.log main;
error_log /var/log/nginx/oidc_error.log debug;
}
location = /_jwks_uri {
internal;
proxy_cache jwk; # Cache the JWK Set recieved from IdP
proxy_cache_valid 200 12h; # How long to consider keys "fresh"
proxy_cache_use_stale error timeout updating; # Use old JWK Set if cannot reach IdP
proxy_ignore_headers Cache-Control Expires Set-Cookie; # Does not influence caching
proxy_method GET; # In case client request was non-GET
proxy_pass $oidc_jwt_keyfile; # Expecting to find a URI here
}
set $redir_location "/_codexch";
location = /_codexch {
# This is where the IdP will send the authorization code after user login
js_content oidcCodeExchange; # JavaScript function to obtain JWT and issue cookie
add_header Set-Cookie "auth_token=$request_id; Path=/; HttpOnly;";
# Catch errors from oidcCodeExchange()
# 500 = token validation error, 502 = error from IdP, 504 = IdP timeout
error_page 500 502 504 @oidc_error;
access_log /var/log/nginx/oidc_auth.log main_jwt;
error_log /var/log/nginx/oidc_error.log debug;
}
location = /_token {
# This location is called by oidcCodeExchange(). We use the proxy_ directives
# to construct the OpenID Connect token request, as per:
# http://openid.net/specs/openid-connect-core-1_0.html#TokenRequest
internal;
gunzip on; # Decompress if necessary
proxy_set_header Content-Type "application/x-www-form-urlencoded";
proxy_method POST;
proxy_set_body "grant_type=authorization_code&code=$arg_code&client_id=$oidc_client&client_secret=$oidc_client_secret&redirect_uri=$scheme://$host:$server_port$redir_location";
proxy_pass $oidc_token_endpoint;
error_log /var/log/nginx/oidc_error.log debug;
}
location = /_refresh {
# This location is called by oidcRefreshRequest(). We use the proxy_ directives
# to construct the OpenID Connect token request, as per:
# https://openid.net/specs/openid-connect-core-1_0.html#RefreshingAccessToken
internal;
gunzip on; # Decompress if necessary
proxy_set_header Content-Type "application/x-www-form-urlencoded";
proxy_method POST;
proxy_set_body "grant_type=refresh_token&refresh_token=$arg_token&client_id=$oidc_client&client_secret=$oidc_client_secret";
proxy_pass $oidc_token_endpoint;
error_log /var/log/nginx/oidc_error.log debug;
}
location = /_id_token_validation {
# This location is called by oidcCodeExchange() and oidcRefreshRequest(). We use
# the auth_jwt_module to validate the OpenID Connect token response, as per:
# https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation
internal;
auth_jwt "" token=$arg_token;
js_content validateIdToken;
error_page 500 502 504 @oidc_error;
error_log /var/log/nginx/oidc_error.log debug;
}
location = /logout {
set $session_jwt -; # Clear tokens from keyval, set to - to indicate logout,
set $refresh_token -; # and so that the new value is propagated by zone_sync.
add_header Set-Cookie "auth_token=; Path=/; HttpOnly;"; # Send empty cookie
add_header Set-Cookie "auth_redir=; Path=/; HttpOnly;"; # Erase original cookie
return 302 $oidc_logout_redirect;
}
location = /_logout {
# This location is the default value of $oidc_logout_redirect (in case it wasn't configured)
default_type text/plain;
return 200 "Logged out\n";
}
location @oidc_error {
# This location is called when oidcCodeExchange() or oidcRefreshRequest() returns an error
default_type text/plain;
return 500 "NGINX / OpenID Connect login failure\n";
}
location /api/ {
api write=on;
allow 127.0.0.1; # Only the NGINX host may call the NIGNX Plus API
deny all;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment