Just to clarify, this won't be a detailed technical guide about how you can build your own authentication layer using OpenResty + Lua, rather it is a document explaining the process behind the solution.

This is a real example of how moltin's API has come to rely on OpenResty + Lua to handle our oauth2 authentication for all users.

The logic used to authenticate a user was originally embedded into moltin's API, built using the PHP Framework Laravel. This means a lot of code had to be booted before we could authenticate, reject or validate a user request resulting in a high latency.

I'm not going to give details about how much time a PHP Framework could take to give a basic response, but if we compare it to other languages/frameworks, you can probably understand.

So we decided to move all logic one layer up to OpenResty + Lua which achieved the following:

Decoupled responsibilities from our Monolitic API.

Improved authentication times and generated access/refresh tokens.

Improved times for rejecting invalid access tokens or authentication credentials.

Improved times when validating an access token and redirecting the request to the API.

We wanted, and needed, to have more control on each request before hitting the actual API and so we decided to use something fast enough to allow us to pre-process each request and flexible enough to be integrated into our actual system. Doing this led us to use OpenResty, a modified version of Nginx, that allowed us to use Lua, the language used to pre-process those requests. Why? Because it's robust and fast enough to use for these purposes and it's a highly recognised scripting language used daily by many large companies.

We followed the concept behind Kong, who use OpenResty + Lua, to offer several micro-services that could be plugged into your API project. However we found that Kong is in a very early stage and is actually trying to offer more than what we needed therefore we decided to implement our own Auth layer to allow us to have more control over it.

Lua Scripts

This is where all the magic happens. We have two scripts to do this:

get_oauth_access.lua

...
ngx.req.read_body()
args, err = ngx.req.get_post_args()
-- If we don't get any post data fail with a bad request
if not args then
return api:respondBadRequest()
end
-- Check the grant type and pass off to the correct function
-- Or fail with a bad request
for key, val in pairs(args) do
if key == "grant_type" then
if val == "client_credentials" then
ClientCredentials.new(args)
elseif val == "password" then
Password.new(args)
elseif val == "implicit" then
Implicit.new(args)
elseif val == "refresh_token" then
RefreshToken.new(args)
else
return api:respondForbidden()
end
end
end
return api:respondOk()
...

check_oauth_access.lua

...
local authorization, err = ngx.req.get_headers()["authorization"]
-- If we have no access token forbid the beasts
if not authorization then
return api:respondUnauthorized()
end
-- Check for the access token
local result = oauth2.getStoredAccessToken(token)
if result == false then
return api:respondUnauthorized()
end
...

Caching Layer

This is where the created access tokens are stored. We can remove, expire or refresh them as we please. We use Redis as a storage layer and we use openresty/lua-resty-redis to connect Lua to Redis.

Resources

Here are some interesting resources on Lua that we used when creating our authentication layer.

Why use Lua in web development

Lua is an easy and elegant programming language that is recorded as the fastest interpreted language on many benchmarks and proven success in other domains of development such as games and embedded systems.
It has good language semantics, awesome documentation, it is very readable and has very powerful mechanisms such as metatables, proper tail calls and many other features that are worth taking a look.
It's a great technical candidate for being a PHP replacement. Lua is being used in production for web development for a long time with success by websites such as TaoBao,
a chinese online shopping website that ranks 11 globally on Alexa with over 760 million product listings, Cloudflare,
Rackspace, itch.io, mail.ru,
Mashape/Kong,
Shopify and others.
Wikipedia uses Lua for its template system.
This blog itself is also running on Lua.

A common complaint of using Lua, though, is the ecosystem, which is exactly why PHP is so popular.
PHP is pervasive and there are many tools and tutorials written for it, so the development becomes easy also for reasons that are not technical, specially due to a large & friendly community.

