doorkeeper_sso 0.4.1 → 0.4.3
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.
- checksums.yaml +4 -4
- data/app/models/sso/pingback.rb +1 -12
- data/lib/sso.rb +4 -3
- data/lib/sso/doorkeeper/application_controller_mixin.rb +43 -0
- data/lib/sso/doorkeeper/authorization.rb +10 -0
- data/lib/sso/doorkeeper/authorization/code_mixin.rb +0 -4
- data/lib/sso/doorkeeper/authorization/token_mixin.rb +1 -4
- data/lib/sso/doorkeeper/oauth.rb +10 -0
- data/lib/sso/doorkeeper/oauth/authorization_code_request_mixin.rb +13 -0
- data/lib/sso/doorkeeper/oauth/base.rb +22 -0
- data/lib/sso/engine.rb +24 -7
- data/lib/sso/engine.rb.orig +71 -0
- data/lib/sso/version.rb +1 -1
- data/lib/sso/warden/hooks/before_logout.rb +1 -0
- data/lib/sso/warden/hooks/create_master_session.rb +8 -5
- data/spec/lib/sso/warden/hooks/before_logout_spec.rb +6 -1
- data/spec/lib/sso/warden/hooks/create_master_session_spec.rb +7 -15
- data/spec/request/oauth/authorization_code_spec.rb +122 -0
- metadata +10 -9
- data/lib/doorkeeper/oauth/request_concern.rb +0 -12
- data/lib/sso/doorkeeper/authorizations_controller_mixin.rb +0 -48
- data/lib/sso/doorkeeper/tokens_controller_mixin.rb +0 -55
- data/spec/lib/doorkeeper/authorizations_controller_mixin_spec.rb +0 -65
- data/spec/lib/doorkeeper/tokens_controller_mixin_spec.rb +0 -72
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ca0ce3b31e9f84891cca3a72dddd92d8b401bf2
|
4
|
+
data.tar.gz: 926a26fbbec7d49bb05a2b71fd4db19f85a6f5fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b96c999fe8b444644bc6b1c5faa131d7f0950a4e391da11ab6a71a0255ec58538dd4636887965fb4542a20f3b550718117bda9d9c8a9a27dcacc66a8e43b645
|
7
|
+
data.tar.gz: 32e6a6a7460f9c5b2e37901f637ad5db92afe1ff4c29e573ee1efe0a620c7ddf204b603b4c5aec7fe22375b7274c03180e29cb702c51b30b23f84be46c976d44
|
data/app/models/sso/pingback.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Sso
|
2
2
|
class Pingback
|
3
3
|
include ::Sso::Logging
|
4
|
+
include ::Sso::Warden::Support
|
4
5
|
|
5
6
|
attr_reader :user, :warden, :options
|
6
7
|
delegate :request, to: :warden
|
@@ -32,17 +33,5 @@ module Sso
|
|
32
33
|
end
|
33
34
|
end
|
34
35
|
end
|
35
|
-
|
36
|
-
def scope
|
37
|
-
scope = options[:scope]
|
38
|
-
end
|
39
|
-
|
40
|
-
def session
|
41
|
-
warden.session(scope)
|
42
|
-
end
|
43
|
-
|
44
|
-
def logged_in?
|
45
|
-
warden.authenticated?(scope) && session && user
|
46
|
-
end
|
47
36
|
end
|
48
37
|
end
|
data/lib/sso.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require "doorkeeper/oauth/request_concern"
|
2
1
|
require "sso/engine"
|
3
2
|
require "sso/logging"
|
4
3
|
require "sso/warden/support"
|
@@ -8,8 +7,9 @@ require "sso/warden/hooks/session_check"
|
|
8
7
|
require "sso/doorkeeper/access_grant_mixin"
|
9
8
|
require "sso/doorkeeper/access_token_mixin"
|
10
9
|
require "sso/doorkeeper/application_mixin"
|
11
|
-
require "sso/doorkeeper/
|
12
|
-
require "sso/doorkeeper/
|
10
|
+
require "sso/doorkeeper/application_controller_mixin"
|
11
|
+
require "sso/doorkeeper/authorization"
|
12
|
+
require "sso/doorkeeper/oauth"
|
13
13
|
|
14
14
|
|
15
15
|
module Sso
|
@@ -17,3 +17,4 @@ module Sso
|
|
17
17
|
'sso_'
|
18
18
|
end
|
19
19
|
end
|
20
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Sso
|
2
|
+
module Doorkeeper
|
3
|
+
module ApplicationControllerMixin
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
include ::Sso::Logging
|
6
|
+
|
7
|
+
included do
|
8
|
+
around_filter :subscribe_to_grant_creation
|
9
|
+
end
|
10
|
+
|
11
|
+
def subscribe_to_grant_creation
|
12
|
+
Wisper.subscribe(self) do
|
13
|
+
yield
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def warden_user_session
|
18
|
+
warden.session(:user)
|
19
|
+
end
|
20
|
+
|
21
|
+
def access_grant_created(token_id)
|
22
|
+
debug { "Wisper#access_grant_created grant - #{token_id}" }
|
23
|
+
oauth_grant = ::Doorkeeper::AccessGrant.find(token_id)
|
24
|
+
|
25
|
+
generate_sso_session if warden_user_session["sso_session_id"].blank?
|
26
|
+
sso_session = Sso::Session.find(warden_user_session["sso_session_id"])
|
27
|
+
|
28
|
+
debug { "Sso::Session.update_master_with_grant - #{sso_session.id.inspect}, #{oauth_grant.inspect}" }
|
29
|
+
sso_session.clients.find_or_create_by!(access_grant_id: oauth_grant.id, application_id: oauth_grant.application_id)
|
30
|
+
rescue => e
|
31
|
+
sso_session.try(:logout)
|
32
|
+
raise
|
33
|
+
end
|
34
|
+
|
35
|
+
def generate_sso_session
|
36
|
+
debug { "Sso:Session doesn't exist for user #{user.id.inspect}. Generate new one" }
|
37
|
+
attributes = { ip: request.ip, agent: request.user_agent }
|
38
|
+
sso_session = Sso::Session.generate_master(user, attributes)
|
39
|
+
warden_user_session["sso_session_id"] = sso_session.id.to_s
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -5,15 +5,11 @@ module Sso
|
|
5
5
|
module Doorkeeper
|
6
6
|
module Authorization
|
7
7
|
module CodeMixin
|
8
|
-
extend ActiveSupport::Concern
|
9
|
-
include ::Sso::Logging
|
10
|
-
|
11
8
|
def issue_token
|
12
9
|
super
|
13
10
|
broadcast(:access_grant_created, token.id) if @token.try(:id)
|
14
11
|
@token
|
15
12
|
end
|
16
|
-
|
17
13
|
end
|
18
14
|
end
|
19
15
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Sso
|
2
|
+
module Doorkeeper
|
3
|
+
module OAuth
|
4
|
+
module Base
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def sso_client
|
8
|
+
return @sso_client if @sso_client
|
9
|
+
|
10
|
+
user = User.find(@access_token.resource_owner_id)
|
11
|
+
sso_session = Sso::Session.generate_master(user, {})
|
12
|
+
@sso_client = sso_session.clients.last
|
13
|
+
end
|
14
|
+
|
15
|
+
def after_successful_response
|
16
|
+
self.sso_client.update_attributes(access_token_id: @access_token.id)
|
17
|
+
super
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/sso/engine.rb
CHANGED
@@ -22,14 +22,31 @@ module Sso
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
config.before_initialize do
|
26
|
+
[::Wisper::Publisher].each do |klass|
|
27
|
+
::Doorkeeper::OAuth::Authorization::Code.send(:include, klass)
|
28
|
+
::Doorkeeper::OAuth::Authorization::Token.send(:include, klass)
|
29
|
+
end
|
30
|
+
|
31
|
+
::Doorkeeper::ApplicationMetalController.send(:include, ::AbstractController::Callbacks)
|
32
|
+
end
|
33
|
+
|
25
34
|
config.after_initialize do
|
26
|
-
::Doorkeeper::
|
27
|
-
::Doorkeeper::
|
28
|
-
|
29
|
-
|
30
|
-
::Doorkeeper::
|
31
|
-
::Doorkeeper::
|
32
|
-
::Doorkeeper::
|
35
|
+
::Doorkeeper::OAuth::Authorization::Code.send(:prepend, ::Sso::Doorkeeper::Authorization::CodeMixin)
|
36
|
+
::Doorkeeper::OAuth::Authorization::Token.send(:prepend, ::Sso::Doorkeeper::Authorization::TokenMixin)
|
37
|
+
|
38
|
+
# Patch every class that includes RequestConcern
|
39
|
+
::Doorkeeper::OAuth::AuthorizationCodeRequest.send(:prepend, ::Sso::Doorkeeper::OAuth::AuthorizationCodeRequestMixin)
|
40
|
+
::Doorkeeper::OAuth::ClientCredentialsRequest.send(:include, ::Sso::Doorkeeper::OAuth::Base)
|
41
|
+
::Doorkeeper::OAuth::PasswordAccessTokenRequest.send(:include, ::Sso::Doorkeeper::OAuth::Base)
|
42
|
+
::Doorkeeper::OAuth::RefreshTokenRequest.send(:include, ::Sso::Doorkeeper::OAuth::Base)
|
43
|
+
|
44
|
+
::Doorkeeper::Application.send(:include, ::Sso::Doorkeeper::ApplicationMixin)
|
45
|
+
::Doorkeeper::AccessGrant.send(:include, ::Sso::Doorkeeper::AccessGrantMixin)
|
46
|
+
::Doorkeeper::AccessToken.send(:include, ::Sso::Doorkeeper::AccessTokenMixin)
|
47
|
+
|
48
|
+
::Doorkeeper::ApplicationController.send(:include, ::Sso::Doorkeeper::ApplicationControllerMixin)
|
49
|
+
# ::Doorkeeper::ApplicationMetalController.send(:include, ::Sso::Doorkeeper::ApplicationControllerMixin)
|
33
50
|
|
34
51
|
::Warden::Manager.after_set_user(scope: :user, except: :fetch, &::Sso::Warden::Hooks::CreateMasterSession.to_proc)
|
35
52
|
::Warden::Manager.before_logout(scope: :user, &::Sso::Warden::Hooks::BeforeLogout.to_proc)
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Sso
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
isolate_namespace Sso
|
4
|
+
|
5
|
+
# New test framework integration
|
6
|
+
config.generators do |g|
|
7
|
+
g.test_framework :rspec,
|
8
|
+
:fixtures => true,
|
9
|
+
:view_specs => false,
|
10
|
+
:helper_specs => false,
|
11
|
+
:routing_specs => false,
|
12
|
+
:controller_specs => true,
|
13
|
+
:request_specs => false
|
14
|
+
g.fixture_replacement :fabrication
|
15
|
+
end
|
16
|
+
|
17
|
+
initializer :append_migrations do |app|
|
18
|
+
unless app.root.to_s.match root.to_s
|
19
|
+
config.paths["db/migrate"].expanded.each do |expanded_path|
|
20
|
+
app.config.paths["db/migrate"] << expanded_path
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
config.before_initialize do
|
26
|
+
[::Sso::Logging, ::Wisper::Publisher].each do |klass|
|
27
|
+
::Doorkeeper::OAuth::RequestConcern.send(:include, klass)
|
28
|
+
::Doorkeeper::OAuth::Authorization::Code.send(:include, klass)
|
29
|
+
::Doorkeeper::OAuth::Authorization::Token.send(:include, klass)
|
30
|
+
end
|
31
|
+
|
32
|
+
::Doorkeeper::ApplicationMetalController.send(:include, ::AbstractController::Callbacks)
|
33
|
+
|
34
|
+
# need a better way to fix this
|
35
|
+
::Doorkeeper::OAuth::RequestConcern.class_eval do
|
36
|
+
def after_successful_response
|
37
|
+
raise "RequestConcern#token - #{@access_token.inspect}"
|
38
|
+
broadcast(:access_token_request_successful, @access_token.id)
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
config.after_initialize do
|
45
|
+
|
46
|
+
::Doorkeeper::OAuth::Authorization::Code.send(:prepend, ::Sso::Doorkeeper::Authorization::CodeMixin)
|
47
|
+
::Doorkeeper::OAuth::Authorization::Token.send(:prepend, ::Sso::Doorkeeper::Authorization::TokenMixin)
|
48
|
+
::Doorkeeper::Application.send(:include, ::Sso::Doorkeeper::ApplicationMixin)
|
49
|
+
::Doorkeeper::AccessGrant.send(:include, ::Sso::Doorkeeper::AccessGrantMixin)
|
50
|
+
::Doorkeeper::AccessToken.send(:include, ::Sso::Doorkeeper::AccessTokenMixin)
|
51
|
+
::Doorkeeper::ApplicationMetalController.send(:include, ::Sso::Doorkeeper::ApplicationControllerMixin)
|
52
|
+
::Doorkeeper::ApplicationController.send(:include, ::Sso::Doorkeeper::ApplicationControllerMixin)
|
53
|
+
# ::Doorkeeper::TokensController.send(:include, ::AbstractController::Callbacks)
|
54
|
+
# ::Doorkeeper::TokensController.send(:include, ::Sso::Doorkeeper::TokensControllerMixin)
|
55
|
+
# ::Doorkeeper::AuthorizationsController.send(:include, ::Sso::Doorkeeper::AuthorizationsControllerMixin)
|
56
|
+
|
57
|
+
<<<<<<< HEAD
|
58
|
+
::Warden::Manager.after_set_user(scope: :user, &::Sso::Warden::Hooks::CreateMasterSession.to_proc)
|
59
|
+
=======
|
60
|
+
>>>>>>> Use wisper to broadcast when token is created
|
61
|
+
::Warden::Manager.after_set_user(scope: :user, except: :fetch, &::Sso::Warden::Hooks::CreateMasterSession.to_proc)
|
62
|
+
::Warden::Manager.before_logout(scope: :user, &::Sso::Warden::Hooks::BeforeLogout.to_proc)
|
63
|
+
|
64
|
+
# TODO : Do we want to ensure that session is always active?
|
65
|
+
# ::Warden::Manager.after_fetch(scope: :user, &::Sso::Warden::Hooks::SessionCheck.to_proc)
|
66
|
+
|
67
|
+
# TODO : Why does it need a passport strategy
|
68
|
+
# Warden::Strategies.add :passport, ::Sso::Server::Warden::Strategies::Passport
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/sso/version.rb
CHANGED
@@ -5,12 +5,15 @@ module Sso
|
|
5
5
|
include ::Sso::Warden::Support
|
6
6
|
|
7
7
|
def call
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
::Sso::Session.logout(session["sso_session_id"])
|
12
|
-
generate_session
|
8
|
+
unless logged_in?
|
9
|
+
throw(:warden)
|
10
|
+
raise "DoorkeeperSso : CreateMasterSession requires an authenticated session" and return
|
13
11
|
end
|
12
|
+
|
13
|
+
debug { "NEW USER WARDEN SESSION" }
|
14
|
+
debug { "Log out previous Sso:Session if exists : ID #{session['sso_session_id']}" }
|
15
|
+
::Sso::Session.logout(session["sso_session_id"])
|
16
|
+
generate_session
|
14
17
|
return nil
|
15
18
|
end
|
16
19
|
|
@@ -32,7 +32,7 @@ RSpec.describe Sso::Warden::Hooks::BeforeLogout do
|
|
32
32
|
|
33
33
|
it "run #logout" do
|
34
34
|
expect(::Sso::Session).to receive(:logout).with(session.id)
|
35
|
-
|
35
|
+
rack.call
|
36
36
|
end
|
37
37
|
|
38
38
|
it 'revokes the passport' do
|
@@ -41,6 +41,11 @@ RSpec.describe Sso::Warden::Hooks::BeforeLogout do
|
|
41
41
|
expect(session.revoked_at.to_i).to eq Time.now.to_i
|
42
42
|
expect(session.revoke_reason).to eq 'logout'
|
43
43
|
end
|
44
|
+
|
45
|
+
it 'clears session' do
|
46
|
+
rack.call
|
47
|
+
expect(rack.session["sso_session_id"]).to be_nil
|
48
|
+
end
|
44
49
|
end
|
45
50
|
|
46
51
|
context "when logged_out" do
|
@@ -33,15 +33,14 @@ RSpec.describe Sso::Warden::Hooks::CreateMasterSession do
|
|
33
33
|
context 'existing session' do
|
34
34
|
let(:sso_params) { { :ip => "202.188.0.133", :agent => "Chrome" } }
|
35
35
|
let(:sso_session) { ::Sso::Session.generate_master(user, sso_params ) }
|
36
|
-
let
|
36
|
+
let(:sso_session_id) { sso_session.id }
|
37
|
+
let!(:session_params) { { "sso_session_id" => sso_session_id } }
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
it { expect(::Sso::Session.count).to eq 2 }
|
41
|
-
it { expect(::Sso::Session.find_by_id(sso_session.id).revoke_reason).to eq "logout" }
|
39
|
+
it { rack.call; expect(::Sso::Session.count).to eq 2 }
|
40
|
+
it { rack.call; expect(::Sso::Session.find_by_id(sso_session.id).revoke_reason).to eq "logout" }
|
42
41
|
|
43
42
|
it "runs Sso::Session.logout" do
|
44
|
-
expect(::Sso::Session).to receive(:logout).with(
|
43
|
+
expect(::Sso::Session).to receive(:logout).with(sso_session_id)
|
45
44
|
rack.call
|
46
45
|
end
|
47
46
|
end
|
@@ -49,16 +48,9 @@ RSpec.describe Sso::Warden::Hooks::CreateMasterSession do
|
|
49
48
|
context 'logged out' do
|
50
49
|
let(:user) { nil }
|
51
50
|
|
52
|
-
|
53
|
-
|
54
|
-
it "will not run Sso::Session.logout" do
|
51
|
+
it "will not run Sso::Session.logout but throw :warden" do
|
55
52
|
expect(::Sso::Session).not_to receive(:logout)
|
56
|
-
rack.call
|
57
|
-
end
|
58
|
-
|
59
|
-
it "will not run #generate_session" do
|
60
|
-
expect(rack).not_to receive(:generate_session)
|
61
|
-
rack.call
|
53
|
+
expect { rack.call }.to raise_exception("uncaught throw :warden")
|
62
54
|
end
|
63
55
|
end
|
64
56
|
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
RSpec.describe 'OAuth 2.0 Authorization Grant Flow', type: :request, db: true do
|
4
|
+
|
5
|
+
let!(:user) { Fabricate(:user, password: "bumblebee") }
|
6
|
+
let!(:doorkeeper_application) { Fabricate('Doorkeeper::Application') }
|
7
|
+
let(:redirect_uri) { doorkeeper_application.redirect_uri }
|
8
|
+
|
9
|
+
let(:grant_params) { { client_id: doorkeeper_application.uid, redirect_uri: redirect_uri, response_type: "code", state: 'some_random_string' } } # client_id=04364b30de79090493f079724571899eece7791b5af54e5866d73c6aaf167ec9&redirect_uri=http%3A%2F%2Flaunchpad.dev%2Fauth%2Fmindvalley%2Fcallback&response_type=code&state=a82b7b992c78ed7c47aba11340cdea76cc5ecc4ffe62ef39
|
10
|
+
|
11
|
+
let(:result) { JSON.parse(response.body) }
|
12
|
+
|
13
|
+
let(:latest_grant) { ::Doorkeeper::AccessGrant.last }
|
14
|
+
let(:latest_access_token) { ::Doorkeeper::AccessToken.last }
|
15
|
+
let(:access_token_count) { ::Doorkeeper::AccessToken.count }
|
16
|
+
let(:grant_count) { ::Doorkeeper::AccessGrant.count }
|
17
|
+
|
18
|
+
let(:latest_passport) { ::SSO::Session.last }
|
19
|
+
let(:passport_count) { ::SSO::Session.last.count }
|
20
|
+
|
21
|
+
before do
|
22
|
+
get_via_redirect '/oauth/authorize', grant_params
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'shows to the login page' do
|
26
|
+
expect(response).to render_template 'devise/sessions/new'
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'Logging in' do
|
30
|
+
before do
|
31
|
+
post '/login', user: { email: user.email, password: "bumblebee" }
|
32
|
+
follow_redirect!
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'redirects to the application callback including the Grant Token' do
|
36
|
+
#expect(latest_grant).to be_present
|
37
|
+
expect(response.body).to eq 1 #redirect_to "#{doorkeeper_application.redirect_uri}?code=#{latest_grant.token}&state=some_random_string"
|
38
|
+
end
|
39
|
+
|
40
|
+
# it 'generates a passport with the grant token attached to it' do
|
41
|
+
# expect(latest_passport.oauth_access_grant_id).to eq latest_grant.id
|
42
|
+
# end
|
43
|
+
|
44
|
+
# it 'does not generate multiple authorization grants' do
|
45
|
+
# expect(grant_count).to eq 1
|
46
|
+
# end
|
47
|
+
|
48
|
+
pending 'Exchanging the Authorization Grant for an Access Token' do
|
49
|
+
let(:grant) { ::Rack::Utils.parse_query(URI.parse(response.location).query).fetch('code') }
|
50
|
+
let(:grant_type) { :authorization_code }
|
51
|
+
let(:params) { { doorkeeper_application_id: doorkeeper_application.uid, doorkeeper_application_secret: doorkeeper_application.secret, code: grant, grant_type: grant_type, redirect_uri: redirect_uri } }
|
52
|
+
let(:token) { JSON.parse(response.body).fetch 'access_token' }
|
53
|
+
|
54
|
+
before do
|
55
|
+
post '/oauth/token', params
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'succeeds' do
|
59
|
+
expect(response.status).to eq 200
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'responds with JSON serialized params' do
|
63
|
+
expect(result).to be_instance_of Hash
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'includes the access_token' do
|
67
|
+
expect(result['access_token']).to eq latest_access_token.token
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'generates a passport with the grant token attached to it' do
|
71
|
+
expect(latest_passport.oauth_access_token_id).to eq latest_access_token.id
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'does not generate multiple passports' do
|
75
|
+
expect(passport_count).to eq 1
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'does not generate multiple access tokens' do
|
79
|
+
expect(access_token_count).to eq 1
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'succeeds' do
|
83
|
+
expect(response.status).to eq 200
|
84
|
+
end
|
85
|
+
|
86
|
+
pending 'Exchanging the Access Token for a Passport' do
|
87
|
+
before do
|
88
|
+
SSO.config.passport_chip_key = SecureRandom.hex
|
89
|
+
post '/oauth/sso/v1/passports', access_token: token
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'succeeds' do
|
93
|
+
expect(response.status).to eq 200
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'gets the passport' do
|
97
|
+
expect(result['passport']).to be_present
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'is the passport for that access token' do
|
101
|
+
expect(result['passport']['id']).to eq latest_passport.id
|
102
|
+
expect(latest_passport.oauth_access_token_id).to eq latest_access_token.id
|
103
|
+
end
|
104
|
+
|
105
|
+
pending 'is an outsider passport' do
|
106
|
+
expect(latest_passport).to_not be_insider
|
107
|
+
end
|
108
|
+
|
109
|
+
pending 'insider application' do
|
110
|
+
let!(:doorkeeper_application) { Fabricate('Doorkeeper::Application') }
|
111
|
+
let(:scope) { :insider }
|
112
|
+
|
113
|
+
it 'is an insider passport' do
|
114
|
+
expect(latest_passport).to be_insider
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: doorkeeper_sso
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
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-09-
|
11
|
+
date: 2015-09-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: warden
|
@@ -348,17 +348,20 @@ files:
|
|
348
348
|
- db/migrate/20150521142926_create_sso_clients.rb
|
349
349
|
- db/migrate/20150521165143_remove_extra_columns_from_sso_sessions.rb
|
350
350
|
- db/migrate/20150603145730_add_pingback_uri_to_doorkeeper_applications.rb
|
351
|
-
- lib/doorkeeper/oauth/request_concern.rb
|
352
351
|
- lib/doorkeeper_sso.rb
|
353
352
|
- lib/sso.rb
|
354
353
|
- lib/sso/doorkeeper/access_grant_mixin.rb
|
355
354
|
- lib/sso/doorkeeper/access_token_mixin.rb
|
355
|
+
- lib/sso/doorkeeper/application_controller_mixin.rb
|
356
356
|
- lib/sso/doorkeeper/application_mixin.rb
|
357
|
+
- lib/sso/doorkeeper/authorization.rb
|
357
358
|
- lib/sso/doorkeeper/authorization/code_mixin.rb
|
358
359
|
- lib/sso/doorkeeper/authorization/token_mixin.rb
|
359
|
-
- lib/sso/doorkeeper/
|
360
|
-
- lib/sso/doorkeeper/
|
360
|
+
- lib/sso/doorkeeper/oauth.rb
|
361
|
+
- lib/sso/doorkeeper/oauth/authorization_code_request_mixin.rb
|
362
|
+
- lib/sso/doorkeeper/oauth/base.rb
|
361
363
|
- lib/sso/engine.rb
|
364
|
+
- lib/sso/engine.rb.orig
|
362
365
|
- lib/sso/logging.rb
|
363
366
|
- lib/sso/version.rb
|
364
367
|
- lib/sso/warden/hooks/before_logout.rb
|
@@ -378,14 +381,13 @@ files:
|
|
378
381
|
- spec/lib/doorkeeper/access_grant_mixin_spec.rb
|
379
382
|
- spec/lib/doorkeeper/access_token_mixin_spec.rb
|
380
383
|
- spec/lib/doorkeeper/application_mixin_spec.rb
|
381
|
-
- spec/lib/doorkeeper/authorizations_controller_mixin_spec.rb
|
382
|
-
- spec/lib/doorkeeper/tokens_controller_mixin_spec.rb
|
383
384
|
- spec/lib/sso/warden/hooks/before_logout_spec.rb
|
384
385
|
- spec/lib/sso/warden/hooks/create_master_session_spec.rb
|
385
386
|
- spec/models/sso/client_spec.rb
|
386
387
|
- spec/models/sso/pingback_spec.rb
|
387
388
|
- spec/models/sso/session_spec.rb
|
388
389
|
- spec/rails_helper.rb
|
390
|
+
- spec/request/oauth/authorization_code_spec.rb
|
389
391
|
- spec/spec_helper.rb
|
390
392
|
- spec/support/api_schema_matcher.rb
|
391
393
|
- spec/support/database_cleaner.rb
|
@@ -438,14 +440,13 @@ test_files:
|
|
438
440
|
- spec/lib/doorkeeper/access_grant_mixin_spec.rb
|
439
441
|
- spec/lib/doorkeeper/access_token_mixin_spec.rb
|
440
442
|
- spec/lib/doorkeeper/application_mixin_spec.rb
|
441
|
-
- spec/lib/doorkeeper/authorizations_controller_mixin_spec.rb
|
442
|
-
- spec/lib/doorkeeper/tokens_controller_mixin_spec.rb
|
443
443
|
- spec/lib/sso/warden/hooks/before_logout_spec.rb
|
444
444
|
- spec/lib/sso/warden/hooks/create_master_session_spec.rb
|
445
445
|
- spec/models/sso/client_spec.rb
|
446
446
|
- spec/models/sso/pingback_spec.rb
|
447
447
|
- spec/models/sso/session_spec.rb
|
448
448
|
- spec/rails_helper.rb
|
449
|
+
- spec/request/oauth/authorization_code_spec.rb
|
449
450
|
- spec/spec_helper.rb
|
450
451
|
- spec/support/api_schema_matcher.rb
|
451
452
|
- spec/support/database_cleaner.rb
|
@@ -1,48 +0,0 @@
|
|
1
|
-
module Sso
|
2
|
-
module Doorkeeper
|
3
|
-
module AuthorizationsControllerMixin
|
4
|
-
extend ActiveSupport::Concern
|
5
|
-
include ::Sso::Logging
|
6
|
-
|
7
|
-
included do
|
8
|
-
around_action :subscribe_to_token_creation, only: [:new, :create]
|
9
|
-
after_action :after_grant_create, only: [:new, :create]
|
10
|
-
end
|
11
|
-
|
12
|
-
protected
|
13
|
-
|
14
|
-
def subscribe_to_token_creation
|
15
|
-
Wisper.subscribe(self) do
|
16
|
-
yield
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def access_token_created(token_id)
|
21
|
-
raise "AuthorizationsController#gives token - #{token_id}"
|
22
|
-
end
|
23
|
-
|
24
|
-
def after_grant_create
|
25
|
-
debug { "AuthorizationsController#Create : after_action" }
|
26
|
-
code_response = authorization.instance_variable_get("@response")
|
27
|
-
oauth_grant = code_response.try(:auth).try(:token)
|
28
|
-
|
29
|
-
warden_session = session["warden.user.user.session"] || {}
|
30
|
-
sso_session = Sso::Session.find_by_id(warden_session["sso_session_id"].to_s)
|
31
|
-
|
32
|
-
unless sso_session.try(:active?)
|
33
|
-
error { "ERROR : AuthorizationsControllerMixin - Sso::Session INACTIVE) #{sso_session.inspect}" }
|
34
|
-
return false
|
35
|
-
end
|
36
|
-
|
37
|
-
if oauth_grant
|
38
|
-
debug { "Sso::Session.update_master_with_grant - #{sso_session.id.inspect}, #{oauth_grant.inspect}" }
|
39
|
-
sso_session.clients.find_or_create_by!(access_grant_id: oauth_grant.id)
|
40
|
-
else
|
41
|
-
error { "ERROR : AuthorizationsControllerMixin - Unable to get grant id from #{oauth_grant.inspect}" }
|
42
|
-
sso_session.logout
|
43
|
-
return false
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
require 'active_support/concern'
|
2
|
-
|
3
|
-
module Sso
|
4
|
-
module Doorkeeper
|
5
|
-
module TokensControllerMixin
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
include ::Sso::Logging
|
8
|
-
|
9
|
-
included do
|
10
|
-
after_action :after_token_create, only: :create
|
11
|
-
end
|
12
|
-
|
13
|
-
protected
|
14
|
-
|
15
|
-
def after_token_create
|
16
|
-
debug { "TokensController#Create : after_action" }
|
17
|
-
handle_authorization_grant_flow
|
18
|
-
end
|
19
|
-
|
20
|
-
def handle_authorization_grant_flow
|
21
|
-
# We cannot rely on session[:sso_session_id] here because the end-user might have cookies disabled.
|
22
|
-
# The only thing we can rely on to identify the user/Passport is the incoming grant token.
|
23
|
-
debug { %(Detected outgoing "Access Token" #{outgoing_access_token.inspect}) }
|
24
|
-
|
25
|
-
unless client = ::Sso::Client.find_by_grant_token(grant_token)
|
26
|
-
return error_and_return "::Sso::Client not found for grant token #{grant_token}"
|
27
|
-
end
|
28
|
-
|
29
|
-
if client.update_access_token(outgoing_access_token)
|
30
|
-
debug { "::Sso::Client.update_access_token success for access_token: #{outgoing_access_token}" }
|
31
|
-
else
|
32
|
-
return error_and_return "::Sso::Session.update_access_token failed. #{client.errors.inspect}"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def error_and_return(msg)
|
37
|
-
error { msg }
|
38
|
-
return false
|
39
|
-
end
|
40
|
-
|
41
|
-
def grant_token
|
42
|
-
params["code"]
|
43
|
-
end
|
44
|
-
|
45
|
-
def grant_type
|
46
|
-
params["grant_type"]
|
47
|
-
end
|
48
|
-
|
49
|
-
def outgoing_access_token
|
50
|
-
@response_hash ||= JSON.parse(response.body)
|
51
|
-
@response_hash["access_token"]
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
@@ -1,65 +0,0 @@
|
|
1
|
-
require 'rails_helper'
|
2
|
-
|
3
|
-
# Engine.rb automatically includes the mixin
|
4
|
-
|
5
|
-
RSpec.describe Doorkeeper::AuthorizationsController do
|
6
|
-
|
7
|
-
let(:user) { Fabricate(:user) }
|
8
|
-
let(:application) { Fabricate('Doorkeeper::Application') }
|
9
|
-
# let(:access_token) { Fabricate('Doorkeeper::AccessToken',
|
10
|
-
# resource_owner_id: user.id) }
|
11
|
-
let!(:access_grant) { Fabricate('Doorkeeper::AccessGrant',
|
12
|
-
application_id: application.id,
|
13
|
-
resource_owner_id: user.id,
|
14
|
-
redirect_uri: 'http://localhost:3002/oauth/callback'
|
15
|
-
) }
|
16
|
-
|
17
|
-
# Set up Session
|
18
|
-
let(:session) { Fabricate('Sso::Session', owner: user) }
|
19
|
-
let!(:client) { Fabricate('Sso::Client', session: session,
|
20
|
-
application_id: application.id) }
|
21
|
-
|
22
|
-
let(:auth) { double :auth, token: access_grant }
|
23
|
-
let(:code_response) { double :code_response, auth: auth }
|
24
|
-
let(:authorization) { double :authorization, instance_variable_get: code_response }
|
25
|
-
let(:warden_session) { { "warden.user.user.session" => { "sso_session_id" => session.id } } }
|
26
|
-
subject(:controller) { described_class.new }
|
27
|
-
|
28
|
-
|
29
|
-
before do
|
30
|
-
allow_any_instance_of(described_class).to receive(:authorization).and_return(authorization)
|
31
|
-
allow_any_instance_of(described_class).to receive(:session).and_return(warden_session)
|
32
|
-
end
|
33
|
-
|
34
|
-
describe "#after_grant_create" do
|
35
|
-
context "working" do
|
36
|
-
it "creates client with grant_id" do
|
37
|
-
controller.send(:after_grant_create)
|
38
|
-
expect(access_grant.sso_client).to be_a ::Sso::Client
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
context "no grant" do
|
43
|
-
let(:access_grant) { nil }
|
44
|
-
|
45
|
-
it "logs error" do
|
46
|
-
expect(controller).to receive(:error)
|
47
|
-
controller.send(:after_grant_create)
|
48
|
-
end
|
49
|
-
|
50
|
-
it "logout session" do
|
51
|
-
expect_any_instance_of(::Sso::Session).to receive(:logout).and_call_original
|
52
|
-
controller.send(:after_grant_create)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
context "no session" do
|
57
|
-
let(:warden_session) { {} }
|
58
|
-
|
59
|
-
it "logs error" do
|
60
|
-
expect(controller).to receive(:error)
|
61
|
-
controller.send(:after_grant_create)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
@@ -1,72 +0,0 @@
|
|
1
|
-
require 'rails_helper'
|
2
|
-
|
3
|
-
# Engine.rb automatically includes the mixin
|
4
|
-
|
5
|
-
RSpec.describe Doorkeeper::TokensController, :type => :controller do
|
6
|
-
|
7
|
-
let(:user) { Fabricate(:user) }
|
8
|
-
let(:application) { Fabricate('Doorkeeper::Application') }
|
9
|
-
let(:access_token) { Fabricate('Doorkeeper::AccessToken',
|
10
|
-
resource_owner_id: user.id) }
|
11
|
-
let!(:access_grant) { Fabricate('Doorkeeper::AccessGrant',
|
12
|
-
application_id: application.id,
|
13
|
-
resource_owner_id: user.id,
|
14
|
-
redirect_uri: 'http://localhost:3002/oauth/callback'
|
15
|
-
) }
|
16
|
-
|
17
|
-
# Set up Session
|
18
|
-
let(:session) { Fabricate('Sso::Session', owner: user) }
|
19
|
-
let!(:client) { Fabricate('Sso::Client', session: session,
|
20
|
-
application_id: application.id,
|
21
|
-
access_grant_id: access_grant.id) }
|
22
|
-
|
23
|
-
let(:auth) { double :auth, token: access_grant }
|
24
|
-
let(:code_response) { double :code_response, auth: auth }
|
25
|
-
let(:authorization) { double :authorization, instance_variable_get: code_response }
|
26
|
-
let(:warden_session) { { "warden.user.user.session" => { "sso_session_id" => session.id } } }
|
27
|
-
subject(:controller) { described_class.new }
|
28
|
-
|
29
|
-
|
30
|
-
describe "#handle_authorization_grant_flow" do
|
31
|
-
before do
|
32
|
-
allow(controller).to receive(:grant_token).and_return(access_grant.try(:token))
|
33
|
-
allow(controller).to receive(:grant_type).and_return("authorization_code")
|
34
|
-
allow(controller).to receive(:outgoing_access_token).and_return(access_token.try(:token))
|
35
|
-
end
|
36
|
-
|
37
|
-
context "working flow" do
|
38
|
-
it "saves access_token" do
|
39
|
-
controller.send(:handle_authorization_grant_flow)
|
40
|
-
client.reload
|
41
|
-
expect(client.access_grant).to eq access_grant
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
context "grant missing" do
|
46
|
-
let!(:access_grant) { nil }
|
47
|
-
let!(:client) { nil }
|
48
|
-
|
49
|
-
it "logs error and halt" do
|
50
|
-
expect(controller).to receive(:error)
|
51
|
-
expect(controller.send(:handle_authorization_grant_flow)).to be_falsy
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
context "access_grant token missing" do
|
56
|
-
let(:access_token) { nil }
|
57
|
-
|
58
|
-
it "logs error and halt" do
|
59
|
-
expect(controller).to receive(:error)
|
60
|
-
expect(controller.send(:handle_authorization_grant_flow)).to be_falsy
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
|
66
|
-
describe "#error_and_return" do
|
67
|
-
after() { controller.send(:error_and_return, "AN ERROR") }
|
68
|
-
|
69
|
-
it { expect(controller).to receive(:error) }
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|