-
-
Save honewatson/5cdc1c2670053c13c339c37f0b1dd715 to your computer and use it in GitHub Desktop.
Simple lua file enabling oauth support for nginx via nginx-lua and access_by_lua.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- certain endpoints are always blocked | |
if nginx_uri == "/_access_token" or nginx_uri == "/_me" then | |
ngx.exit(403) | |
end | |
-- 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) | |
end | |
local access_token = ngx.var.cookie_SGAccessToken | |
if access_token then | |
ngx.header["Set-Cookie"] = "SGAccessToken="..access_token.."; path=/;Max-Age=3000" | |
end | |
-- 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 | |
ngx.say(res.body) | |
ngx.exit(ngx.HTTP_OK) | |
end | |
-- decode the token | |
local text = res.body | |
local json = cjson.decode(text) | |
access_token = json.access_token | |
end | |
-- 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") | |
end | |
end | |
-- 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("https://seatgeek.com/oauth?client_id="..app_id.."&scope=all") | |
end | |
-- Disallow access | |
ngx.status = res.status | |
ngx.say("{"status": 503, "message": "Error accessing api/me for credentials"}") | |
return ngx.exit(ngx.HTTP_OK) | |
end | |
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) | |
end | |
-- 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) | |
end | |
-- Set some headers for use within the protected endpoint | |
ngx.req.set_header("X-USER-ACCESS-LEVEL", json.access_level) | |
ngx.req.set_header("X-USER-EMAIL", json.email) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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; | |
server_name private.example.com; | |
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; | |
break; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment