devise-proxy 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +11 -0
- data/Gemfile.lock +22 -0
- data/LICENSE +27 -0
- data/README.md +21 -0
- data/Rakefile +45 -0
- data/VERSION +1 -0
- data/config.ru +19 -0
- data/config/devise-proxy.yml.sample +3 -0
- data/lib/devise-proxy.rb +2 -0
- data/lib/devise-proxy/authenticator.rb +75 -0
- data/lib/devise-proxy/proxy.rb +89 -0
- data/test/helper.rb +18 -0
- data/test/test_devise-proxy.rb +7 -0
- metadata +116 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
git (1.2.5)
|
5
|
+
jeweler (1.8.4)
|
6
|
+
bundler (~> 1.0)
|
7
|
+
git (>= 1.2.5)
|
8
|
+
rake
|
9
|
+
rdoc
|
10
|
+
json (1.7.5)
|
11
|
+
rack (1.4.1)
|
12
|
+
rake (0.9.2.2)
|
13
|
+
rdoc (3.12)
|
14
|
+
json (~> 1.4)
|
15
|
+
|
16
|
+
PLATFORMS
|
17
|
+
ruby
|
18
|
+
|
19
|
+
DEPENDENCIES
|
20
|
+
jeweler (~> 1.8.4)
|
21
|
+
rack
|
22
|
+
rake
|
data/LICENSE
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Copyright (c) 2012, Preston Lee
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
1. Redistributions of source code must retain the above copyright
|
7
|
+
notice, this list of conditions and the following disclaimer.
|
8
|
+
2. Redistributions in binary form must reproduce the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer in the
|
10
|
+
documentation and/or other materials provided with the distribution.
|
11
|
+
3. All advertising materials mentioning features or use of this software
|
12
|
+
must display the following acknowledgement:
|
13
|
+
This product includes software developed by Preston Lee.
|
14
|
+
4. Neither the name of Preston Lee nor the
|
15
|
+
names of its contributors may be used to endorse or promote products
|
16
|
+
derived from this software without specific prior written permission.
|
17
|
+
|
18
|
+
THIS SOFTWARE IS PROVIDED BY Preston Lee ''AS IS'' AND ANY
|
19
|
+
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
20
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
21
|
+
DISCLAIMED. IN NO EVENT SHALL Preston Lee BE LIABLE FOR ANY
|
22
|
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
23
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
24
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
25
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
26
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
27
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Devise Proxy #
|
2
|
+
|
3
|
+
devise-proxy is a standalone Rack Middleware application that authenticates a username/password against
|
4
|
+
a devise-powered backend application before forwarding the original HTTP request to the same application.
|
5
|
+
|
6
|
+
Authentication is done on *every* request, so it is advisable to use devise-proxy sparingly.
|
7
|
+
|
8
|
+
# Quick Start #
|
9
|
+
|
10
|
+
- Create a devise-proxy.yml using the provided .sample.
|
11
|
+
- `rackup config.ru' to start the proxy server.
|
12
|
+
- Configure you web browser or other client software to use the proxy and set a username (email) and password.
|
13
|
+
- Enjoy!
|
14
|
+
|
15
|
+
# Authors #
|
16
|
+
|
17
|
+
Preston Lee
|
18
|
+
|
19
|
+
# Legal #
|
20
|
+
|
21
|
+
See LICENSE file for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "devise-proxy"
|
18
|
+
gem.homepage = "http://github.com/preston/devise-proxy"
|
19
|
+
gem.license = "BSD"
|
20
|
+
gem.summary = %Q{A standalone Rack Middleware application that authenticates a username/password against a devise-powered backend application before forwarding the original HTTP request to the same application.}
|
21
|
+
gem.description = %Q{A standalone Rack Middleware application that authenticates a username/password against a devise-powered backend application before forwarding the original HTTP request to the same application. Authentication is done on *every* request, so it is advisable to use devise-proxy sparingly.}
|
22
|
+
gem.email = "conmotto@gmail.com"
|
23
|
+
gem.authors = ["Preston Lee"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rake/testtask'
|
29
|
+
Rake::TestTask.new(:test) do |test|
|
30
|
+
test.libs << 'lib' << 'test'
|
31
|
+
test.pattern = 'test/**/test_*.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
|
35
|
+
task :default => :test
|
36
|
+
|
37
|
+
require 'rdoc/task'
|
38
|
+
Rake::RDocTask.new do |rdoc|
|
39
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
40
|
+
|
41
|
+
rdoc.rdoc_dir = 'rdoc'
|
42
|
+
rdoc.title = "devise-proxy #{version}"
|
43
|
+
rdoc.rdoc_files.include('README*')
|
44
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
45
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/config.ru
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
current_dir = File.dirname(File.expand_path(__FILE__))
|
3
|
+
lib_path = File.join(current_dir, 'lib')
|
4
|
+
puts lib_path
|
5
|
+
$LOAD_PATH.unshift lib_path
|
6
|
+
|
7
|
+
require 'devise-proxy'
|
8
|
+
|
9
|
+
# For development only.
|
10
|
+
# use Rack::Reloader
|
11
|
+
|
12
|
+
config_file = File.join(current_dir, 'config', 'devise-proxy.yml')
|
13
|
+
if File.exists? config_file
|
14
|
+
conf = YAML::load(File.open(config_file))
|
15
|
+
run DeviseProxy::Proxy.new(conf['backend']['hostname'], conf['backend']['port'])
|
16
|
+
else
|
17
|
+
puts "\nPlease create a config file prior to starting the proxy using the provided .sample file, at:\n\n\t#{config_file}\n\n"
|
18
|
+
exit 1
|
19
|
+
end
|
data/lib/devise-proxy.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
module DeviseProxy
|
5
|
+
|
6
|
+
class Authenticator
|
7
|
+
|
8
|
+
attr_accessor :host
|
9
|
+
attr_accessor :port
|
10
|
+
@@POST_SIGN = "/users/sign_in.json"
|
11
|
+
@@POST_WS = "/external/rd"
|
12
|
+
|
13
|
+
|
14
|
+
def initialize(host = 'localhost', port = 3000)
|
15
|
+
@host = host
|
16
|
+
@port = port
|
17
|
+
end
|
18
|
+
|
19
|
+
def authenticate(email, password)
|
20
|
+
|
21
|
+
@credentials = {
|
22
|
+
"user" => {
|
23
|
+
"email" => email,
|
24
|
+
"password" => password
|
25
|
+
}
|
26
|
+
}.to_json
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
sig = Net::HTTP::Post.new(@@POST_SIGN, initheader = {'Content-Type' => 'application/json'})
|
31
|
+
sig.body = @credentials
|
32
|
+
|
33
|
+
|
34
|
+
http = Net::HTTP.new(@host, @port).start
|
35
|
+
resp1 = http.request(sig)
|
36
|
+
puts "Response: #{resp1.code} , Message: #{resp1.message} , Body: #{resp1.body}"
|
37
|
+
result = []
|
38
|
+
if resp1.code == "200" then
|
39
|
+
puts "logged in"
|
40
|
+
json_resp = JSON.parse(resp1.body)
|
41
|
+
@auth_token = json_resp['auth_token']
|
42
|
+
|
43
|
+
@req_body = {
|
44
|
+
"device" => {
|
45
|
+
"name" => "device_json",
|
46
|
+
"operating_system_id" => "7",
|
47
|
+
"hash_string" => "jfsg3k4ovj0j02jv"
|
48
|
+
},
|
49
|
+
"auth_token" => @auth_token
|
50
|
+
}.to_json
|
51
|
+
req = Net::HTTP::Post.new(@@POST_WS, initheader = {'Content-Type' =>'application/json'})
|
52
|
+
req.body = @req_body
|
53
|
+
|
54
|
+
response = http.request(req)
|
55
|
+
puts "Response: #{response.code} , Message: #{response.message} , Body: #{response.body}"
|
56
|
+
|
57
|
+
headers = {}
|
58
|
+
sub_response.each_header do |k,v|
|
59
|
+
headers[k] = v unless k.to_s =~ /cookie|content-length|transfer-encoding/i
|
60
|
+
end
|
61
|
+
result = [response.code, headers, response.body]
|
62
|
+
else
|
63
|
+
headers = {}
|
64
|
+
resp1.each_header do |k,v|
|
65
|
+
headers[k] = v unless k.to_s =~ /cookie|content-length|transfer-encoding/i
|
66
|
+
end
|
67
|
+
result = [resp1.code, headers, resp1.body]
|
68
|
+
end
|
69
|
+
return result
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "enumerator"
|
3
|
+
require 'base64'
|
4
|
+
# require 'authenticator'
|
5
|
+
|
6
|
+
module DeviseProxy
|
7
|
+
|
8
|
+
class Proxy
|
9
|
+
|
10
|
+
attr_accessor :host
|
11
|
+
attr_accessor :port
|
12
|
+
attr_accessor :authenticator
|
13
|
+
|
14
|
+
def initialize(remote_host, remote_port)
|
15
|
+
@host = remote_host
|
16
|
+
@port = remote_port
|
17
|
+
@authenticator = DeviseProxy::Authenticator.new(@host, port)
|
18
|
+
end
|
19
|
+
|
20
|
+
def call(env)
|
21
|
+
req = Rack::Request.new(env)
|
22
|
+
puts req.to_yaml
|
23
|
+
|
24
|
+
puts "User agent: #{env['HTTP_USER_AGENT']}"
|
25
|
+
|
26
|
+
client_credential_b64 = env['HTTP_PROXY_AUTHORIZATION']
|
27
|
+
# puts "B64: #{client_credential_b64}"
|
28
|
+
|
29
|
+
if client_credential_b64 != nil and client_credential_b64 != ''
|
30
|
+
# Decode the credentials:
|
31
|
+
encoded = client_credential_b64.split[1]
|
32
|
+
credentials = Base64.decode64(encoded).split(':', 2)
|
33
|
+
email = credentials[0]
|
34
|
+
password = credentials[1]
|
35
|
+
|
36
|
+
puts "Client password credentials email: #{email}, password, #{password}"
|
37
|
+
|
38
|
+
# Authenticate against the backend:
|
39
|
+
auth = @authenticator.authenticate(email, password)
|
40
|
+
allowed = auth[0].to_s == '201'
|
41
|
+
puts "Authenticated #{allowed ? 'approved.' : 'denied!'}\n\n"
|
42
|
+
|
43
|
+
result = [403, auth[1], [auth[2]]]
|
44
|
+
if allowed
|
45
|
+
|
46
|
+
method = req.request_method.downcase
|
47
|
+
method[0..0] = method[0..0].upcase
|
48
|
+
|
49
|
+
sub_request = Net::HTTP.const_get(method).new("#{req.path}#{"?" if req.query_string}#{req.query_string}")
|
50
|
+
|
51
|
+
if sub_request.request_body_permitted? and req.body
|
52
|
+
sub_request.body_stream = req.body
|
53
|
+
sub_request.content_length = req.content_length
|
54
|
+
sub_request.content_type = req.content_type
|
55
|
+
end
|
56
|
+
|
57
|
+
sub_request["X-Forwarded-For"] = (req.env["X-Forwarded-For"].to_s.split(/, +/) + [req.env['REMOTE_ADDR']]).join(", ")
|
58
|
+
sub_request["Accept-Encoding"] = req.accept_encoding
|
59
|
+
sub_request["Referer"] = req.referer
|
60
|
+
|
61
|
+
sub_response = Net::HTTP.start(@host, @port) do |http|
|
62
|
+
http.request(sub_request)
|
63
|
+
end
|
64
|
+
|
65
|
+
headers = {}
|
66
|
+
sub_response.each_header do |k,v|
|
67
|
+
headers[k] = v unless k.to_s =~ /cookie|content-length|transfer-encoding/i
|
68
|
+
end
|
69
|
+
|
70
|
+
result = [sub_response.code.to_i, headers, [sub_response.read_body]]
|
71
|
+
end
|
72
|
+
else
|
73
|
+
# The client needs to retry, next time sending proxy credentials!
|
74
|
+
headers = {}
|
75
|
+
# sub_response.each_header do |k,v|
|
76
|
+
# headers[k] = v unless k.to_s =~ /cookie|content-length|transfer-encoding/i
|
77
|
+
# end
|
78
|
+
headers['Proxy-Authenticate'] = 'Basic realm="A valid account is required. Please use your registered email address as your username."'
|
79
|
+
headers['Content-Type'] = 'text/plain'
|
80
|
+
result = [407, headers, ["Email/Password required!"]]
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
result
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
data/test/helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'test/unit'
|
11
|
+
require 'shoulda'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
|
+
require 'devise-proxy'
|
16
|
+
|
17
|
+
class Test::Unit::TestCase
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: devise-proxy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Preston Lee
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-10-29 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rack
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: jeweler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 1.8.4
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.8.4
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: A standalone Rack Middleware application that authenticates a username/password
|
63
|
+
against a devise-powered backend application before forwarding the original HTTP
|
64
|
+
request to the same application. Authentication is done on *every* request, so it
|
65
|
+
is advisable to use devise-proxy sparingly.
|
66
|
+
email: conmotto@gmail.com
|
67
|
+
executables: []
|
68
|
+
extensions: []
|
69
|
+
extra_rdoc_files:
|
70
|
+
- LICENSE
|
71
|
+
- README.md
|
72
|
+
files:
|
73
|
+
- Gemfile
|
74
|
+
- Gemfile.lock
|
75
|
+
- LICENSE
|
76
|
+
- README.md
|
77
|
+
- Rakefile
|
78
|
+
- VERSION
|
79
|
+
- config.ru
|
80
|
+
- config/devise-proxy.yml.sample
|
81
|
+
- lib/devise-proxy.rb
|
82
|
+
- lib/devise-proxy/authenticator.rb
|
83
|
+
- lib/devise-proxy/proxy.rb
|
84
|
+
- test/helper.rb
|
85
|
+
- test/test_devise-proxy.rb
|
86
|
+
homepage: http://github.com/preston/devise-proxy
|
87
|
+
licenses:
|
88
|
+
- BSD
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
segments:
|
100
|
+
- 0
|
101
|
+
hash: -4305826360320545188
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
none: false
|
104
|
+
requirements:
|
105
|
+
- - ! '>='
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubyforge_project:
|
110
|
+
rubygems_version: 1.8.24
|
111
|
+
signing_key:
|
112
|
+
specification_version: 3
|
113
|
+
summary: A standalone Rack Middleware application that authenticates a username/password
|
114
|
+
against a devise-powered backend application before forwarding the original HTTP
|
115
|
+
request to the same application.
|
116
|
+
test_files: []
|