omniauth-tent 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.kick +17 -0
- data/.travis.yml +9 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +52 -0
- data/Rakefile +8 -0
- data/lib/omniauth-tent.rb +2 -0
- data/lib/omniauth-tent/version.rb +5 -0
- data/lib/omniauth/strategies/tent.rb +220 -0
- data/omniauth-tent.gemspec +31 -0
- data/spec/omniauth/strategies/tent_spec.rb +177 -0
- data/spec/spec_helper.rb +19 -0
- metadata +220 -0
data/.gitignore
ADDED
data/.kick
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
process do |files|
|
2
|
+
test_files = files.take_and_map do |file|
|
3
|
+
if file =~ %r{^(spec|lib)/(.+?)(_spec)?\.rb$}
|
4
|
+
path = $2
|
5
|
+
if file =~ %r{^spec/spec_helper\.rb}
|
6
|
+
""
|
7
|
+
else
|
8
|
+
"spec/#{path}_spec.rb"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
rspec_command = "time bundle exec rspec --tty --color"
|
13
|
+
res = execute "#{rspec_command} #{test_files.join(' ')}" unless test_files.empty?
|
14
|
+
if res.exit_code == 0 && test_files != [""]
|
15
|
+
execute rspec_command
|
16
|
+
end
|
17
|
+
end
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in omniauth-tent.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
gem 'tent-client', :git => 'git://github.com/tent/tent-client-ruby.git', :branch => 'master'
|
7
|
+
gem 'faraday_middleware-multi_json', :git => 'git://github.com/jvatic/faraday_middleware-multi_json.git', :branch => :master
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Jesse Stuart
|
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,52 @@
|
|
1
|
+
[![Build Status](https://secure.travis-ci.org/tent/omniauth-tent.png)](http://travis-ci.org/tent/omniauth-tent)
|
2
|
+
|
3
|
+
# Omniauth::Tent
|
4
|
+
|
5
|
+
Omniauth strategy for Tent.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'omniauth-tent'
|
12
|
+
|
13
|
+
|
14
|
+
## Usage
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
use OmniAuth::Builder do
|
18
|
+
provider :tent, options
|
19
|
+
end
|
20
|
+
```
|
21
|
+
|
22
|
+
Available options (see [the Tent.io docs for details](http://tent.io/docs/app-auth))
|
23
|
+
|
24
|
+
| Option | Required | Description |
|
25
|
+
| ------ | -------- | ----------- |
|
26
|
+
| get_app | Yes | Should be a lambda (or anything which responds to `call`) returning either an existing app attributes hash or `nil`. The entity URI will be passed in as a single argument. |
|
27
|
+
| on_app_created | No | Should respond to `call`. Gets called with Hashie::Mash representation of app when created |
|
28
|
+
| app | Yes | `name`, `icon`, `url`, `description`, `scopes`, and `redirect_uris` |
|
29
|
+
| profile_info_types | Yes | Array of profile info type URIs your app wants access to |
|
30
|
+
| post_types | Yes | Array of post type URIs your app wants access to |
|
31
|
+
| notification_url | Yes | URL for receiving notifications |
|
32
|
+
|
33
|
+
## Testing
|
34
|
+
|
35
|
+
bundle exec kicker
|
36
|
+
|
37
|
+
OR
|
38
|
+
|
39
|
+
bundle exec rspec
|
40
|
+
|
41
|
+
## Contributing
|
42
|
+
|
43
|
+
Here are some tasks that need to be done:
|
44
|
+
|
45
|
+
- Handle being passed an 'error' param in the callback_phase
|
46
|
+
- Find bugs and fix them
|
47
|
+
|
48
|
+
1. Fork it
|
49
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
50
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
51
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
52
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,220 @@
|
|
1
|
+
require 'omniauth'
|
2
|
+
require 'tent-client'
|
3
|
+
require 'uri'
|
4
|
+
require 'securerandom'
|
5
|
+
|
6
|
+
module OmniAuth
|
7
|
+
module Strategies
|
8
|
+
class Tent
|
9
|
+
include OmniAuth::Strategy
|
10
|
+
|
11
|
+
Error = Class.new(StandardError)
|
12
|
+
AppCreateFailure = Class.new(Error)
|
13
|
+
AppLookupFailure = Class.new(Error)
|
14
|
+
AppAuthorizationCreateFailure = Class.new(Error)
|
15
|
+
StateMissmatchError = Class.new(Error)
|
16
|
+
|
17
|
+
option :get_app, lambda { |entity| }
|
18
|
+
option :on_app_created, lambda { |app| }
|
19
|
+
option :app, { :name => nil, :icon => nil, :description => nil, :scopes => {}, :redirect_uris => nil }
|
20
|
+
option :profile_info_types, []
|
21
|
+
option :post_types, []
|
22
|
+
option :notification_url, ""
|
23
|
+
|
24
|
+
def request_params
|
25
|
+
Hashie::Mash.new(request.params)
|
26
|
+
end
|
27
|
+
|
28
|
+
def request_phase
|
29
|
+
if request.post? && request_params.entity
|
30
|
+
delete_state!
|
31
|
+
set_state(:entity, ensure_entity_has_scheme(request_params.entity))
|
32
|
+
perform_discovery!
|
33
|
+
find_or_create_app!
|
34
|
+
build_uri_and_redirect!
|
35
|
+
else
|
36
|
+
OmniAuth::Form.build(
|
37
|
+
:title => (options[:title] || "Entity Verification")
|
38
|
+
) do |f|
|
39
|
+
f.text_field 'Entity', 'entity'
|
40
|
+
end.to_response
|
41
|
+
end
|
42
|
+
rescue AppCreateFailure => e
|
43
|
+
fail!(:app_create_failure, e)
|
44
|
+
rescue AppLookupFailure => e
|
45
|
+
fail!(:app_lookup_failure, e)
|
46
|
+
rescue => e
|
47
|
+
fail!(:unknown_error, e)
|
48
|
+
end
|
49
|
+
|
50
|
+
def callback_phase
|
51
|
+
verify_state!
|
52
|
+
create_app_authorization!
|
53
|
+
build_auth_hash!
|
54
|
+
delete_state!
|
55
|
+
call_app!
|
56
|
+
rescue AppAuthorizationCreateFailure => e
|
57
|
+
fail!(:app_auth_create_failure, e)
|
58
|
+
rescue StateMissmatchError => e
|
59
|
+
fail!(:state_missmatch, e)
|
60
|
+
rescue => e
|
61
|
+
fail!(:unknown_error, e)
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def ensure_entity_has_scheme(entity_uri)
|
67
|
+
if entity_uri =~ %r{^[a-z]{3,}?://}
|
68
|
+
entity_uri
|
69
|
+
else
|
70
|
+
"https://#{entity_uri}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def set_state(key, val)
|
75
|
+
session["omniauth.#{key}"] = val
|
76
|
+
val
|
77
|
+
end
|
78
|
+
|
79
|
+
def get_state(key)
|
80
|
+
session["omniauth.#{key}"]
|
81
|
+
end
|
82
|
+
|
83
|
+
def perform_discovery!
|
84
|
+
client = ::TentClient.new
|
85
|
+
@profile, @server_url = client.discover(request[:entity]).get_profile
|
86
|
+
set_state(:server_url, @server_url)
|
87
|
+
set_state(:profile, @profile)
|
88
|
+
end
|
89
|
+
|
90
|
+
def find_or_create_app!
|
91
|
+
app = Hashie::Mash.new(options[:get_app].call(get_state(:entity)) || {})
|
92
|
+
client = ::TentClient.new(get_state(:server_url), :mac_key_id => app[:mac_key_id],
|
93
|
+
:mac_key => app[:mac_key],
|
94
|
+
:mac_algorithm => app[:mac_algorithm])
|
95
|
+
if app[:id]
|
96
|
+
res = client.app.get(app[:id])
|
97
|
+
if res.body.kind_of?(::String)
|
98
|
+
if res.status == 403
|
99
|
+
create_app and return
|
100
|
+
else
|
101
|
+
raise AppLookupFailure.new(res.inspect)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
set_app(app)
|
105
|
+
else
|
106
|
+
create_app
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def set_app(app)
|
111
|
+
set_state(:app, app)
|
112
|
+
end
|
113
|
+
|
114
|
+
def get_app
|
115
|
+
@tent_app ||= Hashie::Mash.new(get_state(:app) || {})
|
116
|
+
end
|
117
|
+
|
118
|
+
def create_app
|
119
|
+
client = ::TentClient.new(@server_url)
|
120
|
+
app_attrs = {
|
121
|
+
:name => options.app.name,
|
122
|
+
:description => options.app.description,
|
123
|
+
:scopes => options.app.scopes,
|
124
|
+
:icon => options.app.icon,
|
125
|
+
:url => options.app.url,
|
126
|
+
:redirect_uris => options.app.redirect_uris || [callback_url]
|
127
|
+
}
|
128
|
+
|
129
|
+
res = client.app.create(app_attrs)
|
130
|
+
|
131
|
+
if (app = res.body) && !app.kind_of?(::String)
|
132
|
+
set_app(app)
|
133
|
+
options[:on_app_created].call(get_app)
|
134
|
+
else
|
135
|
+
raise AppCreateFailure.new(res.inspect)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def build_uri_and_redirect!
|
140
|
+
auth_uri = URI(@server_url + '/oauth/authorize')
|
141
|
+
params = {
|
142
|
+
:client_id => get_app[:id],
|
143
|
+
:tent_profile_info_types => options[:profile_info_types].join(','),
|
144
|
+
:tent_post_types => options[:post_types].join(','),
|
145
|
+
:tent_notification_url => options[:notification_url],
|
146
|
+
:scope => options[:app][:scopes].keys.join(','),
|
147
|
+
:redirect_uri => callback_url,
|
148
|
+
}
|
149
|
+
params[:state] = set_state(:state, SecureRandom.hex(32))
|
150
|
+
build_uri_params!(auth_uri, params)
|
151
|
+
|
152
|
+
redirect auth_uri.to_s
|
153
|
+
end
|
154
|
+
|
155
|
+
def build_uri_params!(uri, params)
|
156
|
+
uri.query = params.inject([]) do |memo, (key,val)|
|
157
|
+
memo << "#{key}=#{URI.encode_www_form_component(val)}"
|
158
|
+
memo
|
159
|
+
end.join('&')
|
160
|
+
end
|
161
|
+
|
162
|
+
def verify_state!
|
163
|
+
raise StateMissmatchError unless get_state(:state) == request.params['state']
|
164
|
+
end
|
165
|
+
|
166
|
+
def create_app_authorization!
|
167
|
+
client = ::TentClient.new(get_state(:server_url), :mac_key_id => get_app[:mac_key_id],
|
168
|
+
:mac_key => get_app[:mac_key],
|
169
|
+
:mac_algorithm => get_app[:mac_algorithm])
|
170
|
+
res = client.app.authorization.create(get_app[:id], :code => request.params['code'])
|
171
|
+
raise AppAuthorizationCreateFailure.new(res.body) if res.body.kind_of?(String)
|
172
|
+
@app_authorization = Hashie::Mash.new(res.body)
|
173
|
+
end
|
174
|
+
|
175
|
+
def build_auth_hash!
|
176
|
+
env['omniauth.auth'] = Hashie::Mash.new(
|
177
|
+
:provider => 'tent',
|
178
|
+
:uid => get_state(:entity),
|
179
|
+
:info => extract_basic_info(get_state(:profile)),
|
180
|
+
:credentials => {
|
181
|
+
:token => @app_authorization.access_token,
|
182
|
+
:secret => @app_authorization.mac_key
|
183
|
+
},
|
184
|
+
:extra => {
|
185
|
+
:raw_info => {
|
186
|
+
:profile => get_state(:profile),
|
187
|
+
:app_authorization => @app_authorization,
|
188
|
+
:app => get_app
|
189
|
+
},
|
190
|
+
:credentials => {
|
191
|
+
:mac_key_id => @app_authorization.access_token,
|
192
|
+
:mac_key => @app_authorization.mac_key,
|
193
|
+
:mac_algorithm => @app_authorization.mac_algorithm,
|
194
|
+
:token_type => @app_authorization.token_type
|
195
|
+
}
|
196
|
+
}
|
197
|
+
)
|
198
|
+
end
|
199
|
+
|
200
|
+
def delete_state!
|
201
|
+
%w( entity app server_url profile state ).each do |key|
|
202
|
+
session.delete("omniauth.#{key}")
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def extract_basic_info(profile)
|
207
|
+
basic_info = Hashie::Mash.new(profile.inject({}) { |memo, (k,v)|
|
208
|
+
memo = v if k =~ %r{^https://tent.io/types/info/basic}
|
209
|
+
memo
|
210
|
+
})
|
211
|
+
|
212
|
+
{
|
213
|
+
:name => basic_info.name,
|
214
|
+
:nickname => get_state(:entity),
|
215
|
+
:image => basic_info.avatar
|
216
|
+
}
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'omniauth-tent/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "omniauth-tent"
|
8
|
+
gem.version = Omniauth::Tent::VERSION
|
9
|
+
gem.authors = ["Jesse Stuart"]
|
10
|
+
gem.email = ["jessestuart@gmail.com"]
|
11
|
+
gem.description = %q{Omniauth Strategy for Tent}
|
12
|
+
gem.summary = %q{Omniauth Strategy for Tent}
|
13
|
+
gem.homepage = "https://github.com/tent/omniauth-tent"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_runtime_dependency 'omniauth', '~> 1.1.1'
|
21
|
+
gem.add_runtime_dependency 'tent-client'
|
22
|
+
|
23
|
+
gem.add_development_dependency 'rspec', '~> 2.7'
|
24
|
+
gem.add_development_dependency 'rack-test'
|
25
|
+
gem.add_development_dependency 'webmock'
|
26
|
+
gem.add_development_dependency 'bundler'
|
27
|
+
gem.add_development_dependency 'rake'
|
28
|
+
gem.add_development_dependency 'kicker'
|
29
|
+
gem.add_development_dependency 'mocha'
|
30
|
+
gem.add_development_dependency 'yajl-ruby'
|
31
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'yajl'
|
3
|
+
|
4
|
+
describe OmniAuth::Strategies::Tent do
|
5
|
+
attr_accessor :app
|
6
|
+
|
7
|
+
# customize rack app for testing, if block is given, reverts to default
|
8
|
+
# rack app after testing is done
|
9
|
+
def set_app!(tent_options = {})
|
10
|
+
old_app = self.app
|
11
|
+
self.app = Rack::Builder.app do
|
12
|
+
use OmniAuth::Strategies::Tent, tent_options
|
13
|
+
run lambda{|env| [404, {'env' => env}, ["HELLO!"]]}
|
14
|
+
end
|
15
|
+
if block_given?
|
16
|
+
yield
|
17
|
+
self.app = old_app
|
18
|
+
end
|
19
|
+
self.app
|
20
|
+
end
|
21
|
+
|
22
|
+
before(:all) do
|
23
|
+
set_app!
|
24
|
+
end
|
25
|
+
|
26
|
+
let(:env) { {'rack.session' => {}} }
|
27
|
+
|
28
|
+
let(:fresh_strategy){ Class.new(OmniAuth::Strategies::Tent) }
|
29
|
+
|
30
|
+
let(:tent_entity) { 'https://example.com' }
|
31
|
+
let(:tent_server) { "#{tent_entity}/tent" }
|
32
|
+
let(:app_id) { 'app-id-123' }
|
33
|
+
let(:link_header) { %(<#{tent_server}/profile>; rel="%s") % TentClient::PROFILE_REL }
|
34
|
+
let(:tent_profile) { %({"https://tent.io/types/info/core/v0.1.0":{"licenses":["http://creativecommons.org/licenses/by/3.0/"],"entity":"#{tent_entity}","servers":["#{tent_server}"]}}) }
|
35
|
+
let(:app_attrs) do
|
36
|
+
{
|
37
|
+
:name => "Example App",
|
38
|
+
:description => "An example app",
|
39
|
+
:scopes => { "read_posts" => "Display your posts feed" },
|
40
|
+
:icon => "https://example.com/icon.png",
|
41
|
+
:url => "https://example.com"
|
42
|
+
}
|
43
|
+
end
|
44
|
+
let(:app_json) { %({"name":"Example App","id":"#{app_id}"}) }
|
45
|
+
let(:app_hash) { Yajl::Parser.parse(app_json) }
|
46
|
+
|
47
|
+
let(:token_code) { 'token-code-123abc' }
|
48
|
+
|
49
|
+
let(:access_token) { 'access-token-abc' }
|
50
|
+
let(:mac_key) { 'mac-key-312' }
|
51
|
+
let(:mac_algorithm) { 'hmac-sha-256' }
|
52
|
+
let(:token_type) { 'mac' }
|
53
|
+
let(:app_auth_json) { %({"access_token":"#{access_token}","mac_key":"#{mac_key}","mac_algorithm":"#{mac_algorithm}","token_type":"#{token_type}") }
|
54
|
+
|
55
|
+
let(:stub_head_discovery!) do
|
56
|
+
stub_request(:head, tent_entity).to_return(:headers => {'Link' => link_header})
|
57
|
+
end
|
58
|
+
|
59
|
+
let(:stub_profile_discovery!) do
|
60
|
+
stub_request(:get, "#{tent_server}/profile").to_return(:body => tent_profile, :headers => {'Content-Type' => TentClient::MEDIA_TYPE})
|
61
|
+
end
|
62
|
+
|
63
|
+
let(:stub_app_lookup_success!) do
|
64
|
+
stub_request(:get, "#{tent_server}/apps/#{app_id}").to_return(:body => app_json, :headers => { 'Content-Type' => TentClient::MEDIA_TYPE })
|
65
|
+
end
|
66
|
+
|
67
|
+
let(:stub_app_lookup_failure!) do
|
68
|
+
stub_request(:get, "#{tent_server}/apps/#{app_id}").to_return(:status => 404)
|
69
|
+
end
|
70
|
+
|
71
|
+
let(:stub_app_create_success!) do
|
72
|
+
stub_request(:post, "#{tent_server}/apps").to_return(:body => app_json, :headers => { 'Content-Type' => TentClient::MEDIA_TYPE })
|
73
|
+
end
|
74
|
+
|
75
|
+
let(:stub_app_auth_create_success!) do
|
76
|
+
stub_request(:post, "#{tent_server}/apps/#{app_id}/authorizations").with(:body => Yajl::Encoder.encode({ :code => token_code })).to_return(:body => app_auth_json, :headers => { 'Content-Type' => TentClient::MEDIA_TYPE })
|
77
|
+
end
|
78
|
+
|
79
|
+
describe '#request_phase' do
|
80
|
+
it 'should display a form' do
|
81
|
+
get '/auth/tent', {}, env
|
82
|
+
expect(last_response.body).to be_include("<form")
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should perform disvocery' do
|
86
|
+
head_stub = stub_head_discovery!
|
87
|
+
profile_stub = stub_profile_discovery!
|
88
|
+
|
89
|
+
described_class.any_instance.stubs(:find_or_create_app!)
|
90
|
+
described_class.any_instance.stubs(:build_uri_and_redirect!).returns([200, {}, []])
|
91
|
+
|
92
|
+
post '/auth/tent', { :entity => tent_entity }, env
|
93
|
+
|
94
|
+
expect(head_stub).to have_been_requested
|
95
|
+
expect(profile_stub).to have_been_requested
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should create app if app_id callback returns nil' do
|
99
|
+
set_app!(:app => app_attrs)
|
100
|
+
stub_head_discovery!
|
101
|
+
stub_profile_discovery!
|
102
|
+
app_create_stub = stub_app_create_success!
|
103
|
+
described_class.any_instance.stubs(:build_uri_and_redirect!).returns([200, {}, []])
|
104
|
+
|
105
|
+
post '/auth/tent', { :entity => tent_entity }, env
|
106
|
+
|
107
|
+
expect(app_create_stub).to have_been_requested
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should create app if not found' do
|
111
|
+
set_app!(:app => app_attrs, :on_app_created => mock(:call))
|
112
|
+
stub_head_discovery!
|
113
|
+
stub_profile_discovery!
|
114
|
+
stub_app_lookup_failure!
|
115
|
+
app_create_stub = stub_app_create_success!
|
116
|
+
described_class.any_instance.stubs(:build_uri_and_redirect!).returns([200, {}, []])
|
117
|
+
|
118
|
+
post '/auth/tent', { :entity => tent_entity }, env
|
119
|
+
|
120
|
+
expect(app_create_stub).to have_been_requested
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should build uri and redirect' do
|
124
|
+
set_app!(:get_app => lambda { |entity| app_hash })
|
125
|
+
stub_head_discovery!
|
126
|
+
stub_profile_discovery!
|
127
|
+
stub_app_lookup_success!
|
128
|
+
|
129
|
+
post '/auth/tent', { :entity => tent_entity }, env
|
130
|
+
|
131
|
+
expect(last_response.status).to eq(302)
|
132
|
+
expect(last_response.headers["Location"]).to match(%r{^#{tent_server}/oauth/authorize})
|
133
|
+
expect(last_response.headers["Location"]).to match(%r{client_id=#{app_id}})
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe '#callback_phase' do
|
138
|
+
it 'should create app authorization' do
|
139
|
+
state = 'abcdef'
|
140
|
+
session = {}
|
141
|
+
session['omniauth.state'] = state
|
142
|
+
session['omniauth.entity'] = tent_entity
|
143
|
+
session['omniauth.server_url'] = tent_server
|
144
|
+
session['omniauth.app'] = { :id => app_id }
|
145
|
+
session['omniauth.profile'] = Yajl::Parser.parse(tent_profile)
|
146
|
+
|
147
|
+
stub_app_auth_create_success!
|
148
|
+
stub_app_lookup_success!
|
149
|
+
|
150
|
+
get '/auth/tent/callback', { :code => token_code, :state => state }, 'rack.session' => session
|
151
|
+
|
152
|
+
auth_hash = last_response['env']['omniauth.auth']
|
153
|
+
expect(auth_hash).to_not be_nil
|
154
|
+
expect(auth_hash.provider).to eq('tent')
|
155
|
+
expect(auth_hash.uid).to eq(tent_entity)
|
156
|
+
expect(auth_hash.info).to eq(Hashie::Mash.new(
|
157
|
+
:name => nil,
|
158
|
+
:nickname => tent_entity,
|
159
|
+
:image => nil
|
160
|
+
))
|
161
|
+
expect(auth_hash.credentials).to eq(Hashie::Mash.new(
|
162
|
+
:token => access_token,
|
163
|
+
:secret => mac_key
|
164
|
+
))
|
165
|
+
expect(auth_hash.extra.raw_info.profile).to eq(Hashie::Mash.new(Yajl::Parser.parse(tent_profile)))
|
166
|
+
expect(auth_hash.extra.credentials).to eq(Hashie::Mash.new(
|
167
|
+
:mac_key_id => access_token,
|
168
|
+
:mac_key => mac_key,
|
169
|
+
:mac_algorithm => mac_algorithm,
|
170
|
+
:token_type => token_type
|
171
|
+
))
|
172
|
+
expect(auth_hash.extra.raw_info.app_authorization).to eq(Hashie::Mash.new(
|
173
|
+
Yajl::Parser.parse(app_auth_json)
|
174
|
+
))
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'mocha_standalone'
|
6
|
+
require 'rack/test'
|
7
|
+
require 'webmock/rspec'
|
8
|
+
require 'omniauth-tent'
|
9
|
+
|
10
|
+
Dir["#{File.dirname(__FILE__)}/support/*.rb"].each { |f| require f }
|
11
|
+
|
12
|
+
RSpec.configure do |config|
|
13
|
+
config.include WebMock::API
|
14
|
+
config.include Rack::Test::Methods
|
15
|
+
config.extend OmniAuth::Test::StrategyMacros, :type => :strategy
|
16
|
+
config.mock_with :mocha
|
17
|
+
end
|
18
|
+
|
19
|
+
OmniAuth.config.logger = Logger.new(File.join(File.dirname(__FILE__), '..', 'log', 'test.log'))
|
metadata
ADDED
@@ -0,0 +1,220 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: omniauth-tent
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jesse Stuart
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-10-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: omniauth
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.1.1
|
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: 1.1.1
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: tent-client
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '2.7'
|
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: '2.7'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rack-test
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: webmock
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: bundler
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: rake
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: kicker
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: mocha
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ! '>='
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
type: :development
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
- !ruby/object:Gem::Dependency
|
159
|
+
name: yajl-ruby
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ! '>='
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
type: :development
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
170
|
+
requirements:
|
171
|
+
- - ! '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
description: Omniauth Strategy for Tent
|
175
|
+
email:
|
176
|
+
- jessestuart@gmail.com
|
177
|
+
executables: []
|
178
|
+
extensions: []
|
179
|
+
extra_rdoc_files: []
|
180
|
+
files:
|
181
|
+
- .gitignore
|
182
|
+
- .kick
|
183
|
+
- .travis.yml
|
184
|
+
- Gemfile
|
185
|
+
- LICENSE.txt
|
186
|
+
- README.md
|
187
|
+
- Rakefile
|
188
|
+
- lib/omniauth-tent.rb
|
189
|
+
- lib/omniauth-tent/version.rb
|
190
|
+
- lib/omniauth/strategies/tent.rb
|
191
|
+
- omniauth-tent.gemspec
|
192
|
+
- spec/omniauth/strategies/tent_spec.rb
|
193
|
+
- spec/spec_helper.rb
|
194
|
+
homepage: https://github.com/tent/omniauth-tent
|
195
|
+
licenses: []
|
196
|
+
post_install_message:
|
197
|
+
rdoc_options: []
|
198
|
+
require_paths:
|
199
|
+
- lib
|
200
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
201
|
+
none: false
|
202
|
+
requirements:
|
203
|
+
- - ! '>='
|
204
|
+
- !ruby/object:Gem::Version
|
205
|
+
version: '0'
|
206
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
207
|
+
none: false
|
208
|
+
requirements:
|
209
|
+
- - ! '>='
|
210
|
+
- !ruby/object:Gem::Version
|
211
|
+
version: '0'
|
212
|
+
requirements: []
|
213
|
+
rubyforge_project:
|
214
|
+
rubygems_version: 1.8.23
|
215
|
+
signing_key:
|
216
|
+
specification_version: 3
|
217
|
+
summary: Omniauth Strategy for Tent
|
218
|
+
test_files:
|
219
|
+
- spec/omniauth/strategies/tent_spec.rb
|
220
|
+
- spec/spec_helper.rb
|