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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: da45545a31a51031b94607551c7296f3011c3769
4
- data.tar.gz: 79f17b771dffb86ff9527b78a7fbbe14d1a71bf1
3
+ metadata.gz: a96ef0739bfef47af1b4a8fb09debc9c19993268
4
+ data.tar.gz: 44aabb34e2c339f88e49db0bee0d4e192b150466
5
5
  SHA512:
6
- metadata.gz: 84be2b3d973d457a98b52ba75498b3dd84557012dd8fc9ddadeb5e2873fd9a80efb146f2177024214eadbaf1524814869f250c5ce972fce3e5bad3f61aad7714
7
- data.tar.gz: 432c64e9ec6b1953947d6a8ed72e6c4eb019db5cf984cd62de39361c4d594ca7800be2686f25caae168c9b14f5ec24ccf8ae58ff951916ab049129a613687a6d
6
+ metadata.gz: 261454c8ab6c76b725ea4eae8e14f4db6166c5d13e5aefa5f8208014c07c960b970eb941b2a916de39da700e314fedacaf17bd9ff9e13f9e4d4e722eb81be046
7
+ data.tar.gz: 02419d04c5c6a591088fe8c79834d5571bf341e47b91f9d993626b0a5e05b03f3d2349dcd5a2ae661b5758fac43d38c159904d342e204859c4306a21ec8cc7ae
data/Gemfile CHANGED
@@ -5,3 +5,5 @@ gemspec
5
5
 
6
6
  gem 'omniauth-github'
7
7
  gem 'omniauth-google-oauth2'
8
+
9
+ gem 'unicorn'
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
- TBD
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
@@ -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
@@ -26,6 +26,7 @@ server {
26
26
  location / {
27
27
  auth_request /_auth/challenge;
28
28
  # Trick - do internal redirection when auth_request says "need auth".
29
+ proxy_intercept_errors off;
29
30
  error_page 401 = /_auth/initiate;
30
31
 
31
32
  # Receive user info from adapter
@@ -1,6 +1,7 @@
1
1
  # vim: ft=nginx
2
2
  worker_processes 1;
3
3
  daemon off;
4
+ pid /tmp/nginx_omniauth_adapter-nginx.pid;
4
5
 
5
6
  error_log stderr;
6
7
 
@@ -13,5 +14,7 @@ http {
13
14
 
14
15
  server_names_hash_bucket_size 128;
15
16
 
17
+ access_log off;
18
+
16
19
  include nginx-site.conf;
17
20
  }
@@ -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
- p [:auth, session]
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
- p [:auth, :update]
296
+ log(message: 'auth_refresh_app', back_to: params[:back_to], callback: params[:callback])
255
297
  update_session!
256
298
  else
257
- p [:auth, :redirect]
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
@@ -1,3 +1,3 @@
1
1
  module NginxOmniauthAdapter
2
- VERSION = "0.2.0"
2
+ VERSION = "1.0.0"
3
3
  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.2.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-09-02 00:00:00.000000000 Z
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