nginx_omniauth_adapter 0.2.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/README.md +10 -1
- data/circle.yml +35 -0
- data/example/nginx-site.conf +1 -0
- data/example/nginx.conf +3 -0
- data/lib/nginx_omniauth_adapter/app.rb +52 -5
- data/lib/nginx_omniauth_adapter/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a96ef0739bfef47af1b4a8fb09debc9c19993268
|
4
|
+
data.tar.gz: 44aabb34e2c339f88e49db0bee0d4e192b150466
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 261454c8ab6c76b725ea4eae8e14f4db6166c5d13e5aefa5f8208014c07c960b970eb941b2a916de39da700e314fedacaf17bd9ff9e13f9e4d4e722eb81be046
|
7
|
+
data.tar.gz: 02419d04c5c6a591088fe8c79834d5571bf341e47b91f9d993626b0a5e05b03f3d2349dcd5a2ae661b5758fac43d38c159904d342e204859c4306a21ec8cc7ae
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# NginxOmniauthAdapter - Use omniauth for nginx `auth_request`
|
2
2
|
|
3
|
+
[![Circle CI](https://circleci.com/gh/sorah/nginx_omniauth_adapter.svg?style=svg)](https://circleci.com/gh/sorah/nginx_omniauth_adapter)
|
4
|
+
|
3
5
|
Use [omniauth](https://github.com/intridea/omniauth) for your nginx's authentication via ngx_http_auth_request_module.
|
4
6
|
|
5
7
|
NginxOmniauthAdapter provides small Rack app (built with Sinatra) for `auth_request`.
|
@@ -40,7 +42,12 @@ Then write `config.ru` then deploy it. (see ./config.ru for example)
|
|
40
42
|
|
41
43
|
### Using docker
|
42
44
|
|
43
|
-
|
45
|
+
- Prebuilt: https://quay.io/repository/sorah/nginx_omniauth_adapter
|
46
|
+
- Own your risk.
|
47
|
+
- They're built at circleci
|
48
|
+
- Build manually: checkout this repo and run `docker build .`.
|
49
|
+
- Much safer.
|
50
|
+
- But if you can't trust upstream image `quay.io/sorah/rbenv:2.2`, write your own Dockerfile. This is just a simple Rack app.
|
44
51
|
|
45
52
|
## Configuration
|
46
53
|
|
@@ -94,6 +101,8 @@ run NginxOmniauthAdapter.app(
|
|
94
101
|
|
95
102
|
## How it works
|
96
103
|
|
104
|
+
![](http://img.sorah.jp/2015-10-08_22.55_2s4hy.png)
|
105
|
+
|
97
106
|
1. _browser_ access to restricted area (where `auth_request` has enabled)
|
98
107
|
2. _nginx_ sends subrequest to `/_auth/challenge`. It will be proxied to _adapter app_ (`GET /test`)
|
99
108
|
3. _adapter app_ `/test` returns 401 when _request (browser)_ doesn't have valid cookie
|
data/circle.yml
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
machine:
|
2
|
+
services:
|
3
|
+
- docker
|
4
|
+
ruby:
|
5
|
+
version: 2.2.3
|
6
|
+
|
7
|
+
dependencies:
|
8
|
+
cache_directories:
|
9
|
+
- bin
|
10
|
+
- ~/docker
|
11
|
+
pre:
|
12
|
+
- sudo apt-get install nginx
|
13
|
+
- if [ ! -d bin ]; then mkdir bin; fi
|
14
|
+
- if [ ! -x bin/git-set-mtime ]; then curl -o bin/git-set-mtime https://drone.io/github.com/rosylilly/git-set-mtime/files/artifacts/bin/linux_amd64/git-set-mtime && chmod +x bin/git-set-mtime; fi
|
15
|
+
- docker login -u "${DOCKER_USER}" -p "${DOCKER_PASSWORD}" -e "${DOCKER_EMAIL}" https://quay.io
|
16
|
+
- bin/git-set-mtime
|
17
|
+
- mkdir -p ~/docker
|
18
|
+
- if [[ -e ~/docker/cache.tar ]]; then docker load -i ~/docker/cache.tar; fi
|
19
|
+
- docker pull quay.io/sorah/rbenv:2.2
|
20
|
+
- BASE_ID="$(docker inspect -f '{{.Id}}' quay.io/sorah/rbenv:2.2)"; if [[ "_${BASE_ID}" != "_$(cat ~/docker/cache.id)" ]]; then docker save quay.io/sorah/rbenv:2.2 > ~/docker/cache.tar && echo "${BASE_ID}" > ~/docker/cache.id; fi
|
21
|
+
- docker pull quay.io/sorah/nginx_omniauth_adapter:latest
|
22
|
+
- docker build -t quay.io/sorah/nginx_omniauth_adapter:${CIRCLE_SHA1} .
|
23
|
+
|
24
|
+
test:
|
25
|
+
override:
|
26
|
+
- bundle exec env ADAPTER_DOCKER=quay.io/sorah/nginx_omniauth_adapter:${CIRCLE_SHA1} rspec spec/integration_spec.rb
|
27
|
+
- "echo '==== LOG ====' && cat /tmp/nginx_omniauth_helper.spec.log"
|
28
|
+
|
29
|
+
deployment:
|
30
|
+
production:
|
31
|
+
branch: master
|
32
|
+
commands:
|
33
|
+
- docker tag -f quay.io/sorah/nginx_omniauth_adapter:${CIRCLE_SHA1} quay.io/sorah/nginx_omniauth_adapter:latest
|
34
|
+
- docker push quay.io/sorah/nginx_omniauth_adapter:${CIRCLE_SHA1}
|
35
|
+
- docker push quay.io/sorah/nginx_omniauth_adapter:latest
|
data/example/nginx-site.conf
CHANGED
data/example/nginx.conf
CHANGED
@@ -3,6 +3,7 @@ require 'uri'
|
|
3
3
|
require 'time'
|
4
4
|
require 'openssl'
|
5
5
|
require 'json'
|
6
|
+
require 'securerandom'
|
6
7
|
|
7
8
|
module NginxOmniauthAdapter
|
8
9
|
class App < Sinatra::Base
|
@@ -60,13 +61,30 @@ module NginxOmniauthAdapter
|
|
60
61
|
adapter_config[:policy_proc] || proc { true }
|
61
62
|
end
|
62
63
|
|
64
|
+
def log(h={})
|
65
|
+
h = {
|
66
|
+
time: Time.now.xmlschema,
|
67
|
+
severity: :info,
|
68
|
+
logged_in: (!!current_user).inspect,
|
69
|
+
provider: current_user && current_user[:provider],
|
70
|
+
uid: current_user && current_user[:uid],
|
71
|
+
flow_id: current_flow_id,
|
72
|
+
}.merge(h)
|
73
|
+
|
74
|
+
str = h.map { |*kv| kv.join(?:) }.join(?\t)
|
75
|
+
|
76
|
+
puts str
|
77
|
+
if h[:severity] == :warning || h[:severity] == :error
|
78
|
+
$stderr.puts str
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
63
82
|
def default_back_to
|
64
83
|
# TODO:
|
65
84
|
'/'
|
66
85
|
end
|
67
86
|
|
68
87
|
def sanitized_back_to_param
|
69
|
-
p params[:back_to]
|
70
88
|
if allowed_back_to_url === params[:back_to]
|
71
89
|
params[:back_to]
|
72
90
|
else
|
@@ -75,7 +93,6 @@ module NginxOmniauthAdapter
|
|
75
93
|
end
|
76
94
|
|
77
95
|
def sanitized_app_callback_param
|
78
|
-
p params[:callback]
|
79
96
|
if allowed_app_callback_url === params[:callback]
|
80
97
|
params[:callback]
|
81
98
|
else
|
@@ -83,6 +100,14 @@ module NginxOmniauthAdapter
|
|
83
100
|
end
|
84
101
|
end
|
85
102
|
|
103
|
+
def set_flow_id!
|
104
|
+
session[:flow_id] = SecureRandom.uuid
|
105
|
+
end
|
106
|
+
|
107
|
+
def current_flow_id
|
108
|
+
session[:flow_id]
|
109
|
+
end
|
110
|
+
|
86
111
|
def current_user
|
87
112
|
session[:user]
|
88
113
|
end
|
@@ -117,6 +142,7 @@ module NginxOmniauthAdapter
|
|
117
142
|
|
118
143
|
def update_session!(auth = nil)
|
119
144
|
unless session[:app_callback]
|
145
|
+
log severity: :error, message: 'missing app_callback'
|
120
146
|
raise '[BUG] app_callback is missing'
|
121
147
|
end
|
122
148
|
|
@@ -148,7 +174,12 @@ module NginxOmniauthAdapter
|
|
148
174
|
session.merge!(adapter_session)
|
149
175
|
|
150
176
|
session_param = encrypt_session_param(app_session)
|
177
|
+
|
178
|
+
log(message: 'update_session', app_callback: session[:app_callback])
|
179
|
+
|
151
180
|
redirect "#{session.delete(:app_callback)}?session=#{session_param}"
|
181
|
+
ensure
|
182
|
+
session[:flow_id] = nil
|
152
183
|
end
|
153
184
|
|
154
185
|
def secret_key
|
@@ -212,10 +243,12 @@ module NginxOmniauthAdapter
|
|
212
243
|
|
213
244
|
get '/test' do
|
214
245
|
unless current_user
|
246
|
+
log(message: 'test_not_logged_in', original_uri: request.env['HTTP_X_NGX_OMNIAUTH_ORIGINAL_URI'])
|
215
247
|
halt 401
|
216
248
|
end
|
217
249
|
|
218
250
|
if app_authorization_expired?
|
251
|
+
log(message: 'test_app_authorization_expired', original_uri: request.env['HTTP_X_NGX_OMNIAUTH_ORIGINAL_URI'])
|
219
252
|
halt 401
|
220
253
|
end
|
221
254
|
|
@@ -238,34 +271,47 @@ module NginxOmniauthAdapter
|
|
238
271
|
callback = URI.encode_www_form_component(request.env['HTTP_X_NGX_OMNIAUTH_INITIATE_CALLBACK'])
|
239
272
|
|
240
273
|
if back_to == '' || callback == '' || back_to.nil? || callback.nil?
|
274
|
+
log(severity: :error, message: 'initiate_no_required_params', back_to: back_to, callback: callback)
|
241
275
|
halt 400, {'Content-Type' => 'text/plain'}, 'x-ngx-omniauth-initiate-back-to and x-ngx-omniauth-initiate-callback header are required'
|
242
276
|
end
|
243
277
|
|
278
|
+
log(message: 'initiate', adapter_host: adapter_host, back_to: back_to, callback: callback)
|
279
|
+
|
244
280
|
redirect "#{adapter_host}/auth?back_to=#{back_to}&callback=#{callback}"
|
245
281
|
end
|
246
282
|
|
247
283
|
get '/auth' do
|
284
|
+
set_flow_id!
|
285
|
+
|
248
286
|
# TODO: choose provider
|
249
287
|
session[:back_to] = sanitized_back_to_param
|
250
288
|
session[:app_callback] = sanitized_app_callback_param
|
251
|
-
|
289
|
+
|
290
|
+
if session[:back_to] == '' || session[:app_callback] == '' || session[:back_to].nil? || session[:app_callback].nil?
|
291
|
+
log(severity: :error, message: 'auth_invalid_params', back_to: params[:back_to], callback: params[:callback])
|
292
|
+
halt 400, {'Content-Type' => 'text/plain'}, 'back_to or/and app_callback is invalid'
|
293
|
+
end
|
252
294
|
|
253
295
|
if current_user && !adapter_authorization_expired?
|
254
|
-
|
296
|
+
log(message: 'auth_refresh_app', back_to: params[:back_to], callback: params[:callback])
|
255
297
|
update_session!
|
256
298
|
else
|
257
|
-
|
299
|
+
log(message: 'auth', provider: providers[0], back_to: params[:back_to], callback: params[:callback])
|
258
300
|
redirect "#{adapter_host}/auth/#{providers[0]}"
|
259
301
|
end
|
260
302
|
end
|
261
303
|
|
262
304
|
omniauth_callback = proc do
|
305
|
+
|
263
306
|
session[:user_data] = {}
|
264
307
|
|
265
308
|
unless instance_eval(&on_login_proc)
|
309
|
+
log(severity: :warning, message: 'omniauth_callback_forbidden', new_uid: env['omniauth.auth'][:uid])
|
266
310
|
halt 403, {'Content-Type' => 'text/plain'}, 'Forbidden (on_login_proc policy)'
|
267
311
|
end
|
268
312
|
|
313
|
+
log(message: 'omniauth_callback', new_uid: env['omniauth.auth'][:uid])
|
314
|
+
|
269
315
|
session[:logged_in_at] = Time.now.xmlschema
|
270
316
|
update_session! env['omniauth.auth']
|
271
317
|
end
|
@@ -275,6 +321,7 @@ module NginxOmniauthAdapter
|
|
275
321
|
get '/callback' do # app side
|
276
322
|
app_session = decrypt_session_param(params[:session])
|
277
323
|
session.merge!(app_session)
|
324
|
+
log(message: 'app_callback', back_to: session[:back_to])
|
278
325
|
redirect session.delete(:back_to)
|
279
326
|
end
|
280
327
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nginx_omniauth_adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shota Fukumori (sora_h)
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-10-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sinatra
|
@@ -123,6 +123,7 @@ files:
|
|
123
123
|
- LICENSE.txt
|
124
124
|
- README.md
|
125
125
|
- Rakefile
|
126
|
+
- circle.yml
|
126
127
|
- config.ru
|
127
128
|
- example/Procfile
|
128
129
|
- example/nginx-site.conf
|