doorkeeper_sso_client 0.4.6 → 0.4.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/doorkeeper_sso_client.rb +0 -2
- data/lib/doorkeeper_sso_client/mixins/devise/controller_helpers.rb +4 -0
- data/lib/doorkeeper_sso_client/version.rb +1 -1
- data/spec/lib/doorkeeper_sso_client/mixins/devise/controller_helper_spec.rb +4 -0
- data/spec/models/passport_spec.rb +17 -1
- metadata +2 -4
- data/lib/doorkeeper_sso_client/passport_verifier.rb +0 -146
- data/lib/doorkeeper_sso_client/warden/hooks/after_fetch.rb +0 -134
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e39b15ab6dd20ae730f58de5e82d046a49eadb72
|
4
|
+
data.tar.gz: b5a888aeca2850a2f10f65a248d620ae887bef95
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83316a1e64626bad774180b1b8ad8dbe824b50448fde2c2f37b87e073a14c4f172a01d04414b868018905070947d46c506c70dcaeafd4b1dc36a67dcd27f9b57
|
7
|
+
data.tar.gz: 97937dfdb0942e6e278e91557e5029471952ab96f5378e345df7775023411a9d2da86671f40719b62ab31f018ba45c12af81d3d9696de3d23c34592a08b1f97d
|
@@ -3,9 +3,7 @@ require 'doorkeeper_sso_client/mixins'
|
|
3
3
|
require "doorkeeper_sso_client/engine"
|
4
4
|
require 'doorkeeper_sso_client/config'
|
5
5
|
require 'doorkeeper_sso_client/logging'
|
6
|
-
require 'doorkeeper_sso_client/passport_verifier'
|
7
6
|
require 'doorkeeper_sso_client/warden/support'
|
8
|
-
require 'doorkeeper_sso_client/warden/hooks/after_fetch'
|
9
7
|
require 'doorkeeper_sso_client/version'
|
10
8
|
require 'omniauth/strategies/doorkeeper_sso'
|
11
9
|
|
@@ -27,6 +27,10 @@ module DoorkeeperSsoClient
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
def after_omniauth_failure_path_for(scope)
|
31
|
+
return File.join( DoorkeeperSsoClient::Config.base_uri, "logout?app_id=" + DoorkeeperSsoClient::Config.oauth_client_id.to_s )
|
32
|
+
end
|
33
|
+
|
30
34
|
def sign_out(resource_or_scope=nil)
|
31
35
|
return sign_out_all_scopes unless resource_or_scope
|
32
36
|
if scope_match? resource_or_scope, :#{scope}
|
@@ -53,6 +53,10 @@ RSpec.describe "DoorkeeperSsoClient::Mixins::Devise::ControllerHelpers DeviseHoo
|
|
53
53
|
it { expect(controller.after_sign_out_path_for(:user)).to eq "http://sso_server.com/logout?app_id=123" }
|
54
54
|
end
|
55
55
|
|
56
|
+
describe "#after_omniauth_failure_path_for" do
|
57
|
+
# Will redirect to sso server to completely logout user
|
58
|
+
it { expect(controller.after_omniauth_failure_path_for(:ANYSCOPE)).to eq "http://sso_server.com/logout?app_id=123" }
|
59
|
+
end
|
56
60
|
|
57
61
|
describe "#after_sign_in_path_for" do
|
58
62
|
# Will redirect to request.env['omniauth.origin']
|
@@ -52,7 +52,23 @@ RSpec.describe DoorkeeperSsoClient::Passport, :type => :model do
|
|
52
52
|
it { expect(fetched_passport.uid).to eq passport_uid }
|
53
53
|
it { expect(fetched_passport.token).to eq token }
|
54
54
|
end
|
55
|
-
|
56
55
|
end
|
57
56
|
|
57
|
+
|
58
|
+
describe "#update_from_pingback" do
|
59
|
+
subject(:passport) { Fabricate("DoorkeeperSsoClient::Passport") }
|
60
|
+
let(:the_time) { Time.now }
|
61
|
+
let(:pingback_data) {
|
62
|
+
HashWithIndifferentAccess.new(
|
63
|
+
revoked_at: the_time,
|
64
|
+
revoke_reason: 'logout',
|
65
|
+
activity_at: the_time
|
66
|
+
)
|
67
|
+
}
|
68
|
+
|
69
|
+
before() { passport.update_from_pingback(pingback_data) }
|
70
|
+
it { expect(passport.revoked_at).to eq the_time }
|
71
|
+
it { expect(passport.revoke_reason).to eq 'logout' }
|
72
|
+
it { expect(passport.last_login_at).to eq the_time }
|
73
|
+
end
|
58
74
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: doorkeeper_sso_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Wong
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-08-
|
11
|
+
date: 2015-08-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: omniauth
|
@@ -348,9 +348,7 @@ files:
|
|
348
348
|
- lib/doorkeeper_sso_client/mixins/devise/test_helpers.rb
|
349
349
|
- lib/doorkeeper_sso_client/mixins/mongoid/passport.rb
|
350
350
|
- lib/doorkeeper_sso_client/mixins/passport_base.rb
|
351
|
-
- lib/doorkeeper_sso_client/passport_verifier.rb
|
352
351
|
- lib/doorkeeper_sso_client/version.rb
|
353
|
-
- lib/doorkeeper_sso_client/warden/hooks/after_fetch.rb
|
354
352
|
- lib/doorkeeper_sso_client/warden/support.rb
|
355
353
|
- lib/omniauth/strategies/doorkeeper_sso.rb
|
356
354
|
- lib/tasks/doorkeeper_sso_client_tasks.rake
|
@@ -1,146 +0,0 @@
|
|
1
|
-
module DoorkeeperSsoClient
|
2
|
-
class PassportVerifier
|
3
|
-
|
4
|
-
attr_reader :passport_id, :passport_state, :passport_secret, :user_ip, :user_agent, :device_id
|
5
|
-
|
6
|
-
def initialize(options = {})
|
7
|
-
options = ActionController::Parameters.new(options)
|
8
|
-
options.require(:passport_id, :passport_state, :passport_secret, :user_ip)
|
9
|
-
options.permit(:user_agent, :device_id)
|
10
|
-
|
11
|
-
options.each { |k,v| instance_variable_set("@#{k}",v) }
|
12
|
-
end
|
13
|
-
|
14
|
-
def call
|
15
|
-
fetch_response { |failure| return failure }
|
16
|
-
interpret_response
|
17
|
-
|
18
|
-
rescue ::JSON::ParserError
|
19
|
-
error { 'SSO Server response is not valid JSON.' }
|
20
|
-
error { response.inspect }
|
21
|
-
Operations.failure :server_response_not_parseable, object: response
|
22
|
-
end
|
23
|
-
|
24
|
-
def human_readable_timeout_in_ms
|
25
|
-
"#{timeout_in_milliseconds}ms"
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def fetch_response
|
31
|
-
yield Operations.failure(:server_unreachable, object: response) unless response.code.to_s == '200'
|
32
|
-
yield Operations.failure(:server_response_not_parseable, object: response) unless parsed_response
|
33
|
-
yield Operations.failure(:server_response_missing_success_flag, object: response) unless response_has_success_flag?
|
34
|
-
Operations.success :server_response_looks_legit
|
35
|
-
end
|
36
|
-
|
37
|
-
def interpret_response
|
38
|
-
debug { "Interpreting response code #{response_code.inspect}" }
|
39
|
-
|
40
|
-
case response_code
|
41
|
-
when :passpord_unmodified then Operations.success(:passport_valid)
|
42
|
-
when :passport_changed then Operations.success(:passport_valid_and_modified, object: received_passport)
|
43
|
-
when :passport_invalid then Operations.failure(:passport_invalid)
|
44
|
-
else Operations.failure(:unexpected_server_response_status, object: response)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def response_code
|
49
|
-
return :unknown_response_code if parsed_response['code'].to_s == ''
|
50
|
-
parsed_response['code'].to_s.to_sym
|
51
|
-
end
|
52
|
-
|
53
|
-
def received_passport
|
54
|
-
::DoorkeeperSsoClient::Passport.new received_passport_attributes
|
55
|
-
|
56
|
-
rescue ArgumentError
|
57
|
-
error { "Could not instantiate Passport from serialized response #{received_passport_attributes.inspect}" }
|
58
|
-
raise
|
59
|
-
end
|
60
|
-
|
61
|
-
def received_passport_attributes
|
62
|
-
attributes = parsed_response['passport']
|
63
|
-
attributes.keys.each do |key|
|
64
|
-
attributes[(key.to_sym rescue key) || key] = attributes.delete(key)
|
65
|
-
end
|
66
|
-
attributes
|
67
|
-
end
|
68
|
-
|
69
|
-
def params
|
70
|
-
result = { ip: user_ip, agent: user_agent, device_id: device_id, state: passport_state }
|
71
|
-
result.merge! insider_id: insider_id, insider_signature: insider_signature
|
72
|
-
result
|
73
|
-
end
|
74
|
-
|
75
|
-
def insider_id
|
76
|
-
::Sso.config.oauth_client_id
|
77
|
-
end
|
78
|
-
|
79
|
-
def insider_secret
|
80
|
-
::Sso.config.oauth_client_secret
|
81
|
-
end
|
82
|
-
|
83
|
-
def insider_signature
|
84
|
-
::OpenSSL::HMAC.hexdigest signature_digest, insider_secret, user_ip
|
85
|
-
end
|
86
|
-
|
87
|
-
def signature_digest
|
88
|
-
OpenSSL::Digest.new 'sha1'
|
89
|
-
end
|
90
|
-
|
91
|
-
def token
|
92
|
-
Signature::Token.new passport_id, passport_secret
|
93
|
-
end
|
94
|
-
|
95
|
-
def signature_request
|
96
|
-
Signature::Request.new('GET', path, params)
|
97
|
-
end
|
98
|
-
|
99
|
-
def auth_hash
|
100
|
-
signature_request.sign token
|
101
|
-
end
|
102
|
-
|
103
|
-
def timeout_in_milliseconds
|
104
|
-
::Sso.config.passport_verification_timeout_ms.to_i
|
105
|
-
end
|
106
|
-
|
107
|
-
def timeout_in_seconds
|
108
|
-
(timeout_in_milliseconds / 1000).round 2
|
109
|
-
end
|
110
|
-
|
111
|
-
# TODO: Needs to be configurable
|
112
|
-
def path
|
113
|
-
::OmniAuth::Strategies::DoorkeeperSso.sessions_path
|
114
|
-
end
|
115
|
-
|
116
|
-
def base_endpoint
|
117
|
-
::OmniAuth::Strategies::DoorkeeperSso.endpoint
|
118
|
-
end
|
119
|
-
|
120
|
-
def endpoint
|
121
|
-
URI.join(base_endpoint, path).to_s
|
122
|
-
end
|
123
|
-
|
124
|
-
def query_params
|
125
|
-
params.merge auth_hash
|
126
|
-
end
|
127
|
-
|
128
|
-
def response
|
129
|
-
@response ||= response!
|
130
|
-
end
|
131
|
-
|
132
|
-
def response!
|
133
|
-
debug { "Fetching Passport from #{endpoint.inspect}" }
|
134
|
-
::HTTParty.get endpoint, timeout: timeout_in_seconds, query: query_params, headers: { 'Accept' => 'application/json' }
|
135
|
-
end
|
136
|
-
|
137
|
-
def parsed_response
|
138
|
-
response.parsed_response
|
139
|
-
end
|
140
|
-
|
141
|
-
def response_has_success_flag?
|
142
|
-
parsed_response && parsed_response.respond_to?(:key?) && (parsed_response.key?('success') || parsed_response.key?(:success))
|
143
|
-
end
|
144
|
-
|
145
|
-
end
|
146
|
-
end
|
@@ -1,134 +0,0 @@
|
|
1
|
-
module DoorkeeperSsoClient
|
2
|
-
module Warden
|
3
|
-
module Hooks
|
4
|
-
# This is a helpful `Warden::Manager.after_fetch` hook for Alpha and Beta.
|
5
|
-
# Whenever Carol is fetched out of the session, we also verify her resource.
|
6
|
-
#
|
7
|
-
# Usage:
|
8
|
-
#
|
9
|
-
# SSO::Client::Warden::Hooks::AfterFetch.activate scope: :vip
|
10
|
-
#
|
11
|
-
class AfterFetch
|
12
|
-
include ::DoorkeeperSsoClient::Logging
|
13
|
-
|
14
|
-
attr_reader :resource, :warden, :options
|
15
|
-
delegate :request, to: :warden
|
16
|
-
delegate :params, to: :request
|
17
|
-
|
18
|
-
def self.activate(warden_options)
|
19
|
-
::Warden::Manager.after_fetch(warden_options) do |resource, warden, options|
|
20
|
-
self.new(resource, warden, options).call
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def initialize(resource, warden, options)
|
25
|
-
@resource, @warden, @options = resource, warden, options
|
26
|
-
end
|
27
|
-
|
28
|
-
def call
|
29
|
-
return unless resource.is_a?(Session)
|
30
|
-
verify
|
31
|
-
|
32
|
-
rescue ::Timeout::Error
|
33
|
-
error { 'SSO Server timed out. Continuing with last known authentication/authorization...' }
|
34
|
-
Operations.failure :server_request_timed_out
|
35
|
-
|
36
|
-
rescue => exception
|
37
|
-
raise exception
|
38
|
-
Operations.failure :client_exception_caught
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
def verifier
|
44
|
-
::DoorkeeperSsoClient::PassportVerifier.new resource_id: resource.id, resource_state: resource.state, resource_secret: resource.secret, user_ip: ip, user_agent: agent, device_id: device_id
|
45
|
-
end
|
46
|
-
|
47
|
-
def verification
|
48
|
-
@verification ||= verifier.call
|
49
|
-
end
|
50
|
-
|
51
|
-
def verification_code
|
52
|
-
verification.code
|
53
|
-
end
|
54
|
-
|
55
|
-
def verification_object
|
56
|
-
verification.object
|
57
|
-
end
|
58
|
-
|
59
|
-
def verify
|
60
|
-
debug { "Validating Passport #{resource.id.inspect} of logged in #{resource.user.class} in scope #{warden_scope.inspect}" }
|
61
|
-
|
62
|
-
case verification_code
|
63
|
-
when :server_unreachable then server_unreachable!
|
64
|
-
when :server_response_not_parseable then server_response_not_parseable!
|
65
|
-
when :server_response_missing_success_flag then server_response_missing_success_flag!
|
66
|
-
when :resource_valid then resource_valid!
|
67
|
-
when :resource_valid_and_modified then resource_valid_and_modified!(verification.object)
|
68
|
-
when :resource_invalid then resource_invalid!
|
69
|
-
else unexpected_server_response_status!
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def resource_valid_and_modified!(modified_resource)
|
74
|
-
debug { 'Valid resource, but state changed' }
|
75
|
-
resource.verified!
|
76
|
-
resource.modified!
|
77
|
-
resource.user = modified_resource.user
|
78
|
-
resource.state = modified_resource.state
|
79
|
-
Operations.success :valid_and_modified
|
80
|
-
end
|
81
|
-
|
82
|
-
def resource_valid!
|
83
|
-
debug { 'Valid resource, no changes' }
|
84
|
-
resource.verified!
|
85
|
-
Operations.success :valid
|
86
|
-
end
|
87
|
-
|
88
|
-
def resource_invalid!
|
89
|
-
info { 'Your Passport is not valid any more.' }
|
90
|
-
warden.logout warden_scope
|
91
|
-
Operations.failure :invalid
|
92
|
-
end
|
93
|
-
|
94
|
-
def server_unreachable!
|
95
|
-
error { "SSO Server responded with an unexpected HTTP status code (#{verification_code.inspect} instead of 200). #{verification_object.inspect}" }
|
96
|
-
Operations.failure :server_unreachable
|
97
|
-
end
|
98
|
-
|
99
|
-
def server_response_missing_success_flag!
|
100
|
-
error { 'SSO Server response did not include the expected success flag.' }
|
101
|
-
Operations.failure :server_response_missing_success_flag
|
102
|
-
end
|
103
|
-
|
104
|
-
def unexpected_server_response_status!
|
105
|
-
error { "SSO Server response did not include a known resource status code. #{verification_code.inspect}" }
|
106
|
-
Operations.failure :unexpected_server_response_status
|
107
|
-
end
|
108
|
-
|
109
|
-
def server_response_not_parseable!
|
110
|
-
error { 'SSO Server response could not be parsed at all.' }
|
111
|
-
Operations.failure :server_response_not_parseable
|
112
|
-
end
|
113
|
-
|
114
|
-
# TODO: Use ActionDispatch remote IP or you might get the Load Balancer's IP instead :(
|
115
|
-
def ip
|
116
|
-
request.ip
|
117
|
-
end
|
118
|
-
|
119
|
-
def agent
|
120
|
-
request.user_agent
|
121
|
-
end
|
122
|
-
|
123
|
-
def device_id
|
124
|
-
params['device_id']
|
125
|
-
end
|
126
|
-
|
127
|
-
def warden_scope
|
128
|
-
options[:scope]
|
129
|
-
end
|
130
|
-
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|