Search code examples
nginxluaauthorizationbasic-authentication

NGINX Lua Basic HTTP Authorization/Authentication Allow Certain Number of Attempts


I'm trying to use a Lua script I found on this Git Repository: https://github.com/knq/nginx-crowd-lua/blob/master/crowd-auth.lua to authorize users to restricted content against an Atlassian Crowd user management system.

What happens when I use this script as is is that if a user enters in an incorrect username/password, then the browser returns a 403 Forbidden response, without allowing the user to try again unless the user closes the browser and goes back to the page.

What I'm trying to do is allow 3 attempts to log in before the 403 page is displayed.

I've tried looping this script, but either the loop doesn't work, and an incorrect user/pass goes straight to the 403 page on the first attempt, or the loop is infinite, allowing unlimited attempts.

Could someone please advise on this? If you need more detail please comment and I'll provide.

Thanks


Solution

  • I figured it out. For those who are also interested in this, I've posted the solution:

    The ngx.header['WWW-Authenticate'] command stops the script and sends a new request. No type of variable, be it in NGINX or Lua, can hold it's value across requests. What you CAN do, is set a cookie that holds that max auth attempts, like this:

    local auth_tries = ngx.var.cookie_AuthAttempts
    
    if not auth_tries then
      auth_tries = 1
    end
    
    if type(auth_tries) == "string" then
      auth_tries = tonumber(auth_tries)
    end
    

    Then set the counter at the end of the loop, and set the cookie to its value:

    auth_header = nil
    auth_tries = auth_tries + 1
    
    ngx.header['Set-Cookie'] = "AuthAttempts="..auth_tries.."; Path=/; Expires="..ngx.cookie_time(ngx.time() + 3600*24)
    

    Then, if the max failed attempts have been reached, clean up, and send the 401 response:

    ngx.header['Set-Cookie'] = "AuthAttempts=0; Path=/; Expires="..ngx.cookie_time(ngx.time() + 3600*24)
    
    if res ~= nil then
    if res.status ~= 200 then
      ngx.exit(ngx.HTTP_FORBIDDEN)
    end
    else
      ngx.exit(ngx.HTTP_FORBIDDEN)
    end