@nhz.io/slush-jwt-auth-proxy-conf
Version:
CouchDB JWT Auth Proxy nginx.conf generator
203 lines (145 loc) • 6.21 kB
Plain Text
env <%= JWT_SECRET %>;
env <%= COUCH_PROXY_SECRET %>;
error_log <%= ERROR_LOG %>;
pid <%= PID_PATH %>;
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
merge_slashes on;
# Prepare jwt_token from cookie -> headers -> params
# Params have highest priority and will overwrite the rest
map $cookie_<%= JWT_COOKIE_NAME_snake_case %> $jwt_token_cookie {
default "<%= DEFAULT_JWT_TOKEN %>";
"~*(?<token>.+)" "$token";
}
map $http_<%= JWT_HEADER_NAME_snake_case %> x_jwt_auth $jwt_token_headers {
default $jwt_token_cookie;
"~*(?<token>.+)" "$token";
}
map $request $jwt_token_param {
default "";
"~*[A-Z]+ /<%= JWT_TOKEN_PREFIX %>(?<token>[-_a-zA-Z0-9]+\.[-_a-zA-Z0-9]+\.[-_a-zA-Z0-9]+)" "$token";
}
map $jwt_token_param $jwt_token {
default $jwt_token_headers;
"~*(?<token>.+)" "$token";
}
server {
<% if (HOST) { %>server_name <%= HOST %>; <% } %>
listen <%= PORT %>;
# Deny access early without token
if ($jwt_token = "") {
return 403;
}
# Init vars
set $required_roles "";
set $redirect_prefix "";
set $couch_user "";
set $couch_roles "";
set_by_lua_block $couch_token {
local jwt = require "resty.jwt"
local validators = require "resty.jwt-validators"
local sha1 = require "sha1"
local jwt_secret = os.getenv("<%= JWT_SECRET %>")
local proxy_secret = os.getenv("<%= COUCH_PROXY_SECRET %>")
local jwt_token = ngx.var.jwt_token
local jwt_obj = jwt:verify(jwt_secret, jwt_token, {
exp = validators.is_not_expired()
})
if jwt_obj.verified == false then return "" end
local jwt_token_param = ngx.var.jwt_token_param
if jwt_token_param then
ngx.var.redirect_prefix = "/<%= JWT_TOKEN_PREFIX %>" .. jwt_token_param
end
ngx.var.couch_user = jwt_obj.payload.data.user
ngx.var.couch_roles = table.concat(jwt_obj.payload.data.roles, ",")
return sha1.hmac(proxy_secret, jwt_obj.payload.data.user)
}
if ($couch_token = "") {
return 403;
}
# Strip token
location ~ ^/<%= JWT_TOKEN_PREFIX %>[^/.]+\.[^/.]+\.[^/.]+ {
rewrite ^/<%= JWT_TOKEN_PREFIX %>[^/.]+\.[^/.]+\.[^/.]+/?(.*) /$1 last;
}
<% locations.forEach(({MATCH, ROLES, REWRITE}) => { %>
location <%= MATCH %> {
set $required_roles "<%= ROLES %>";
rewrite <%= REWRITE %> last;
}
<% }) %>
location /rewrite {
internal;
rewrite_by_lua_block {
local jwt_token = ngx.var.jwt_token
local ck = require "resty.cookie"
local cookie, err = ck:new()
cookie:set({
key = "<%= JWT_COOKIE_NAME %>",
path = "/",
httponly = true,
value = jwt_token
})
local required_roles = ngx.var.required_roles
if required_roles then
function string:split(sep)
local sep, fields = sep or ":", {}
local pattern = string.format("([^%s]+)", sep)
self:gsub(pattern, function(c) fields[#fields+1] = c end)
return fields
end
function table:value_set()
local res = {}
for k, v in pairs(self) do res[v] = true end
return res
end
local pass = 0
local required_roles_set = table.value_set(string.split(required_roles, " *, *"))
local roles_set = table.value_set(string.split(ngx.var.couch_roles, " *, *"))
for k in pairs(required_roles_set) do
if roles_set[k] ~= true then
ngx.req.set_uri("/deny", true)
return
end
end
end
local uri = ngx.var.uri
local next_uri, n, err = ngx.re.sub(uri, "/rewrite(.+)", "$1")
local m, err = ngx.re.match(next_uri, ".+/_changes")
if m then
ngx.req.set_uri("/pass_no_buffer" .. next_uri, true)
else
ngx.req.set_uri("/pass" .. next_uri, true)
end
}
}
location /pass {
internal;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Auth-CouchDB-UserName $couch_user;
proxy_set_header X-Auth-CouchDB-Roles $couch_roles;
proxy_set_header X-Auth-CouchDB-Token $couch_token;
proxy_redirect ~(<%= COUCH_SCHEMA || 'http' %>://[^/:]+)(:\d+)?(/.*)$ http://$host:$server_port$redirect_prefix$3;
rewrite ^/pass/(.*) /$1 break;
proxy_pass <%= COUCH_SCHEMA || 'http' %>://<%= COUCH_HOST %><% COUCH_PORT ? `:${COUCH_PORT}` : '' %>;
}
location /pass_no_buffer {
internal;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Auth-CouchDB-UserName $couch_user;
proxy_set_header X-Auth-CouchDB-Roles $couch_roles;
proxy_set_header X-Auth-CouchDB-Token $couch_token;
proxy_redirect ~(<%= COUCH_SCHEMA || 'http' %>://[^/:]+)(:\d+)?(/.*)$ http://$host:$server_port$redirect_prefix$3;
rewrite ^/pass_no_buffer/(.*) /$1 break;
proxy_pass <%= COUCH_SCHEMA || 'http' %>://<%= COUCH_HOST %><% COUCH_PORT ? `:${COUCH_PORT}` : '' %>;
}
location /deny {
internal;
return 403;
}
}
}