However, the landscape for Lua is changing and now the ecosystem is growing rapidly (a feat I partially attritube to the merge of LuaRocks and MoonRocks).
We have been able to write in Lua for the web for years and now we can find a large number of tools available.
You can write in Lua for major webservers such as Apache and Nginx/OpenResty (top 2 web servers used), and also others such as Lighttpd and pure Lua stand-alone servers like Xavante or Pegasus.
Highlights go to Nginx server, which allows to develop blazing fast non-blocking asynchronous apps written in a sequential fashion keeping the event-driven logic hidden inside Nginx (no callback hell).

There are also many frameworks available, which this post aims to compare. I am myself the lead developer of one of them (Sailor) and I haven't developed using all the options I'm listing, but I hope this is a fairly decent comparison.
You can make a pull request to this article to make it better.

Something important to note, there is one advantage that is not listed because it applies to all of them, which is the good performance and small footprint. This is even more enhanced on tools that support LuaJIT.

Extra

Lua Templates is a multi-purpose templating engine used to create output in
various formats, e.g. HTML pages, plain text, or, LaTeX source files.
Lua Templates can contain Lua code or Lua expressions (whence the name), but
there is also a powerful mechanism to extend existing templates by re-defining
named blocks found in the base template (one could call this an "inheritance"
mechanism.)

(Lua Templates have been used by my company micro systems
as part of the arcapos solution for applications like
online ticket sales, backoffice, accounting, CRM etc, serving thousands of
users.)

As we are currently in the process of open-sourcing Lua Templates, this first
blog post should explain how Lua Templates work. Once the code is published
on github.com/mbalmer/, another blog post
will explain (some) technical details of the implementation.

How Lua Templates work

Lua Templates are first converted to Lua code when they are parsed for the
first time and then executed, which generates the output, optionally escaping
the output it for the target format. On subsequent calls of the same template,
the already compiled Lua code is executed directly to render the template.
This way, templates are rendered very fast an we achieve
high transaction rates e.g. for web applications.

For security reasons, the Lua code generated from a template is executed
in a separate container, either a separate Lua state or a sandbox. The
normal operation mode is to provide the values that the template expects to
the separate container and then call the Lua function that corresponds
to the template being rendered.

The conversion from Lua Templates to Lua code is done in a Lua Templates
specific reader function
that is passed to a lua_load() call. This function is written in the C
language.

Template syntax

Lua Templates are textfiles in any encoding, containing markup in
<% ... %> brackets. When rendering a template, the following
principles apply:

Regular text, i.e. text not containing any markup, is output as is.

Text in <% ... %> brackets is interpreted as Lua code and
executed when the template is rendered. There is normally no output.

Text in <%= ...%> brackets is interpreted as a Lua expression
and the result of the expression is inserted in the output. After the
equal sign, an optional format specifier conforming to string.format()
format specifiers can be added, e.g. to create output with fixed
width.

Text in <%=*escaping* ... %> brackets is interpreted as a Lua
expression and the result of the expression is escaped according to
escaping and then inserted in the output. For possible values of
escaping, see the list below.

Text in <%! ... %> brackets is interpreted as a Lua Template command
The following commands are currently defined:

blockname. Define a named block.

endblock. End a block definition.

escape. Define the standard escaping for <%= ... %>
expressions.
The following escapings are defined:

html. Escape the output as HTML code.

xml. Escape the output as XML code .

latex. Escape the output as LaTeX code.

none. Don't escape the output.

url. Escape the output as a URL.

extendsname. Indicate that this template extends the template name.
The contents of blocks defined in this template with
<%! blockname%> ... <%! endblock %> will replace
the corresponding blocks in the template that is being extended.
Important: The extends command must be the first command in a
template. There is no need to re-define all blocks in the base template,
only those that are to be modified (e.g. a page title and the contents, but
not the page header and footer). Multi-level extension of templates is
possible (and usually makes sense).

includename. Insert a template in the output.

The name argument of the block, extends, and, include command
can be put in single or double quotes or no quotes at all.

In Lua code, the function lt.out() can be used to output arbitrary data.
lt.out() expects a single string as argument.