warden-bootic 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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