bsm-sso-client 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.
@@ -0,0 +1 @@
1
+ require 'bsm/sso/client'
@@ -0,0 +1,57 @@
1
+ require 'rails'
2
+ require 'active_support/core_ext/numeric/time'
3
+ require 'active_support/dependencies'
4
+ require 'active_resource'
5
+ require 'action_controller'
6
+ require 'rails_warden'
7
+
8
+ module Bsm
9
+ module Sso
10
+ module Client
11
+ autoload :User, 'bsm/sso/client/user'
12
+ autoload :UserMethods, 'bsm/sso/client/user_methods'
13
+ autoload :UrlHelpers, 'bsm/sso/client/url_helpers'
14
+ autoload :FailureApp, 'bsm/sso/client/failure_app'
15
+
16
+ mattr_accessor :secret
17
+ @@secret = nil
18
+
19
+ mattr_accessor :expire_after
20
+ @@expire_after = 2.hours
21
+
22
+ mattr_writer :user_class
23
+ @@user_class = nil
24
+
25
+ class << self
26
+
27
+ delegate :site=, :site, :to => :"Bsm::Sso::Client::User"
28
+
29
+ def user_class
30
+ @@user_class || Bsm::Sso::Client::User
31
+ end
32
+
33
+ # Default message verifier
34
+ def verifier
35
+ raise "Please configure a secret! Example: Bsm::Sso::Client.secret = '...'" unless secret.present?
36
+ @verifier ||= ActiveSupport::MessageVerifier.new(secret)
37
+ end
38
+
39
+ # Configure the SSO. Example:
40
+ #
41
+ # # config/initializers/sso.rb
42
+ # Bsm::Sso::Client.configure do |c|
43
+ # c.site = "https://sso.example.com"
44
+ # c.secret = "m4GHRWxvXiL3ZSR8adShpqNWXmepkqeyUqRfpB8F"
45
+ # end
46
+ def configure(&block)
47
+ tap(&block)
48
+ end
49
+
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ require 'bsm/sso/client/railtie'
56
+ require 'bsm/sso/client/warden_ext'
57
+ require 'bsm/sso/client/strategies'
@@ -0,0 +1,41 @@
1
+ class Bsm::Sso::Client::FailureApp < ActionController::Metal
2
+ include ActionController::RackDelegation
3
+ include ActionController::Redirecting
4
+ include Bsm::Sso::Client::UrlHelpers
5
+
6
+ NAVIGATIONAL_FORMATS = [:html, :all, :js, nil].to_set.freeze
7
+ UnauthorizedAccess = Class.new(ActionController::ActionControllerError)
8
+
9
+ def self.call(env)
10
+ action(:respond).call(env)
11
+ end
12
+
13
+ def self.default_url_options(*args)
14
+ ApplicationController.default_url_options(*args)
15
+ end
16
+
17
+ def respond
18
+ if NAVIGATIONAL_FORMATS.include?(request.format.try(:to_sym))
19
+ request.xhr? ? respond_with_js! : redirect!
20
+ else
21
+ stop!
22
+ end
23
+ end
24
+
25
+ def redirect!
26
+ redirect_to Bsm::Sso::Client.user_class.sign_in_url(:service => service_url(env["warden.options"][:attempted_path])), :status => 303
27
+ end
28
+
29
+ def respond_with_js!
30
+ self.status = :ok
31
+ self.content_type = request.format.to_s
32
+ self.response_body = "alert('Your session has expired');"
33
+ end
34
+
35
+ # Throws UnauthorizedAccess (rescued as 403 Forbidden response)
36
+ def stop!(message = nil)
37
+ message ||= "You are not permitted to access the resource in #{request.path}"
38
+ raise UnauthorizedAccess, message
39
+ end
40
+
41
+ end
@@ -0,0 +1,31 @@
1
+ require 'bsm/sso/client'
2
+ require 'rails'
3
+
4
+ class Bsm::Sso::Client::Railtie < ::Rails::Railtie
5
+
6
+ initializer "bsm-sso.insert_middleware" do |app|
7
+ Bsm::Sso::Client::Railtie.insert_middleware!(app)
8
+ end
9
+
10
+ config.after_initialize do
11
+ Bsm::Sso::Client::Railtie.handle_exceptions!
12
+ end
13
+
14
+ def self.insert_middleware!(app)
15
+ app.config.middleware.use RailsWarden::Manager do |manager|
16
+ manager.default_strategies :sso_ticket, :sso_http_auth
17
+ manager.failure_app = Bsm::Sso::Client::FailureApp
18
+ end
19
+ end
20
+
21
+ def self.handle_exceptions!
22
+ return unless defined?(::ActionDispatch::ShowExceptions)
23
+ ActionDispatch::ShowExceptions.rescue_responses.update("Bsm::Sso::Client::FailureApp::UnauthorizedAccess" => :forbidden)
24
+ end
25
+
26
+ def self.plugin!(app)
27
+ insert_middleware!(app)
28
+ handle_exceptions!
29
+ end
30
+
31
+ end
@@ -0,0 +1,6 @@
1
+ module Bsm::Sso::Client::Strategies
2
+ end
3
+
4
+ require 'bsm/sso/client/strategies/base'
5
+ require 'bsm/sso/client/strategies/ticket'
6
+ require 'bsm/sso/client/strategies/http_auth'
@@ -0,0 +1,7 @@
1
+ class Bsm::Sso::Client::Strategies::Base < ::Warden::Strategies::Base
2
+
3
+ def user_class
4
+ Bsm::Sso::Client.user_class
5
+ end
6
+
7
+ end
@@ -0,0 +1,23 @@
1
+ class Bsm::Sso::Client::Strategies::HttpAuth < Bsm::Sso::Client::Strategies::Base
2
+
3
+ def store?
4
+ false
5
+ end
6
+
7
+ def valid?
8
+ token.present?
9
+ end
10
+
11
+ def authenticate!
12
+ u = user_class.authorize(token)
13
+ u.nil? ? fail!(:invalid) : success!(u)
14
+ end
15
+
16
+ def token
17
+ return nil unless request.authorization && request.authorization =~ /^Basic (.*)/m
18
+ @token ||= ActiveSupport::Base64.decode64($1).split(/:/, 2).first
19
+ end
20
+
21
+ Warden::Strategies.add :sso_http_auth, self
22
+
23
+ end
@@ -0,0 +1,14 @@
1
+ class Bsm::Sso::Client::Strategies::Ticket < Bsm::Sso::Client::Strategies::Base
2
+ include Bsm::Sso::Client::UrlHelpers
3
+
4
+ def valid?
5
+ params[:ticket].present?
6
+ end
7
+
8
+ def authenticate!
9
+ u = user_class.consume(params[:ticket], service_url)
10
+ u.nil? ? fail!(:invalid) : success!(u)
11
+ end
12
+
13
+ Warden::Strategies.add :sso_ticket, self
14
+ end
@@ -0,0 +1,12 @@
1
+ require 'active_support/core_ext/string/encoding'
2
+
3
+
4
+ module Bsm::Sso::Client::UrlHelpers
5
+
6
+ def service_url(path = request.fullpath)
7
+ part = Regexp.escape params.slice(:ticket).to_query
8
+ request.base_url + path.sub(/#{part}\&?/, '').chomp("&").chomp("?")
9
+ end
10
+
11
+ end
12
+
@@ -0,0 +1,45 @@
1
+ class Bsm::Sso::Client::User < ActiveResource::Base
2
+ self.format = :json
3
+
4
+ class << self
5
+
6
+ def headers
7
+ { 'AUTHORIZATION' => Bsm::Sso::Client.verifier.generate(30.seconds.from_now) }
8
+ end
9
+
10
+ def consume(ticket, service)
11
+ # TODO rename Sso endpoint to /validate
12
+ find :one, :from => '/validate', :params => { :ticket => ticket, :service => service }
13
+ rescue ActiveResource::ResourceInvalid
14
+ nil
15
+ end
16
+
17
+ def authorize(token)
18
+ find :one, :from => '/authorize', :params => { :auth_token => token }
19
+ rescue ActiveResource::ResourceInvalid
20
+ nil
21
+ end
22
+
23
+ def authenticate(credentials)
24
+ find :one, :from => "/authenticate", :params => credentials.slice(:email, :password)
25
+ rescue ActiveResource::ResourceInvalid
26
+ nil
27
+ end
28
+
29
+ def sign_in_url(params = {})
30
+ custom_absolute_method_root_url(:sign_in, params)
31
+ end
32
+
33
+ def sign_out_url(params = {})
34
+ custom_absolute_method_root_url(:sign_out, params)
35
+ end
36
+
37
+ private
38
+
39
+ def custom_absolute_method_root_url(method_name, params = {})
40
+ "#{site.to_s.chomp('/')}/#{method_name}#{query_string(params)}"
41
+ end
42
+
43
+ end
44
+ end
45
+
@@ -0,0 +1,29 @@
1
+ module Bsm::Sso::Client::UserMethods
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ class << self
6
+ delegate :sign_in_url, :sign_out_url, :to => :"Bsm::Sso::Client::User"
7
+ end
8
+ end
9
+
10
+ module ClassMethods
11
+
12
+ def consume(*a)
13
+ result = Bsm::Sso::Client::User.consume(*a)
14
+ new(result.attributes) if result
15
+ end
16
+
17
+ def authenticate(*a)
18
+ result = Bsm::Sso::Client::User.authenticate(*a)
19
+ new(result.attributes) if result
20
+ end
21
+
22
+ def authorize(*a)
23
+ result = Bsm::Sso::Client::User.authorize(*a)
24
+ new(result.attributes) if result
25
+ end
26
+
27
+ end
28
+ end
29
+
@@ -0,0 +1,11 @@
1
+ class Warden::SessionSerializer
2
+
3
+ def serialize(record)
4
+ record.id
5
+ end
6
+
7
+ def deserialize(id)
8
+ Bsm::Sso::Client.user_class.find(id)
9
+ end
10
+
11
+ end
metadata ADDED
@@ -0,0 +1,164 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bsm-sso-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Dimitrij Denissenko
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-21 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activeresource
16
+ requirement: &25666220 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 3.0.0
22
+ - - <
23
+ - !ruby/object:Gem::Version
24
+ version: 3.2.0
25
+ type: :runtime
26
+ prerelease: false
27
+ version_requirements: *25666220
28
+ - !ruby/object:Gem::Dependency
29
+ name: actionpack
30
+ requirement: &25665200 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: 3.0.0
36
+ - - <
37
+ - !ruby/object:Gem::Version
38
+ version: 3.2.0
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: *25665200
42
+ - !ruby/object:Gem::Dependency
43
+ name: railties
44
+ requirement: &25663920 !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ! '>='
48
+ - !ruby/object:Gem::Version
49
+ version: 3.0.0
50
+ - - <
51
+ - !ruby/object:Gem::Version
52
+ version: 3.2.0
53
+ type: :runtime
54
+ prerelease: false
55
+ version_requirements: *25663920
56
+ - !ruby/object:Gem::Dependency
57
+ name: rails_warden
58
+ requirement: &25662760 !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ~>
62
+ - !ruby/object:Gem::Version
63
+ version: 0.5.0
64
+ type: :runtime
65
+ prerelease: false
66
+ version_requirements: *25662760
67
+ - !ruby/object:Gem::Dependency
68
+ name: rake
69
+ requirement: &25648320 !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: *25648320
78
+ - !ruby/object:Gem::Dependency
79
+ name: rack-test
80
+ requirement: &25646620 !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: *25646620
89
+ - !ruby/object:Gem::Dependency
90
+ name: rspec
91
+ requirement: &25646200 !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ type: :development
98
+ prerelease: false
99
+ version_requirements: *25646200
100
+ - !ruby/object:Gem::Dependency
101
+ name: shoulda-matchers
102
+ requirement: &25645560 !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ! '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ type: :development
109
+ prerelease: false
110
+ version_requirements: *25645560
111
+ - !ruby/object:Gem::Dependency
112
+ name: webmock
113
+ requirement: &25644920 !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ! '>='
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: *25644920
122
+ description: ''
123
+ email: dimitrij@blacksquaremedia.com
124
+ executables: []
125
+ extensions: []
126
+ extra_rdoc_files: []
127
+ files:
128
+ - lib/bsm/sso/client.rb
129
+ - lib/bsm/sso/client/strategies/ticket.rb
130
+ - lib/bsm/sso/client/strategies/base.rb
131
+ - lib/bsm/sso/client/strategies/http_auth.rb
132
+ - lib/bsm/sso/client/failure_app.rb
133
+ - lib/bsm/sso/client/railtie.rb
134
+ - lib/bsm/sso/client/user_methods.rb
135
+ - lib/bsm/sso/client/url_helpers.rb
136
+ - lib/bsm/sso/client/user.rb
137
+ - lib/bsm/sso/client/warden_ext.rb
138
+ - lib/bsm/sso/client/strategies.rb
139
+ - lib/bsm-sso-client.rb
140
+ homepage: https://github.com/bsm/sso-client
141
+ licenses: []
142
+ post_install_message:
143
+ rdoc_options: []
144
+ require_paths:
145
+ - lib
146
+ required_ruby_version: !ruby/object:Gem::Requirement
147
+ none: false
148
+ requirements:
149
+ - - ! '>='
150
+ - !ruby/object:Gem::Version
151
+ version: 1.8.7
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: 1.3.6
158
+ requirements: []
159
+ rubyforge_project:
160
+ rubygems_version: 1.8.10
161
+ signing_key:
162
+ specification_version: 3
163
+ summary: BSM's internal SSO client
164
+ test_files: []