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.
- data/lib/bsm-sso-client.rb +1 -0
- data/lib/bsm/sso/client.rb +57 -0
- data/lib/bsm/sso/client/failure_app.rb +41 -0
- data/lib/bsm/sso/client/railtie.rb +31 -0
- data/lib/bsm/sso/client/strategies.rb +6 -0
- data/lib/bsm/sso/client/strategies/base.rb +7 -0
- data/lib/bsm/sso/client/strategies/http_auth.rb +23 -0
- data/lib/bsm/sso/client/strategies/ticket.rb +14 -0
- data/lib/bsm/sso/client/url_helpers.rb +12 -0
- data/lib/bsm/sso/client/user.rb +45 -0
- data/lib/bsm/sso/client/user_methods.rb +29 -0
- data/lib/bsm/sso/client/warden_ext.rb +11 -0
- metadata +164 -0
@@ -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,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
|
+
|
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: []
|