warden-bootic 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.
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ coverage
2
+ .bundle
3
+ pkg
4
+ .DS_Store
5
+ Gemfile.lock
6
+ vendor/gems
7
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,26 @@
1
+ source 'http://rubygems.org'
2
+
3
+ group :runtime do
4
+ gem 'warden', '~>1.0.4'
5
+ gem 'oauth2', '~>0.4.1'
6
+ gem 'json', '>=1.0.0'
7
+ end
8
+
9
+ group :test do
10
+ gem 'rake'
11
+ gem 'rspec', '~>1.3.0', :require => 'spec'
12
+ gem 'rcov'
13
+ gem 'sinatra', '~>1.0', :require => 'sinatra/base'
14
+ gem 'shotgun'
15
+ gem 'webrat', '~>0.7.0'
16
+ gem 'bundler', '~>1.0'
17
+ gem 'randexp', '>=0.1.4'
18
+ gem 'ruby-debug19', :platforms => :ruby_19
19
+ gem 'ruby-debug', :platforms => :ruby_18
20
+ gem 'addressable', '~>2.2.0', :require => 'addressable/uri'
21
+ gem 'rack-test', '~>0.5.3', :require => 'rack/test'
22
+ end
23
+
24
+ group :development do
25
+ gem 'rest-client'
26
+ end
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Ismael Celis
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,18 @@
1
+ warden-bootic
2
+ =============
3
+
4
+ NOTE: this code is basically warden-github adapted to work against Bootic oauth provider.
5
+
6
+ https://github.com/atmos/warden-github
7
+
8
+ A [warden](http://github.com/hassox/warden) strategy that provides oauth authentication to Bootic. IN PROGRESS.
9
+
10
+ To test it out on localhost set your callback url to 'http://localhost:9292/auth/bootic/callback'
11
+
12
+ There's an example app in [spec/app.rb](/ismasan/warden-bootic/blob/master/spec/app.rb).
13
+
14
+ The Extension in Action
15
+ =======================
16
+ % gem install bundler
17
+ % bundle install
18
+ % OAUTH_CLIENT_ID="<from Bootic>" OAUTH_CLIENT_SECRET="<from Bootic>" bundle exec rackup
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new('spec')
6
+
7
+ # If you want to make this the default task
8
+ task :default => :spec
data/config.ru ADDED
@@ -0,0 +1,34 @@
1
+ ENV['RACK_ENV'] ||= 'development'
2
+
3
+ begin
4
+ require File.expand_path('../.bundle/environment', __FILE__)
5
+ rescue LoadError
6
+ require "rubygems"
7
+ require "bundler"
8
+ Bundler.setup
9
+ end
10
+
11
+ Bundler.require(:runtime, :test)
12
+ require "ruby-debug"
13
+
14
+ $LOAD_PATH << File.dirname(__FILE__) + '/lib'
15
+ require File.expand_path(File.join(File.dirname(__FILE__), 'lib', 'warden-bootic'))
16
+ require File.expand_path(File.join(File.dirname(__FILE__), 'spec', 'app'))
17
+
18
+ class Fix
19
+
20
+ def initialize(app)
21
+ @app = app
22
+ end
23
+
24
+ def call(env)
25
+ status, headers, response = @app.call(env)
26
+ headers['Content-Type'] = 'text/html'
27
+ [status, headers, response]
28
+ end
29
+ end
30
+
31
+ use Fix
32
+ run Example.app
33
+
34
+ # vim:ft=ruby
@@ -0,0 +1,14 @@
1
+ require 'warden'
2
+ require 'oauth2'
3
+ require 'json'
4
+
5
+ module Warden
6
+ module Bootic
7
+ API_URL = ENV['BOOTIC_API_URL'] || 'https://api.bootic.net'
8
+ end
9
+ end
10
+
11
+ require 'warden-bootic/user'
12
+ require 'warden-bootic/proxy'
13
+ require 'warden-bootic/version'
14
+ require 'warden-bootic/strategy'
@@ -0,0 +1,44 @@
1
+ module Warden
2
+ module Bootic
3
+ module Oauth
4
+ class Proxy
5
+ attr_accessor :client_id, :secret, :scopes, :callback_url
6
+ def initialize(client_id, secret, scopes, callback_url)
7
+ @client_id, @secret, @scopes, @callback_url = client_id, secret, scopes, callback_url
8
+ end
9
+
10
+ def ssl_options
11
+ ca_file = "/usr/lib/ssl/certs/ca-certificates.crt"
12
+ if File.exists?(ca_file)
13
+ { :ca_file => ca_file }
14
+ else
15
+ { :ca_file => ''}
16
+ end
17
+ end
18
+
19
+ def client
20
+ @client ||= OAuth2::Client.new(@client_id, @secret,
21
+ :ssl => ssl_options,
22
+ :site => Warden::Bootic::API_URL,
23
+ :authorize_path => '/oauth/authorize',
24
+ :access_token_path => '/oauth/token')
25
+ end
26
+
27
+ def access_token_for(code)
28
+ web_server.get_access_token(code, :redirect_uri => callback_url)
29
+ end
30
+
31
+ def authorize_url
32
+ web_server.authorize_url(
33
+ :scope => scopes,
34
+ :redirect_uri => callback_url
35
+ )
36
+ end
37
+
38
+ def web_server
39
+ client.web_server
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,57 @@
1
+ Warden::Strategies.add(:bootic) do
2
+ # Need to make sure that we have a pure representation of the query string.
3
+ # Rails adds an "action" parameter which causes the openid gem to error
4
+ def params
5
+ @params ||= Rack::Utils.parse_query(request.query_string)
6
+ end
7
+
8
+ def authenticate!
9
+ if params['code']
10
+ begin
11
+ access_token = access_token_for(params['code'])
12
+ user = JSON.parse(access_token.get('/oauth/me'))
13
+ success!(Warden::Bootic::Oauth::User.new(user, access_token.token))
14
+ rescue OAuth2::HTTPError
15
+ %(<p>Outdated ?code=#{params['code']}:</p><p>#{$!}</p><p><a href="/auth/bootic">Retry</a></p>)
16
+ end
17
+ else
18
+ env['rack.session']['return_to'] = env['REQUEST_URI']
19
+ throw(:warden, [ 302, {'Location' => authorize_url}, [ ]])
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def oauth_client
26
+ oauth_proxy.client
27
+ end
28
+
29
+ def authorize_url
30
+ oauth_proxy.authorize_url
31
+ end
32
+
33
+ def access_token_for(code)
34
+ oauth_proxy.access_token_for(code)
35
+ end
36
+
37
+ def oauth_proxy
38
+ @oauth_proxy ||= Warden::Bootic::Oauth::Proxy.new(env['warden'].config[:client_id],
39
+ env['warden'].config[:secret],
40
+ env['warden'].config[:scopes],
41
+ callback_url)
42
+ end
43
+
44
+ def callback_url
45
+ absolute_url(request, env['warden'].config[:callback_url])
46
+ end
47
+
48
+ def absolute_url(request, suffix = nil)
49
+ port_part = case request.scheme
50
+ when "http"
51
+ request.port == 80 ? "" : ":#{request.port}"
52
+ when "https"
53
+ request.port == 443 ? "" : ":#{request.port}"
54
+ end
55
+ "#{request.scheme}://#{request.host}#{port_part}#{suffix}"
56
+ end
57
+ end
@@ -0,0 +1,27 @@
1
+ module Warden
2
+ module Bootic
3
+ module Oauth
4
+ class User
5
+
6
+ attr_reader :attribs, :token
7
+
8
+ def initialize(attribs, token)
9
+ @attribs, @token = attribs, token
10
+ end
11
+
12
+ def user_name
13
+ attribs['user_info']['user_name']
14
+ end
15
+
16
+ def email
17
+ attribs['user_info']['email']
18
+ end
19
+
20
+ def role
21
+ attribs['user_info']['role_key']
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,5 @@
1
+ module Warden
2
+ module Bootic
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
data/spec/app.rb ADDED
@@ -0,0 +1,86 @@
1
+ require 'rest-client'
2
+
3
+ module Example
4
+ class App < Sinatra::Base
5
+
6
+ use Rack::Session::Cookie, :key => 'rack.session',
7
+ :path => '/',
8
+ :expire_after => 2592000, # In seconds
9
+ :secret => 'change_me',
10
+ :old_secret => 'change_me'
11
+ enable :raise_errors
12
+ disable :show_exceptions
13
+
14
+ use Warden::Manager do |manager|
15
+ manager.default_strategies :bootic
16
+ manager.failure_app = BadAuthentication
17
+
18
+ manager[:client_id] = ENV['OAUTH_CLIENT_ID'] || '12345678901234567890' # or test id
19
+ manager[:secret] = ENV['OAUTH_CLIENT_SECRET']
20
+
21
+ manager[:scopes] = 'public'
22
+ manager[:callback_url] = '/auth/bootic/callback'
23
+ end
24
+
25
+ helpers do
26
+ def ensure_authenticated
27
+ unless env['warden'].authenticate!
28
+ throw(:warden)
29
+ end
30
+ end
31
+
32
+ def user
33
+ env['warden'].user
34
+ end
35
+
36
+ def bootic(path)
37
+ JSON.parse(RestClient.get("#{Warden::Bootic::API_URL}/#{path}", :params => { :access_token => user.token }, :accept => :json))
38
+ end
39
+ end
40
+
41
+ get '/' do
42
+ ensure_authenticated
43
+ p [:user, user.attribs]
44
+ "Hello There, #{user.user_name}!. Your token: #{user.token.inspect}"
45
+ end
46
+
47
+ get '/products' do
48
+ ensure_authenticated
49
+ bootic('/products')['entries'].map do |product|
50
+ html = '<div>'
51
+ html += "<h2>#{product['title']}</h2>"
52
+ html += %(<img src="#{product['images'].first['small']}" />) if product['images'].any?
53
+ html += '/<div>'
54
+ html
55
+ end.join("\n")
56
+ end
57
+
58
+ get '/redirect_to' do
59
+ ensure_authenticated
60
+ "Hello There, #{user.user_name}! return_to is working!"
61
+ end
62
+
63
+ get '/auth/bootic/callback' do
64
+ ensure_authenticated
65
+ redirect '/'
66
+ end
67
+
68
+ get '/logout' do
69
+ env['warden'].logout
70
+ "Peace!"
71
+ end
72
+ end
73
+
74
+ class BadAuthentication < Sinatra::Base
75
+ get '/unauthenticated' do
76
+ status 403
77
+ "Unable to authenticate, sorry bud."
78
+ end
79
+ end
80
+
81
+ def self.app
82
+ @app ||= Rack::Builder.new do
83
+ run App
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,18 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "Warden::Github" do
4
+ it "requesting an url that requires authentication redirects to bootic" do
5
+ response = get "/"
6
+
7
+ uri = Addressable::URI.parse(response.headers["Location"])
8
+
9
+ uri.scheme.should eql('https')
10
+ uri.host.should eql('api.bootic.net')
11
+
12
+ params = uri.query_values
13
+ params['response_type'].should eql('code')
14
+ params['scope'].should eql('public')
15
+ params['client_id'].should match(/\w{20}/)
16
+ params['redirect_uri'].should eql('http://example.org/auth/bootic/callback')
17
+ end
18
+ end
@@ -0,0 +1,33 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "Warden::Bootic::Oauth::Proxy" do
4
+ before(:all) do
5
+ sha = Digest::SHA1.hexdigest(Time.now.to_s)
6
+ @proxy = Warden::Bootic::Oauth::Proxy.new(sha[0..19], sha[0..39],
7
+ 'user',
8
+ 'http://example.org/auth/bootic/callback')
9
+ end
10
+
11
+ it "returns an authorize url" do
12
+ uri = Addressable::URI.parse(@proxy.authorize_url)
13
+
14
+ uri.scheme.should eql('https')
15
+ uri.host.should eql('api.bootic.net')
16
+
17
+ params = uri.query_values
18
+ params['response_type'].should eql('code')
19
+ params['scope'].should eql('user')
20
+ params['client_id'].should match(/\w{20}/)
21
+ params['redirect_uri'].should eql('http://example.org/auth/bootic/callback')
22
+ end
23
+
24
+ it "has a client object" do
25
+ @proxy.client.should_not be_nil
26
+ end
27
+
28
+ it "returns access tokens" do
29
+ pending "this hits the network" do
30
+ lambda { @proxy.access_token_for(/\w{20}/.gen) }.should_not raise_error
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,24 @@
1
+ Bundler.require(:default, :runtime, :test)
2
+
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'warden-bootic')
4
+ require File.join(File.dirname(__FILE__), 'app')
5
+
6
+ require 'pp'
7
+
8
+ Webrat.configure do |config|
9
+ config.mode = :rack
10
+ config.application_port = 4567
11
+ end
12
+
13
+ Spec::Runner.configure do |config|
14
+ config.include(Rack::Test::Methods)
15
+ config.include(Webrat::Methods)
16
+ config.include(Webrat::Matchers)
17
+
18
+ config.before(:each) do
19
+ end
20
+
21
+ def app
22
+ Example.app
23
+ end
24
+ end
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ require 'warden-bootic/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "warden-bootic"
8
+ s.version = Warden::Bootic::VERSION
9
+ s.platform = Gem::Platform::RUBY
10
+ s.authors = ["Ismael Celis"]
11
+ s.email = ["ismael@bootic.net"]
12
+ s.homepage = "http://github.com/ismasan/warden-bootic"
13
+ s.summary = "A warden strategy for easy oauth integration with Bootic"
14
+ s.description = s.summary
15
+
16
+ s.rubyforge_project = "warden-bootic"
17
+
18
+ s.add_dependency "json", "~>1.5"
19
+ s.add_dependency "warden", "~>1.0.4"
20
+ s.add_dependency "oauth2", "~>0.4.1"
21
+
22
+ s.add_development_dependency "rake"
23
+ s.add_development_dependency "rspec", "~>1.3.0"
24
+ s.add_development_dependency "shotgun"
25
+ s.add_development_dependency "bundler", "~>1.0"
26
+ s.add_development_dependency "addressable", "~>2.2.0"
27
+ s.add_development_dependency "rack-test", "~>0.5.3"
28
+ s.add_development_dependency "ruby-debug"
29
+
30
+ s.files = `git ls-files`.split("\n")
31
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
32
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
33
+ s.require_paths = ["lib"]
34
+ end
metadata ADDED
@@ -0,0 +1,182 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: warden-bootic
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Ismael Celis
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-12-31 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: json
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: "1.5"
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: warden
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: 1.0.4
35
+ type: :runtime
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: oauth2
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.4.1
46
+ type: :runtime
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: rake
50
+ prerelease: false
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ type: :development
58
+ version_requirements: *id004
59
+ - !ruby/object:Gem::Dependency
60
+ name: rspec
61
+ prerelease: false
62
+ requirement: &id005 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ~>
66
+ - !ruby/object:Gem::Version
67
+ version: 1.3.0
68
+ type: :development
69
+ version_requirements: *id005
70
+ - !ruby/object:Gem::Dependency
71
+ name: shotgun
72
+ prerelease: false
73
+ requirement: &id006 !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ type: :development
80
+ version_requirements: *id006
81
+ - !ruby/object:Gem::Dependency
82
+ name: bundler
83
+ prerelease: false
84
+ requirement: &id007 !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: "1.0"
90
+ type: :development
91
+ version_requirements: *id007
92
+ - !ruby/object:Gem::Dependency
93
+ name: addressable
94
+ prerelease: false
95
+ requirement: &id008 !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ~>
99
+ - !ruby/object:Gem::Version
100
+ version: 2.2.0
101
+ type: :development
102
+ version_requirements: *id008
103
+ - !ruby/object:Gem::Dependency
104
+ name: rack-test
105
+ prerelease: false
106
+ requirement: &id009 !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ~>
110
+ - !ruby/object:Gem::Version
111
+ version: 0.5.3
112
+ type: :development
113
+ version_requirements: *id009
114
+ - !ruby/object:Gem::Dependency
115
+ name: ruby-debug
116
+ prerelease: false
117
+ requirement: &id010 !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: "0"
123
+ type: :development
124
+ version_requirements: *id010
125
+ description: A warden strategy for easy oauth integration with Bootic
126
+ email:
127
+ - ismael@bootic.net
128
+ executables: []
129
+
130
+ extensions: []
131
+
132
+ extra_rdoc_files: []
133
+
134
+ files:
135
+ - .gitignore
136
+ - Gemfile
137
+ - LICENSE
138
+ - README.md
139
+ - Rakefile
140
+ - config.ru
141
+ - lib/warden-bootic.rb
142
+ - lib/warden-bootic/proxy.rb
143
+ - lib/warden-bootic/strategy.rb
144
+ - lib/warden-bootic/user.rb
145
+ - lib/warden-bootic/version.rb
146
+ - spec/app.rb
147
+ - spec/oauth_spec.rb
148
+ - spec/proxy_spec.rb
149
+ - spec/spec_helper.rb
150
+ - warden-bootic.gemspec
151
+ homepage: http://github.com/ismasan/warden-bootic
152
+ licenses: []
153
+
154
+ post_install_message:
155
+ rdoc_options: []
156
+
157
+ require_paths:
158
+ - lib
159
+ required_ruby_version: !ruby/object:Gem::Requirement
160
+ none: false
161
+ requirements:
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ version: "0"
165
+ required_rubygems_version: !ruby/object:Gem::Requirement
166
+ none: false
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: "0"
171
+ requirements: []
172
+
173
+ rubyforge_project: warden-bootic
174
+ rubygems_version: 1.8.6
175
+ signing_key:
176
+ specification_version: 3
177
+ summary: A warden strategy for easy oauth integration with Bootic
178
+ test_files:
179
+ - spec/app.rb
180
+ - spec/oauth_spec.rb
181
+ - spec/proxy_spec.rb
182
+ - spec/spec_helper.rb