rack-oauth_proxy 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +11 -0
- data/Rakefile +1 -0
- data/lib/rack-oauth_proxy.rb +1 -0
- data/lib/rack/oauth_proxy.rb +27 -0
- data/lib/rack/oauth_proxy/access_tokens/base.rb +39 -0
- data/lib/rack/oauth_proxy/access_tokens/invalid.rb +22 -0
- data/lib/rack/oauth_proxy/access_tokens/valid.rb +23 -0
- data/lib/rack/oauth_proxy/client.rb +63 -0
- data/lib/rack/oauth_proxy/client/request.rb +42 -0
- data/lib/rack/oauth_proxy/client/response.rb +42 -0
- data/lib/rack/oauth_proxy/version.rb +5 -0
- data/rack-oauth_proxy.gemspec +26 -0
- data/spec/rack/oauth_proxy/client_spec.rb +55 -0
- data/spec/spec_helper.rb +9 -0
- metadata +147 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5834c55b2217ffe7ab3ef9808613717e03c3d30e
|
4
|
+
data.tar.gz: 3920d54037d98faa67ae7dfe68374ee75f16a458
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1fc62efb3ba2b9a55ee38a495277011d867d2dae4295cce6e7c3258f09b987ae82bb8b24769eb9321ee70c35bc570e4cb1708144c178f1e974367c7878e4ef62
|
7
|
+
data.tar.gz: 58eb2bc1b1e0c95a5093bbcec332fa5054661961399933befefe24472f2ccbb82efbd08e598b6c10af53c1711367ce9095f32986cbfe9dce93257fea08197145
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Ryo Nakamura
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# Rack::OauthProxy
|
2
|
+
Delegates OAuth authentication to other authentication server.
|
3
|
+
|
4
|
+
## Usage
|
5
|
+
For Rails example:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
class ApplicationController < ActionController::Base
|
9
|
+
use Rack::OauthProxy, url: "http://auth.example.com/oauth/token"
|
10
|
+
end
|
11
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1 @@
|
|
1
|
+
require "rack/oauth_proxy"
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "rack/oauth_proxy/access_tokens/base"
|
2
|
+
require "rack/oauth_proxy/access_tokens/invalid"
|
3
|
+
require "rack/oauth_proxy/access_tokens/valid"
|
4
|
+
require "rack/oauth_proxy/client"
|
5
|
+
require "rack/oauth_proxy/client/request"
|
6
|
+
require "rack/oauth_proxy/client/response"
|
7
|
+
require "rack/oauth_proxy/version"
|
8
|
+
|
9
|
+
module Rack
|
10
|
+
class OauthProxy
|
11
|
+
def initialize(app, options = {})
|
12
|
+
@app = app
|
13
|
+
@options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
env["rack-oauth_proxy.access_token"] = client.fetch(env)
|
18
|
+
@app.call(env)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def client
|
24
|
+
@client ||= Client.new(@options)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Rack
|
2
|
+
class OauthProxy
|
3
|
+
module AccessTokens
|
4
|
+
class Base
|
5
|
+
ATTRIBUTE_NAMES = %w[
|
6
|
+
application_id
|
7
|
+
expired_at
|
8
|
+
refresh_token
|
9
|
+
resource_owner_id
|
10
|
+
scope
|
11
|
+
token
|
12
|
+
token_type
|
13
|
+
]
|
14
|
+
|
15
|
+
ATTRIBUTE_NAMES.each {|name| attr_accessor name }
|
16
|
+
|
17
|
+
def initialize(attributes)
|
18
|
+
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def accessible?
|
22
|
+
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def revoked?
|
26
|
+
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def expired?
|
30
|
+
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def scopes
|
34
|
+
scope.split(" ") if scope
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Rack
|
2
|
+
class OauthProxy
|
3
|
+
module AccessTokens
|
4
|
+
class Invalid < Base
|
5
|
+
def initialize(attributes = nil)
|
6
|
+
end
|
7
|
+
|
8
|
+
def accessible?
|
9
|
+
false
|
10
|
+
end
|
11
|
+
|
12
|
+
def revoked?
|
13
|
+
false
|
14
|
+
end
|
15
|
+
|
16
|
+
def expired?
|
17
|
+
false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Rack
|
2
|
+
class OauthProxy
|
3
|
+
module AccessTokens
|
4
|
+
class Valid < Base
|
5
|
+
def initialize(attributes)
|
6
|
+
ATTRIBUTE_NAMES.each {|name| send("#{name}=", attributes[name]) }
|
7
|
+
end
|
8
|
+
|
9
|
+
def accessible?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
def revoked?
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
def expired?
|
18
|
+
false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "net/http"
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
class OauthProxy
|
5
|
+
class Client
|
6
|
+
READ_TIMEOUT = 1
|
7
|
+
OPEN_TIMEOUT = 1
|
8
|
+
|
9
|
+
def initialize(options = {})
|
10
|
+
@options = options
|
11
|
+
end
|
12
|
+
|
13
|
+
def fetch(env)
|
14
|
+
request = Request.new(env)
|
15
|
+
if request.has_any_valid_credentials?
|
16
|
+
path = "#{uri.path}"
|
17
|
+
path << "?#{request.to_query}" if request.to_query.present?
|
18
|
+
header = {
|
19
|
+
"Authorization" => request.authorization,
|
20
|
+
"Host" => host,
|
21
|
+
"Resource-Owner-Id" => request.resource_owner_id,
|
22
|
+
"Scopes" => request.scopes,
|
23
|
+
}.reject {|key, value| value.nil? }
|
24
|
+
raw_response = http_client.get(path, header)
|
25
|
+
response = Response.new(raw_response)
|
26
|
+
if response.valid_as_access_token?
|
27
|
+
AccessTokens::Valid.new(response.to_hash)
|
28
|
+
else
|
29
|
+
AccessTokens::Invalid.new
|
30
|
+
end
|
31
|
+
else
|
32
|
+
AccessTokens::Invalid.new
|
33
|
+
end
|
34
|
+
rescue Timeout::Error
|
35
|
+
AccessTokens::Invalid.new
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def uri
|
41
|
+
@uri ||= URI.parse(url)
|
42
|
+
end
|
43
|
+
|
44
|
+
def http_client
|
45
|
+
client = Net::HTTP.new(uri.host, uri.port)
|
46
|
+
client.read_timeout = READ_TIMEOUT
|
47
|
+
client.open_timeout = OPEN_TIMEOUT
|
48
|
+
client
|
49
|
+
end
|
50
|
+
|
51
|
+
def url
|
52
|
+
@options[:url] or raise NoUrlError
|
53
|
+
end
|
54
|
+
|
55
|
+
def host
|
56
|
+
@options[:host]
|
57
|
+
end
|
58
|
+
|
59
|
+
class NoUrlError < StandardError
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "active_support/core_ext/hash/slice"
|
2
|
+
require "active_support/core_ext/object/blank"
|
3
|
+
require "active_support/core_ext/object/to_query"
|
4
|
+
require "rack"
|
5
|
+
|
6
|
+
module Rack
|
7
|
+
class OauthProxy
|
8
|
+
class Client
|
9
|
+
class Request
|
10
|
+
def initialize(env)
|
11
|
+
@env = env
|
12
|
+
end
|
13
|
+
|
14
|
+
def has_any_valid_credentials?
|
15
|
+
authorization.present? ||
|
16
|
+
rack_request.params[:access_token].present? ||
|
17
|
+
rack_request.params[:bearer_token].present?
|
18
|
+
end
|
19
|
+
|
20
|
+
def rack_request
|
21
|
+
@rack_request ||= Rack::Request.new(@env)
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_query
|
25
|
+
rack_request.params.slice("access_token", "bearer_token").to_query
|
26
|
+
end
|
27
|
+
|
28
|
+
def authorization
|
29
|
+
@env["HTTP_AUTHORIZATION"]
|
30
|
+
end
|
31
|
+
|
32
|
+
def resource_owner_id
|
33
|
+
@env["HTTP_RESOURCE_OWNER_ID"]
|
34
|
+
end
|
35
|
+
|
36
|
+
def scopes
|
37
|
+
@env["HTTP_SCOPES"]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
class OauthProxy
|
5
|
+
class Client
|
6
|
+
class Response
|
7
|
+
def initialize(raw)
|
8
|
+
@raw = raw
|
9
|
+
end
|
10
|
+
|
11
|
+
def valid_as_access_token?
|
12
|
+
ok? && json? && hash?
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_hash
|
16
|
+
parsed_body
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def ok?
|
22
|
+
@raw.code == "200"
|
23
|
+
end
|
24
|
+
|
25
|
+
def json?
|
26
|
+
parsed_body
|
27
|
+
true
|
28
|
+
rescue JSON::ParserError
|
29
|
+
false
|
30
|
+
end
|
31
|
+
|
32
|
+
def hash?
|
33
|
+
parsed_body.is_a?(Hash)
|
34
|
+
end
|
35
|
+
|
36
|
+
def parsed_body
|
37
|
+
@parsed_body ||= JSON.parse(@raw.body)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "rack/oauth_proxy/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "rack-oauth_proxy"
|
8
|
+
spec.version = Rack::OauthProxy::VERSION
|
9
|
+
spec.authors = ["Ryo Nakamura"]
|
10
|
+
spec.email = ["r7kamura@gmail.com"]
|
11
|
+
spec.summary = "Delegates OAuth authentication to other authentication server"
|
12
|
+
spec.homepage = "https://github.com/r7kamura/rack-oauth_proxy"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency "activesupport"
|
21
|
+
spec.add_dependency "rack"
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
spec.add_development_dependency "rspec", "2.14.1"
|
25
|
+
spec.add_development_dependency "webmock"
|
26
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "stringio"
|
3
|
+
|
4
|
+
describe Rack::OauthProxy::Client do
|
5
|
+
let(:client) do
|
6
|
+
described_class.new(url: url)
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:url) do
|
10
|
+
"http://example.com/oauth/token"
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:env) do
|
14
|
+
{
|
15
|
+
"HTTP_AUTHORIZATION" => "Bearer #{token}",
|
16
|
+
"rack.input" => StringIO.new,
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:token) do
|
21
|
+
SecureRandom.hex(32)
|
22
|
+
end
|
23
|
+
|
24
|
+
context "#fetch" do
|
25
|
+
context "when authentication succeeded" do
|
26
|
+
before do
|
27
|
+
stub_request(:get, url).to_return(status: 200, body: {}.to_json)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "returns valid access token" do
|
31
|
+
client.fetch(env).should be_a Rack::OauthProxy::AccessTokens::Valid
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "without no credentials in request" do
|
36
|
+
before do
|
37
|
+
env.delete("HTTP_AUTHORIZATION")
|
38
|
+
end
|
39
|
+
|
40
|
+
it "returns invalid access token" do
|
41
|
+
client.fetch(env).should be_a Rack::OauthProxy::AccessTokens::Invalid
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when authentication failed" do
|
46
|
+
before do
|
47
|
+
stub_request(:get, url).to_return(status: 401, body: {}.to_json)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "returns invalid access token" do
|
51
|
+
client.fetch(env).should be_a Rack::OauthProxy::AccessTokens::Invalid
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
|
2
|
+
require "rack/oauth_proxy"
|
3
|
+
require "webmock/rspec"
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
7
|
+
config.run_all_when_everything_filtered = true
|
8
|
+
config.filter_run :focus
|
9
|
+
end
|
metadata
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-oauth_proxy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryo Nakamura
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rack
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.5'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 2.14.1
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 2.14.1
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: webmock
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description:
|
98
|
+
email:
|
99
|
+
- r7kamura@gmail.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- .gitignore
|
105
|
+
- Gemfile
|
106
|
+
- LICENSE.txt
|
107
|
+
- README.md
|
108
|
+
- Rakefile
|
109
|
+
- lib/rack-oauth_proxy.rb
|
110
|
+
- lib/rack/oauth_proxy.rb
|
111
|
+
- lib/rack/oauth_proxy/access_tokens/base.rb
|
112
|
+
- lib/rack/oauth_proxy/access_tokens/invalid.rb
|
113
|
+
- lib/rack/oauth_proxy/access_tokens/valid.rb
|
114
|
+
- lib/rack/oauth_proxy/client.rb
|
115
|
+
- lib/rack/oauth_proxy/client/request.rb
|
116
|
+
- lib/rack/oauth_proxy/client/response.rb
|
117
|
+
- lib/rack/oauth_proxy/version.rb
|
118
|
+
- rack-oauth_proxy.gemspec
|
119
|
+
- spec/rack/oauth_proxy/client_spec.rb
|
120
|
+
- spec/spec_helper.rb
|
121
|
+
homepage: https://github.com/r7kamura/rack-oauth_proxy
|
122
|
+
licenses:
|
123
|
+
- MIT
|
124
|
+
metadata: {}
|
125
|
+
post_install_message:
|
126
|
+
rdoc_options: []
|
127
|
+
require_paths:
|
128
|
+
- lib
|
129
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
requirements: []
|
140
|
+
rubyforge_project:
|
141
|
+
rubygems_version: 2.0.3
|
142
|
+
signing_key:
|
143
|
+
specification_version: 4
|
144
|
+
summary: Delegates OAuth authentication to other authentication server
|
145
|
+
test_files:
|
146
|
+
- spec/rack/oauth_proxy/client_spec.rb
|
147
|
+
- spec/spec_helper.rb
|