- 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) |
# 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; | |
} | |
} | |
} |
![]() |
2
orzfly 2014-06-13 16:11:49 +08:00
早就部署上了哈哈哈哈……
配合 GitLab 上用 Doorkeeper gem 做了一个 OAuth Provider,然后把服务器上一些资源就直接用 OAuth 登陆了,登陆之后可以通过 GitLab 的权限系统做访问控制~ |
![]() |
3
orzfly 2014-06-13 16:12:36 +08:00
|
![]() |
4
LazyZhu 2014-06-13 16:45:35 +08:00
配合js做后端前移
|
![]() |
5
sobigfish 2014-06-13 18:48:13 +08:00
单APP_ID和APP_SECRET,
不知道能不能配合mongodb做真正的server |
![]() |
6
hourui 2014-06-13 18:52:17 +08:00
lua配合上一些nginx插件, 简单需求基本上nginx就能hold全场了
|