local jwt = require "resty.jwt" local cjson = require "cjson" local basexx = require "basexx" local secret = os.getenv("JWT_SECRET") assert(secret ~= nil, "Environment variable JWT_SECRET not set") if os.getenv("JWT_SECRET_IS_BASE64_ENCODED") == 'true' then -- convert from URL-safe Base64 to Base64 local r = #secret % 4 if r == 2 then secret = secret .. "==" elseif r == 3 then secret = secret .. "=" end secret = string.gsub(secret, "-", "+") secret = string.gsub(secret, "_", "/") -- convert from Base64 to UTF-8 string secret = basexx.from_base64(secret) end local M = {} function M.auth(claim_specs) -- strip our headers to avoid spoofing ngx.req.clear_header("User-Id") ngx.req.clear_header("Scopes") ngx.req.clear_header("JWT-Scope") ngx.req.clear_header("JWT-Issuer") ngx.req.clear_header("JWT-Subject") ngx.req.clear_header("JWT-Expiration-Time") ngx.req.clear_header("JWT-Not-Before") ngx.req.clear_header("JWT-Issued-At") -- require Authorization request header local auth_header = ngx.var.http_Authorization if auth_header == nil then ngx.log(ngx.INFO, "No Authorization header") -- ngx.exit(ngx.HTTP_UNAUTHORIZED) return else ngx.log(ngx.INFO, "Authorization: " .. auth_header) -- require Bearer token local _, _, token = string.find(auth_header, "Bearer%s+(.+)") if token == nil then ngx.log(ngx.INFO, "Missing token") -- ngx.exit(ngx.HTTP_UNAUTHORIZED) return else ngx.log(ngx.INFO, "Token: " .. token) -- require valid JWT local jwt_obj = jwt:verify(secret, token, 60) if jwt_obj.verified == false then if string.find(jwt_obj.reason, "expired at") ~= nil then ngx.status = ngx.HTTP_UNAUTHORIZED ngx.say('{"error": "access_denied", "header": "authorization"}') return ngx.exit(ngx.HTTP_UNAUTHORIZED) else ngx.log(ngx.WARN, "Invalid token: ".. jwt_obj.reason) -- ngx.exit(ngx.HTTP_UNAUTHORIZED) end return else ngx.log(ngx.INFO, "JWT: " .. cjson.encode(jwt_obj)) -- write the headers ngx.req.set_header("User-Id", jwt_obj.payload.sub) ngx.req.set_header("Scopes", jwt_obj.payload.scope) ngx.req.set_header("JWT-Scope", jwt_obj.payload.scope) ngx.req.set_header("JWT-Issuer", jwt_obj.payload.iss) ngx.req.set_header("JWT-Subject", jwt_obj.payload.sub) ngx.req.set_header("JWT-Expiration-Time", jwt_obj.payload.exp) ngx.req.set_header("JWT-Not-Before", jwt_obj.payload.nbf) ngx.req.set_header("JWT-Issued-At", jwt_obj.payload.iat) return end end end end return M