UNPKG

@nhz.io/slush-jwt-auth-proxy-conf

Version:
203 lines (145 loc) 6.21 kB
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; } } }