Using the lua-resty-openidc Nginx Library as a Relying Party With Gluu Server#
As a brief explanation, we will have two servers. One is the Identity Provider(IDP), the Gluu Server; the other is the Relying Party(RP), the Nginx OpenResty server with the lua-resty-openidc library. The lua-resty-openidc Nginx library uses the OpenID Connect Authorization Code Flow. Upon the user giving consent, the RP will gather user information from the IDP and if the user is authorized, forward the user to a redirect URI.
Requirements:
- Gluu Server (Installation Instructions)
- OpenResty 1.11.2.5
- gcc
- libpcre3 libpcre3-dev
- libssl-dev
- lua5.2
- lua-resty-http
- lua-resty-session
- lua-resty-jwt
Installing OpenResty#
First, you'll need to install a few dependencies for lua-resty-openidc. The dependencies list is, for the most part, covered by OpenResty
. As of writing this (5 June 2018) there is an API conflict with OpenResty 1.13.6's OpenSSL 1.1.0
implementation and lua-resty-jwt
which used OpenSSL 1.0.2
. So, we must build OpenResty 1.11.2.5, as this includes OpenSSL 1.0.2
.
apt update
apt-get install gcc libssl-dev libpcre3 libpcre3-dev
wget https://openresty.org/download/openresty-1.11.2.5.tar.gz
tar -xvf openresty-1.11.2.5.tar.gz
cd openresty-1.11.2.5
./configure -j2
make -j2
sudo make install
Then we can add the OpenResty bin to PATH:
export PATH=/usr/local/openresty/bin:$PATH
After that, we can download the lua-resty dependencies with OPM (OpenResty Package Manager):
opm install bungle/lua-resty-session
opm install SkyLothar/lua-resty-jwt
opm install pintsized/lua-resty-http
opm install zmartzone/lua-resty-openidc
Configuring a Gluu Server OpenID Connect Client#
At this point, we need to register an OpenID Connect client, lua-resty-openidc, in Gluu Server. We also need to configure Nginx with lua-resty-openidc to use Gluu Server as its Identity Provider.
Navigate to your Gluu Server, and click OpenID Connect
-> Clients
.
Here, we want to click the Add Client
button on the top.
Now, name the client anything you want. I chose lua-resty-openidc for convenience, but this is only for human recognition. The Client Description
can be more thorough to describe the purpose of the client. Client Secret
can be anything you want it to be. You can increase the entropy and difficulty of your secret by running this in a terminal:
gpg --gen-random --armor 1 30
And using it as your secret. Make sure to store this somewhere, as it won't be retrievable in the Identity UI.
Moving forward, we can skip a lot of configuration examples for the sake of simplicity in this tutorial and jump down to the bottom, where we will Add Login Redirect URI
, Add Scope
, Add Response Type
and Add Grant Type
. For our example, our Redirect Login URI
will be:
https://$HOSTNAME/welcome
Now, click Add Scope
and Search
to display all scope options. Check email
, openid
and profile
.
Next, click Add Response Type
and check code
and id_token
.
Click Add Grant Type
and check authorization_code
.
For our simple example, this is enough, and we can click the Add
button at the bottom of the page. Once we've done this, we can gather our inum from the OpenID Connect/Clients
dashboard next to the Display Name of the client we created. We will need this later for the lua-resty-openidc Nginx configuration's client_id
.
Configuring OpenResty's Nginx#
Now, on our Relying Party Server (Not the Gluu Server), let's create some SSL certificates and then use those in our Nginx configuration.
mkdir -p /usr/local/openresty/nginx/ssl/
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /usr/local/openresty/nginx/ssl/nginx.key -out /usr/local/openresty/nginx/ssl/nginx.crt
Fill out the prompts for your certificates. We'll use them in the following Nginx configuration.
Now, we can finally make our configuration in OpenResty's Nginx. This nginx.conf can be found at /usr/local/openresty/nginx/conf/nginx.conf
. Replace $INUM
and $SECRET
with the inum and client secret from the OpenID client we just created in Gluu Server. Replace ${GLUU_SERVER}
with the hostname of your Gluu Server.
events {
worker_connections 1024;
}
http {
lua_package_path "/usr/local/openresty/?.lua;;";
resolver 8.8.8.8;
lua_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
lua_ssl_verify_depth 5;
# cache for discovery metadata documents
lua_shared_dict discovery 1m;
# cache for JWKs
lua_shared_dict jwks 1m;
server {
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
ssl_certificate /usr/local/openresty/nginx/ssl/nginx.crt;
ssl_certificate_key /usr/local/openresty/nginx/ssl/nginx.key;
location / {
access_by_lua_block {
local opts = {
redirect_uri_path = "/welcome",
discovery = "https://${GLUU_SERVER}/.well-known/openid-configuration",
client_id = "$INUM",
client_secret = "$SECRET",
ssl_verify = "no",
scope = "openid email profile",
redirect_uri_scheme = "https",
}
-- call authenticate for OpenID Connect user authentication
local res, err = require("resty.openidc").authenticate(opts)
if err then
ngx.status = 500
ngx.say(err)
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
ngx.req.set_header("X-USER", res.id_token.sub)
}
}
}
}
After we've saved this configuration file, let's run the openresty
command we added to our path.
Now navigate to the RP, which will redirect you to your IDP, where you can log in, authorize the RP to gather information and be directed back to the OpenResty default index.html
, which is located at /usr/local/openresty/nginx/html/index.html
.
Of course, this is a limited and simplified proof of concept. Further customization and optionality can be added. Please refer to the official documentation for the lua-resty-openidc
library to add more extensibility for your use case. There are a multitude of examples on the main README.md. Also, check out the Gluu Server OpenID Connect API documentation for help with ~1:1 configuration settings that need to be set to match the libary.