Skip to content

Instantly share code, notes, and snippets.

Created December 3, 2012 18:26
Show Gist options
  • Save josegonzalez/4196901 to your computer and use it in GitHub Desktop.
Save josegonzalez/4196901 to your computer and use it in GitHub Desktop.
Simple lua file enabling oauth support for nginx via nginx-lua and access_by_lua.
- certain endpoints are always blocked
if nginx_uri == "/_access_token" or nginx_uri == "/_me" then
-- import requirements
local cjson = require "cjson"
-- setup some app-level vars
local app_id = "APP_ID"
local app_secret = "APP_SECRET"
local args = ngx.req.get_uri_args()
if args.error and args.error == "access_denied" then
ngx.status = ngx.HTTP_UNAUTHORIZED
ngx.say("{"status": 401, "message": ""..args.error_description..""}")
return ngx.exit(ngx.HTTP_OK)
local access_token = ngx.var.cookie_SGAccessToken
if access_token then
ngx.header["Set-Cookie"] = "SGAccessToken="..access_token.."; path=/;Max-Age=3000"
-- first lets check for a code where we retrieve
-- credentials from the api
if not access_token or args.code then
if args.code then
-- internal-oauth:1337/access_token
local res = ngx.location.capture("/_access_token?client_id="..app_id.."&client_secret="..app_secret.."&code="..args.code)
-- kill all invalid responses immediately
if res.status ~= 200 then
ngx.status = res.status
-- decode the token
local text = res.body
local json = cjson.decode(text)
access_token = json.access_token
-- both the cookie and proxy_pass token retrieval failed
if not access_token then
-- Track the endpoint they wanted access to so we can transparently redirect them back
ngx.header["Set-Cookie"] = "SGRedirectBack="..nginx_uri.."; path=/;Max-Age=120"
-- Redirect to the /oauth endpoint, request access to ALL scopes
return ngx.redirect("internal-oauth:1337/oauth?client_id="..app_id.."&scope=all")
-- ensure we have a user with the proper access app-level
-- internal-oauth:1337/accessible
local res = ngx.location.capture("/_accessible", {args = { access_token = access_token } } )
if res.status ~= 200 then
-- delete their bad token
ngx.header["Set-Cookie"] = "SGAccessToken=deleted; path=/; Expires=Thu, 01-Jan-1970 00:00:01 GMT"
-- Redirect 403 forbidden back to the oauth endpoint, as their stored token was somehow bad
if res.status == 403 then
return ngx.redirect(""..app_id.."&scope=all")
-- Disallow access
ngx.status = res.status
ngx.say("{"status": 503, "message": "Error accessing api/me for credentials"}")
return ngx.exit(ngx.HTTP_OK)
local json = cjson.decode(res.body)
-- Ensure we have the minimum for access_level to this resource
if json.access_level < 255 then
-- Expire their stored token
ngx.header["Set-Cookie"] = "SGAccessToken=deleted; path=/; Expires=Thu, 01-Jan-1970 00:00:01 GMT"
-- Disallow access
ngx.status = ngx.HTTP_UNAUTHORIZED
ngx.say("{"status": 403, "message": "USER_ID"..json.user_id.." has no access to this resource"}")
return ngx.exit(ngx.HTTP_OK)
-- Store the access_token within a cookie
ngx.header["Set-Cookie"] = "SGAccessToken="..access_token.."; path=/;Max-Age=3000"
-- Support redirection back to your request if necessary
local redirect_back = ngx.var.cookie_SGRedirectBack
if redirect_back then
ngx.header["Set-Cookie"] = "SGRedirectBack=deleted; path=/; Expires=Thu, 01-Jan-1970 00:00:01 GMT"
return ngx.redirect(redirect_back)
-- Set some headers for use within the protected endpoint
ngx.req.set_header("X-USER-ACCESS-LEVEL", json.access_level)
# The app we are proxying to
upstream production-app {
server localhost:8080;
# The internal oauth provider
upstream internal-oauth {
server localhost:1337;
server {
listen 80;
root /apps;
charset utf-8;
# This will run for everything but subrequests
access_by_lua_file "/etc/nginx/access.lua";
# Used in a subrequest
location /_access_token { proxy_pass http://internal-oauth/oauth/access_token; }
location /_user { proxy_pass http://internal-oauth/user; }
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_max_temp_file_size 0;
if (!-f $request_filename) {
proxy_pass http://production-app;
Copy link

Do we have similar lua for nginx acts as OAuth client? Something like oauth2_proxy can be used with google. But we want to do OAuth with salesforce. Do you have any idea?

Copy link

jirutka commented Dec 4, 2015

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