Skip to content

Instantly share code, notes, and snippets.

@gerardcl
Last active February 23, 2019 18:30
Show Gist options
  • Save gerardcl/e5455da9014e46558be8a3e8c504a63a to your computer and use it in GitHub Desktop.
Save gerardcl/e5455da9014e46558be8a3e8c504a63a to your computer and use it in GitHub Desktop.
Lua Crowd HTTP Auth module
local _M = {}
function _M.run ()
-- grab auth header
local auth_header = ngx.req.get_headers().authorization
local hWWWAuth = string.format('Basic realm="%s"', os.getenv("CROWD_REALM_NAME"))
-- check that the header is present, and if not sead authenticate header
if not auth_header or auth_header == '' or not string.match(auth_header, '^[Bb]asic ') then
ngx.log(ngx.DEBUG, string.format("no auth header provided --> basic realm set to: %s", hWWWAuth))
ngx.header['WWW-Authenticate'] = hWWWAuth
ngx.header.content_type = "text/html"
ngx.status = ngx.HTTP_UNAUTHORIZED
ngx.say("UNAUTHORIZED")
ngx.exit(ngx.HTTP_UNAUTHORIZED)
end
-- decode authenication header and verify its good
local userpass = string.splitBy(ngx.decode_base64(string.splitBy(auth_header, ' ')[2]), ':')
if not userpass or #userpass ~= 2 then
ngx.log(ngx.ERR, string.format("No auth provided. Bad request."))
ngx.header['WWW-Authenticate'] = hWWWAuth
ngx.header.content_type = "text/html"
ngx.status = ngx.HTTP_UNAUTHORIZED
ngx.say("UNAUTHORIZED")
ngx.exit(ngx.HTTP_UNAUTHORIZED)
end
ngx.log(ngx.DEBUG, string.format("received auth --> %s:**** (length: %s)", userpass[1],table.getn(userpass)))
-- authenticate against crowd
local http = require("resty.http") -- dependency repo at pintsized/lua-resty-http
local httpc = http.new()
local path = string.format("/rest/usermanagement/1/authentication?username=%s", userpass[1])
local fullpath = string.format("%s%s", os.getenv("CROWD_URL"), path)
local userPass = string.format("%s:%s", os.getenv("CROWD_SERVICE"), os.getenv("CROWD_PASSWORD"))
local userPassEnc64 = ngx.encode_base64(userPass)
local authBasicHeader = string.format("Basic %s", userPassEnc64)
local payload = string.format('{"value":"%s"}', userpass[2])
ngx.log(ngx.DEBUG, string.format("crowd auth --> %s -- auth: %s", fullpath, authBasicHeader))
local res, err = httpc:request_uri(fullpath, {
method = "POST",
body = payload,
headers = {
["Authorization"] = authBasicHeader,
["Content-Type"] = "application/json",
["Accept"] = "application/json",
["Content-Length"] = payload:len(),
},
keepalive_timeout = 60,
keepalive_pool = 10
})
-- error out if not successful
if not res then
ngx.log(ngx.ERR, string.format("No response. Crowd Auth error: %s", err))
ngx.header['WWW-Authenticate'] = hWWWAuth
ngx.header.content_type = "text/html"
ngx.status = ngx.HTTP_UNAUTHORIZED
ngx.say("UNAUTHORIZED")
ngx.exit(ngx.HTTP_UNAUTHORIZED)
end
if res.status ~= 200 then
ngx.log(ngx.ERR, string.format("Crowd Auth error. HTTP status code: %s", res.status))
ngx.header['WWW-Authenticate'] = hWWWAuth
ngx.header.content_type = "text/html"
ngx.status = ngx.HTTP_UNAUTHORIZED
ngx.say("UNAUTHORIZED")
ngx.exit(ngx.HTTP_UNAUTHORIZED)
end
-- no error out, so let's proceed with the proxy
ngx.log(ngx.DEBUG, string.format("crowd res --> %s -- err: %s", res.status, err))
end
return _M
-- splitBy utils method dependency (can be added in the module or through external utils module)
function string.splitBy(pString, pPattern)
local Table = {} -- NOTE: use {n = 0} in Lua-5.0
local fpat = "(.-)" .. pPattern
local last_end = 1
local s, e, cap = pString:find(fpat, 1)
while s do
if s ~= 1 or cap ~= "" then
table.insert(Table,cap)
end
last_end = e + 1
s, e, cap = pString:find(fpat, last_end)
end
if last_end <= #pString then
cap = pString:sub(last_end)
table.insert(Table, cap)
end
return Table
end
- implementation running with OpenResty 1.13.6.x
- to load the environment variables inside nginx. Before http->
env CROWD_REALM_NAME;
env CROWD_URL;
env CROWD_SERVICE;
env CROWD_PASSWORD;
- to load under http block the Lua required config params in order to assure SSL connections are working. Under http->
lua_ssl_verify_depth 2;
lua_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt; # it might change depending on the OS/Distro
- to define on access state the auth-crowd module. Under http->server->location->
access_by_lua_block {
require("auth-crowd").run()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment