Skip to content

Instantly share code, notes, and snippets.

@mariocesar
Last active November 5, 2023 07:16
Show Gist options
  • Save mariocesar/cdb9fdc6f95a1993e218 to your computer and use it in GitHub Desktop.
Save mariocesar/cdb9fdc6f95a1993e218 to your computer and use it in GitHub Desktop.
Nginx Lua script redis based for Basic user authentication
function password_encode(password)
local bcrypt = require 'bcrypt'
return bcrypt.digest(password, 12)
end
function check_password(password, encoded_password)
local bcrypt = require 'bcrypt'
return bcrypt.verify(password, encoded_password)
end
function get_user(username)
--- Defaults
local access_redis_host = ngx.var.access_redis_host == ''
and '127.0.0.1' or ngx.var.access_redis_host
local access_redis_port = ngx.var.access_redis_port == ''
and 6379 or ngx.var.access_redis_port
local access_user_catalogue = ngx.var.access_user_catalogue == ''
and 'nginx_catalogue:users' or ngx.var.access_user_catalogue
---
local redis = require "nginx.redis"
local red = redis:new()
red:set_timeout(1000)
local ok, err = red:connect(access_redis_host, access_redis_port)
if not ok then
ngx.log(ngx.ERR, "failed to connect to the redis server: ", err)
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
return
end
local res, err = red:hget(access_user_catalogue, username)
if not res then
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
return
end
-- User is not found
if res == ngx.null then
return
end
return res
end
function authenticate()
-- Test Authentication header is set and with a value
local header = ngx.req.get_headers()['Authorization']
if header == nil or header:find(" ") == nil then
return false
end
local divider = header:find(' ')
if header:sub(0, divider-1) ~= 'Basic' then
return false
end
local auth = ngx.decode_base64(header:sub(divider+1))
if auth == nil or auth:find(':') == nil then
return false
end
divider = auth:find(':')
local username = auth:sub(0, divider-1)
local password = auth:sub(divider+1)
local res = get_user(username)
if res == nil then
return false
end
if check_password(password, res) then
return true
end
return false
end
local user = authenticate()
if not user then
ngx.header.content_type = 'text/plain'
ngx.header.www_authenticate = 'Basic realm=""'
ngx.status = ngx.HTTP_UNAUTHORIZED
ngx.say('401 Access Denied')
end
server {
listen 80;
server_name _;
root /var/www/html;
location / {
set $access_redis_host '127.0.0.1';
set $access_redis_port 6379;
set $access_user_catalogue 'myapp:users';
access_by_lua_file access.lua;
}
}
@lcp580
Copy link

lcp580 commented Feb 22, 2016

thank you

@bwalia
Copy link

bwalia commented Feb 22, 2017

Thanks for the awesome code, we require http auth and on our server (ubuntu) we do not seem to have bcrypt enabled. How do I get bcrypt require working? What steps do we take to enable bcrypt?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment