lua-resty-openidc is a library for NGINX implementing the [OpenID Connect] (http://openid.net/specs/openid-connect-core-1_0.html) Relying Party (RP) and the OAuth 2.0 Resource Server (RS) functionality.
When used as an OpenID Connect Relying Party it authenticates users against an OpenID Connect Provider using OpenID Connect Discovery and the Basic Client Profile (i.e. the Authorization Code flow). When used as an OAuth 2.0 Resource Server it can validate OAuth 2.0 Bearer Access Tokens against an Authorization Server.
It maintains sessions for authenticated users by leveraging lua-resty-session
thus offering
a configurable choice between storing the session state in a client-side browser cookie or use
in of the server-side storage mechanisms shared-memory|memcache|redis
.
It supports server-wide caching of resolved Discovery documents and validated Access Tokens.
lua-resty-openidc depends on the following packages:
The dependencies above come automatically with OpenResty. You will need to install two extra pure-Lua dependencies that implement session management and HTTP client functions:
Copy openidc.lua
somewhere in your lua_package_path
under a directory named resty
.
If you are using OpenResty, the default location would be /usr/local/openresty/lualib/resty
.
Sample nginx.conf
configuration for authenticating users against Google+ Signin, protecting a reverse-proxied path.
events {
worker_connections 128;
}
http {
lua_package_path '~/lua/?.lua;;';
resolver 8.8.8.8;
lua_ssl_trusted_certificate /opt/local/etc/openssl/cert.pem;
lua_ssl_verify_depth 5;
# cache for discovery metadata documents
lua_shared_dict discovery 1m;
server {
listen 8080;
location / {
access_by_lua '
local opts = {
-- the full redirect URI must be protected by this script and becomes:
-- ngx.var.scheme.."://"..ngx.var.http_host..opts.redirect_uri_path
-- unless the scheme is overridden using opts.redirect_uri_scheme or an X-Forwarded-Proto header in the incoming request
redirect_uri_path = "/redirect_uri",
discovery = "https://accounts.google.com/.well-known/openid-configuration",
client_id = "<client_id",
client_secret = "<client_secret"
--authorization_params = { hd="pingidentity.com" },
--scope = "openid email profile",
--iat_slack = 600,
--redirect_uri_scheme = "https",
--logout_path = "/logout",
--ssl_verify = "no"
}
-- 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
-- at this point res is a Lua table with 3 keys:
-- id_token : a Lua table with the claims from the id_token (required)
-- access_token: the access token (optional)
-- user : a Lua table with the claims returned from the user info endpoint (optional)
--if res.id_token.hd ~= "pingidentity.com" then
-- ngx.exit(ngx.HTTP_FORBIDDEN)
--end
--if res.user.email ~= "[email protected]" then
-- ngx.exit(ngx.HTTP_FORBIDDEN)
--end
-- set headers with user info (overwriting any existing!)
ngx.req.set_header("X-USER", res.id_token.sub)
';
proxy_pass http://localhost:80;
}
}
}
Sample nginx.conf
configuration for validating Bearer Access Tokens against a PingFederate OAuth 2.0 Authorization Server.
events {
worker_connections 128;
}
http {
lua_package_path '~/lua/?.lua;;';
resolver 8.8.8.8;
lua_ssl_trusted_certificate /opt/local/etc/openssl/cert.pem;
lua_ssl_verify_depth 5;
# cache for validation results
lua_shared_dict introspection 10m;
server {
listen 8080;
location /api {
access_by_lua '
local opts = {
introspection_endpoint="https://localhost:9031/as/token.oauth2",
introspection_token_param_name="token",
introspection_params = {
grant_type="urn:pingidentity.com:oauth2:grant_type:validate_bearer",
},
client_id="rs_client",
client_secret="2Federate",
ssl_verify = "no"
}
-- call introspect for OAuth 2.0 Bearer Access Token validation
local res, err = require("resty.openidc").introspect(opts)
if err then
ngx.status = 403
ngx.say(err)
ngx.exit(ngx.HTTP_FORBIDDEN)
end
-- at this point res is a Lua table that represents the JSON
-- object returned from the introspection/validation endpoint
--if res.scope ~= "edit" then
-- ngx.exit(ngx.HTTP_FORBIDDEN)
--end
--if res.client_id ~= "ro_client" then
-- ngx.exit(ngx.HTTP_FORBIDDEN)
--end
';
}
}
}
This software is open sourced by Ping Identity but not supported commercially as such. Any questions/issues should go to the Github issues tracker or the author [email protected] directly See also the DISCLAIMER file in this directory.