In our requirements, we need to differentiate between:
a) unauthenticated users: those that have not logged in yet, or those with expired sessions: return HTTP 401, so that they are redirected to a login page
b) unauthorized users: those trying to access API endpoints or resources that, although they are authenticated, they don’t have permission for: return HTTP 403, indicating they don’t have permission (and logging in again won’t help).
I have been able to achieve this with this codebase as it stands, with the multiple calls to jwt:verify, but this seems a bit inefficient. The attached PR allows us to do the to validate two sets of claims in one call and differentiate between 401 and 403 statuses (or any other status for that matter. With these changes I'm not able to do the following:
local header = ngx.var.http_Authorization
if header then
_, _, token = string.find(header, "Bearer%s+(.+)")
else
token = nil
end
if token == nil then
ngx.status = ngx.HTTP_UNAUTHORIZED
ngx.header.content_type = "application/json; charset=utf-8"
ngx.say("{error: \"missing JWT token or Authorization header\"}")
ngx.exit(ngx.HTTP_UNAUTHORIZED)
end
local validators = require "resty.jwt-validators"
validators.set_system_leeway(15) -- time in seconds
-- Verify the token is present and valid - 401 if not
local authenticated_claims = {
exp = validators.is_not_expired()
}
-- Verify the token is authorized for this resouce - 403 if not
local authorized_claims = {
iss = validators.equals("https://accounts.google.com"),
hd = validators.equals("examplecorp.com"),
__status = ngx.HTTP_FORBIDDEN
}
local result = jwt:verify(os.getenv("JWT_SECRET"), token, authenticated_claims, authorized_claims)
if not result.verified then
ngx.status = result.status
ngx.log(ngx.WARN, result.reason)
ngx.header.content_type = "application/json; charset=utf-8"
ngx.say("{error: \"" .. result.reason .. "\"}")
ngx.exit(ngx.status)
end
In our requirements, we need to differentiate between: a) unauthenticated users: those that have not logged in yet, or those with expired sessions: return HTTP 401, so that they are redirected to a login page b) unauthorized users: those trying to access API endpoints or resources that, although they are authenticated, they don’t have permission for: return HTTP 403, indicating they don’t have permission (and logging in again won’t help). I have been able to achieve this with this codebase as it stands, with the multiple calls to jwt:verify, but this seems a bit inefficient. The attached PR allows us to do the to validate two sets of claims in one call and differentiate between 401 and 403 statuses (or any other status for that matter. With these changes I'm not able to do the following: