doorkeeper_sso 0.2.3 → 0.2.5
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/controllers/sso/application_controller.rb +16 -1
- data/app/controllers/sso/sessions_controller.rb +18 -11
- data/app/models/sso/client.rb +3 -3
- data/app/models/sso/session.rb +0 -20
- data/lib/sso/doorkeeper/authorizations_controller_mixin.rb +8 -7
- data/lib/sso/doorkeeper/tokens_controller_mixin.rb +8 -4
- data/lib/sso/version.rb +1 -1
- data/lib/sso/warden/hooks/after_authentication.rb +2 -27
- data/lib/sso/warden/hooks/before_logout.rb +2 -27
- data/lib/sso/warden/hooks/session_check.rb +1 -28
- data/lib/sso/warden/support.rb +38 -0
- data/lib/sso.rb +1 -0
- data/spec/lib/doorkeeper/authorizations_controller_mixin_spec.rb +65 -0
- data/spec/lib/doorkeeper/tokens_controller_mixin_spec.rb +72 -0
- data/spec/lib/sso/warden/hooks/after_authentication_spec.rb +56 -26
- data/spec/lib/sso/warden/hooks/before_logout_spec.rb +50 -25
- data/spec/models/sso/client_spec.rb +45 -0
- data/spec/models/sso/session_spec.rb +0 -74
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 00bd0477d279b369c70ea874e7beffdad2cefff4
|
4
|
+
data.tar.gz: 5289840040a7eb1845aee6b451c89c62d630d2e0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7667f3e47917c7aa922a2da26e694afad7d5354664b6c24087afc6178676fdf0af4356f58cea24fac5459d650632724d6523252385f76a21a3dbd23ecbb3eccc
|
7
|
+
data.tar.gz: 73462490fe311329f0ef6fdb04600ec377c4517697692a16fe8f69196c6cdb5d038648f5bd3be760051fa538aeb980e532ad0acf12ac5e25db7cca900761ed28
|
@@ -1,6 +1,21 @@
|
|
1
1
|
module Sso
|
2
|
-
class ApplicationController < ::ApplicationController
|
3
2
|
# class ApplicationController < RocketPants::Base
|
4
3
|
# extend Apipie::DSL::Controller
|
4
|
+
class ApplicationController < ::ApplicationController
|
5
|
+
# include ::Doorkeeper::Helpers::Controller
|
6
|
+
|
7
|
+
# TODO: Security issue?
|
8
|
+
protect_from_forgery
|
9
|
+
# Bug in devise so we skip protect_from_forgery for only create
|
10
|
+
# http://stackoverflow.com/questions/20875591/actioncontrollerinvalidauthenticitytoken-in-registrationscontrollercreate
|
11
|
+
# http://stackoverflow.com/questions/23773730/rails-4-skipping-protect-from-forgery-for-api-actions
|
12
|
+
# skip_before_action :verify_authenticity_token, if: :json_request?
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
def json_request?
|
17
|
+
request.format.json?
|
18
|
+
end
|
19
|
+
|
5
20
|
end
|
6
21
|
end
|
@@ -1,12 +1,9 @@
|
|
1
1
|
module Sso
|
2
2
|
class SessionsController < Sso::ApplicationController
|
3
|
+
include ::Sso::Logging
|
3
4
|
|
4
|
-
before_action :authenticate_user!, only: :jsonp
|
5
|
+
before_action :authenticate_user!, only: [:jsonp]
|
5
6
|
before_action :doorkeeper_authorize!, only: [:show, :create]
|
6
|
-
|
7
|
-
# TODO: Security issue?
|
8
|
-
protect_from_forgery with: :null_session
|
9
|
-
|
10
7
|
respond_to :json
|
11
8
|
|
12
9
|
################################################################################
|
@@ -26,12 +23,11 @@ module Sso
|
|
26
23
|
# Passport Strategy first exchange
|
27
24
|
# Insider : Client information from Apps should always be trusted
|
28
25
|
def create
|
29
|
-
# passport.load_user!
|
30
|
-
# passport.create_chip!
|
31
|
-
current_client = ::Sso::Client.find_by_access_token(doorkeeper_token.id)
|
32
|
-
current_client.update!(client_params)
|
33
|
-
|
34
26
|
@session = current_client.session
|
27
|
+
debug { "SessionsController#create - #{@session.inspect}"}
|
28
|
+
raise "ResourceOwner from token != session.owner" if doorkeeper_token.resource_owner_id != @session.owner.id
|
29
|
+
|
30
|
+
current_client.update_attributes!(client_params)
|
35
31
|
render json: @session, status: :created, serializer: Sso::SessionSerializer
|
36
32
|
end
|
37
33
|
|
@@ -50,6 +46,9 @@ module Sso
|
|
50
46
|
################################################################################
|
51
47
|
def mobile
|
52
48
|
# TODO : Check inconsistent
|
49
|
+
|
50
|
+
# passport.load_user!
|
51
|
+
# passport.create_chip!
|
53
52
|
render :nothing => true
|
54
53
|
# respond_with @session, :location => sso.sessions_url
|
55
54
|
end
|
@@ -59,7 +58,15 @@ module Sso
|
|
59
58
|
protected
|
60
59
|
|
61
60
|
def current_client
|
62
|
-
@
|
61
|
+
@current_client ||= doorkeeper_token.sso_client
|
62
|
+
end
|
63
|
+
|
64
|
+
def current_resource_owner
|
65
|
+
@current_resource_owner ||= User.find(doorkeeper_token.resource_owner_id)
|
66
|
+
end
|
67
|
+
|
68
|
+
def current_session
|
69
|
+
@current_session = current_client.session
|
63
70
|
end
|
64
71
|
|
65
72
|
def client_params
|
data/app/models/sso/client.rb
CHANGED
@@ -12,16 +12,16 @@ module Sso
|
|
12
12
|
|
13
13
|
class << self
|
14
14
|
def find_by_grant_token(token)
|
15
|
-
find_by
|
15
|
+
find_by(access_grant: ::Doorkeeper::AccessGrant.by_token(token))
|
16
16
|
end
|
17
17
|
|
18
18
|
def find_by_access_token(token)
|
19
|
-
find_by
|
19
|
+
find_by(access_token: ::Doorkeeper::AccessToken.by_token(token))
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
23
|
def update_access_token(token)
|
24
|
-
oauth_token = ::Doorkeeper::AccessToken.by_token(token)
|
24
|
+
return false unless oauth_token = ::Doorkeeper::AccessToken.by_token(token)
|
25
25
|
update(access_token_id: oauth_token.id, application_id: oauth_token.application.id)
|
26
26
|
end
|
27
27
|
end
|
data/app/models/sso/session.rb
CHANGED
@@ -46,32 +46,12 @@ module Sso
|
|
46
46
|
sso_session
|
47
47
|
end
|
48
48
|
|
49
|
-
def generate(user, access_token, options = {})
|
50
|
-
master_sso_session = active.find_by!(owner_id: user.id)
|
51
|
-
|
52
|
-
attributes = ActionController::Parameters.new(options).permit(:ip, :agent, :location)
|
53
|
-
relations = { application: access_token.application, access_token: access_token }
|
54
|
-
|
55
|
-
debug { "Sso::Session::generate for #{user.inspect} - #{access_token.inspect} - #{attributes.inspect}" }
|
56
|
-
|
57
|
-
if client = master_sso_session_id.clients.find_by(access_token_id: access_token.id)
|
58
|
-
client.update_columns(attributes)
|
59
|
-
else
|
60
|
-
master_sso_session.clients.create!(relations.merge(attributes))
|
61
|
-
end
|
62
|
-
master_sso_session
|
63
|
-
end
|
64
|
-
|
65
49
|
def logout(sso_session_id)
|
66
50
|
return false unless session = find_by_id(sso_session_id)
|
67
51
|
session.logout
|
68
52
|
end
|
69
53
|
end
|
70
54
|
|
71
|
-
def create_session(token, options = {})
|
72
|
-
create(access_token_id)
|
73
|
-
end
|
74
|
-
|
75
55
|
def active?
|
76
56
|
revoked_at.blank?
|
77
57
|
end
|
@@ -15,20 +15,21 @@ module Sso
|
|
15
15
|
code_response = authorization.instance_variable_get("@response")
|
16
16
|
oauth_grant = code_response.try(:auth).try(:token)
|
17
17
|
|
18
|
-
warden_session = session["warden.user.user.session"]
|
19
|
-
sso_session = Sso::Session.
|
18
|
+
warden_session = session["warden.user.user.session"] || {}
|
19
|
+
sso_session = Sso::Session.find_by_id(warden_session["sso_session_id"].to_s)
|
20
20
|
|
21
|
-
|
22
|
-
error { "ERROR : AuthorizationsControllerMixin - Sso::Session INACTIVE) #{sso_session.inspect}"}
|
23
|
-
|
21
|
+
unless sso_session.try(:active?)
|
22
|
+
error { "ERROR : AuthorizationsControllerMixin - Sso::Session INACTIVE) #{sso_session.inspect}" }
|
23
|
+
return false
|
24
24
|
end
|
25
25
|
|
26
26
|
if oauth_grant
|
27
27
|
debug { "Sso::Session.update_master_with_grant - #{sso_session.id.inspect}, #{oauth_grant.inspect}" }
|
28
28
|
sso_session.clients.find_or_create_by!(access_grant_id: oauth_grant.id)
|
29
29
|
else
|
30
|
-
error { "ERROR : AuthorizationsControllerMixin - Unable to get grant id from #{oauth_grant.inspect}"}
|
31
|
-
|
30
|
+
error { "ERROR : AuthorizationsControllerMixin - Unable to get grant id from #{oauth_grant.inspect}" }
|
31
|
+
sso_session.logout
|
32
|
+
return false
|
32
33
|
end
|
33
34
|
end
|
34
35
|
end
|
@@ -10,7 +10,7 @@ module Sso
|
|
10
10
|
after_action :after_token_create, only: :create
|
11
11
|
end
|
12
12
|
|
13
|
-
|
13
|
+
protected
|
14
14
|
|
15
15
|
def after_token_create
|
16
16
|
debug { "TokensController#Create : after_action" }
|
@@ -23,17 +23,21 @@ module Sso
|
|
23
23
|
debug { %(Detected outgoing "Access Token" #{outgoing_access_token.inspect}) }
|
24
24
|
|
25
25
|
unless client = ::Sso::Client.find_by_grant_token(grant_token)
|
26
|
-
|
26
|
+
return error_and_return "::Sso::Client not found for grant token #{grant_token}"
|
27
27
|
end
|
28
28
|
|
29
29
|
if client.update_access_token(outgoing_access_token)
|
30
30
|
debug { "::Sso::Client.update_access_token success for access_token: #{outgoing_access_token}" }
|
31
31
|
else
|
32
|
-
|
33
|
-
warden.logout
|
32
|
+
return error_and_return "::Sso::Session.update_access_token failed. #{client.errors.inspect}"
|
34
33
|
end
|
35
34
|
end
|
36
35
|
|
36
|
+
def error_and_return(msg)
|
37
|
+
error { msg }
|
38
|
+
return false
|
39
|
+
end
|
40
|
+
|
37
41
|
def grant_token
|
38
42
|
params["code"]
|
39
43
|
end
|
data/lib/sso/version.rb
CHANGED
@@ -2,25 +2,12 @@ module Sso
|
|
2
2
|
module Warden
|
3
3
|
module Hooks
|
4
4
|
class AfterAuthentication
|
5
|
-
include ::Sso::
|
6
|
-
|
7
|
-
attr_reader :user, :warden, :options
|
8
|
-
delegate :request, to: :warden
|
9
|
-
delegate :params, to: :request
|
10
|
-
|
11
|
-
def self.to_proc
|
12
|
-
proc do |user, warden, options|
|
13
|
-
new(user, warden, options).call
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def initialize(user, warden, options)
|
18
|
-
@user, @warden, @options = user, warden, options
|
19
|
-
end
|
5
|
+
include ::Sso::Warden::Support
|
20
6
|
|
21
7
|
def call
|
22
8
|
debug { "Starting hook because this is considered the first login of the current session..." }
|
23
9
|
generate_session
|
10
|
+
return nil
|
24
11
|
end
|
25
12
|
|
26
13
|
def generate_session
|
@@ -31,18 +18,6 @@ module Sso
|
|
31
18
|
debug { "Sso:Session with ID #{sso_session.id} generated successfuly. Persisting it in session..." }
|
32
19
|
session["sso_session_id"] = sso_session.id.to_s
|
33
20
|
end
|
34
|
-
|
35
|
-
def scope
|
36
|
-
scope = options[:scope]
|
37
|
-
end
|
38
|
-
|
39
|
-
def session
|
40
|
-
warden.session(scope)
|
41
|
-
end
|
42
|
-
|
43
|
-
def logged_in?
|
44
|
-
warden.authenticated?(scope) && session && user
|
45
|
-
end
|
46
21
|
end
|
47
22
|
end
|
48
23
|
end
|
@@ -2,21 +2,7 @@ module Sso
|
|
2
2
|
module Warden
|
3
3
|
module Hooks
|
4
4
|
class BeforeLogout
|
5
|
-
include ::Sso::
|
6
|
-
|
7
|
-
attr_reader :user, :warden, :options
|
8
|
-
delegate :request, to: :warden
|
9
|
-
delegate :params, to: :request
|
10
|
-
|
11
|
-
def self.to_proc
|
12
|
-
proc do |user, warden, options|
|
13
|
-
new(user, warden, options).call
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def initialize(user, warden, options)
|
18
|
-
@user, @warden, @options = user, warden, options
|
19
|
-
end
|
5
|
+
include ::Sso::Warden::Support
|
20
6
|
|
21
7
|
def call
|
22
8
|
# Only run if user is logged in
|
@@ -25,18 +11,7 @@ module Sso
|
|
25
11
|
debug { "user is #{user.inspect}" }
|
26
12
|
::Sso::Session.logout(session["sso_session_id"])
|
27
13
|
end
|
28
|
-
|
29
|
-
|
30
|
-
def scope
|
31
|
-
scope = options[:scope]
|
32
|
-
end
|
33
|
-
|
34
|
-
def session
|
35
|
-
warden.session(scope)
|
36
|
-
end
|
37
|
-
|
38
|
-
def logged_in?
|
39
|
-
warden.authenticated?(scope) && session && user
|
14
|
+
return nil
|
40
15
|
end
|
41
16
|
end
|
42
17
|
end
|
@@ -2,43 +2,16 @@ module Sso
|
|
2
2
|
module Warden
|
3
3
|
module Hooks
|
4
4
|
class SessionCheck
|
5
|
-
include ::Sso::
|
6
|
-
|
7
|
-
attr_reader :user, :warden, :options
|
8
|
-
delegate :request, to: :warden
|
9
|
-
delegate :params, to: :request
|
10
|
-
|
11
|
-
def self.to_proc
|
12
|
-
proc do |user, warden, options|
|
13
|
-
new(user, warden, options).call
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def initialize(user, warden, options)
|
18
|
-
@user, @warden, @options = user, warden, options
|
19
|
-
end
|
5
|
+
include ::Sso::Warden::Support
|
20
6
|
|
21
7
|
def call
|
22
8
|
debug { "Starting hook after user is fetched into the session" }
|
23
9
|
|
24
|
-
# Infinite loop with BeforeLogout - before logout runs this too
|
25
10
|
unless logged_in? && Sso::Session.find_by_id(session["sso_session_id"]).try(:active?)
|
26
11
|
warden.logout(scope)
|
27
12
|
throw(:warden, :scope => scope, :reason => "Sso::Session INACTIVE")
|
28
13
|
end
|
29
14
|
end
|
30
|
-
|
31
|
-
def scope
|
32
|
-
scope = options[:scope]
|
33
|
-
end
|
34
|
-
|
35
|
-
def session
|
36
|
-
warden.session(scope)
|
37
|
-
end
|
38
|
-
|
39
|
-
def logged_in?
|
40
|
-
warden.authenticated?(scope) && session && user
|
41
|
-
end
|
42
15
|
end
|
43
16
|
end
|
44
17
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Sso
|
2
|
+
module Warden
|
3
|
+
module Support
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
include ::Sso::Logging
|
6
|
+
|
7
|
+
included do
|
8
|
+
attr_reader :user, :warden, :options
|
9
|
+
delegate :request, to: :warden
|
10
|
+
delegate :params, to: :request
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
def to_proc
|
15
|
+
proc do |user, warden, options|
|
16
|
+
new(user, warden, options).call
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(user, warden, options)
|
22
|
+
@user, @warden, @options = user, warden, options
|
23
|
+
end
|
24
|
+
|
25
|
+
def scope
|
26
|
+
scope = options[:scope]
|
27
|
+
end
|
28
|
+
|
29
|
+
def session
|
30
|
+
warden.session(scope)
|
31
|
+
end
|
32
|
+
|
33
|
+
def logged_in?
|
34
|
+
warden.authenticated?(scope) && session && user
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/sso.rb
CHANGED
@@ -0,0 +1,65 @@
|
|
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
|
@@ -0,0 +1,72 @@
|
|
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
|
@@ -1,36 +1,66 @@
|
|
1
1
|
require 'rails_helper'
|
2
2
|
|
3
|
-
# These tests are moot
|
4
3
|
RSpec.describe Sso::Warden::Hooks::AfterAuthentication do
|
5
|
-
#include Warden::Test::Helpers
|
6
4
|
|
7
|
-
#
|
8
|
-
|
9
|
-
# let(:
|
10
|
-
|
11
|
-
# let(:after_authentication) { Sso::Warden::Hooks::AfterAuthentication.new(user, warden_mock, {:scope => :user}) }
|
12
|
-
|
13
|
-
# let(:master_sso_session) { Sso::Session.generate_master(user, attributes) }
|
14
|
-
# let(:access_token) { Fabricate("Doorkeeper::AccessToken",
|
5
|
+
# Set up user
|
6
|
+
let(:user) { Fabricate(:user) }
|
7
|
+
# let(:application) { Fabricate('Doorkeeper::Application') }
|
8
|
+
# let(:access_token) { Fabricate('Doorkeeper::AccessToken',
|
15
9
|
# resource_owner_id: user.id) }
|
16
|
-
# let(:access_grant) { Fabricate('Doorkeeper::AccessGrant',
|
10
|
+
# let!(:access_grant) { Fabricate('Doorkeeper::AccessGrant',
|
11
|
+
# application_id: application.id,
|
17
12
|
# resource_owner_id: user.id,
|
18
13
|
# redirect_uri: 'http://localhost:3002/oauth/callback'
|
19
14
|
# ) }
|
20
15
|
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
|
27
|
-
|
28
|
-
#
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
16
|
+
# # Set up Session
|
17
|
+
# let(:session) { Fabricate('Sso::Session', owner: user) }
|
18
|
+
# let!(:client) { Fabricate('Sso::Client', session: session,
|
19
|
+
# application_id: application.id,
|
20
|
+
# access_token_id: access_token.id,
|
21
|
+
# access_grant_id: access_grant.id) }
|
22
|
+
|
23
|
+
# Set up rack
|
24
|
+
let(:proc) { described_class.to_proc }
|
25
|
+
let(:session_params) { { } }
|
26
|
+
let(:request) { double :request, ip: "10.10.10.133", user_agent: "I AM YOUR BROWSER", session: session_params }
|
27
|
+
let(:warden) { double :warden, request: request, authenticated?: true }
|
28
|
+
let(:options) { { scope: :user } }
|
29
|
+
subject(:rack) { described_class.new(user, warden, options) }
|
30
|
+
|
31
|
+
|
32
|
+
before do
|
33
|
+
Timecop.freeze
|
34
|
+
allow_any_instance_of(described_class).to receive(:session).and_return(session_params)
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '::to_proc' do
|
38
|
+
it 'is a proc' do
|
39
|
+
expect(proc).to be_instance_of Proc
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#call" do
|
44
|
+
it 'accepts the three warden arguments and returns nothing' do
|
45
|
+
expect(rack.call).to be_nil
|
46
|
+
end
|
47
|
+
|
48
|
+
it "run #generate_session" do
|
49
|
+
expect(rack).to receive(:generate_session)
|
50
|
+
rack.call
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#generate_session' do
|
55
|
+
it "generates master session" do
|
56
|
+
expect(::Sso::Session).to receive(:generate_master).with( user, { ip: "10.10.10.133", agent: "I AM YOUR BROWSER" } ).and_call_original
|
57
|
+
rack.call
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'sets the session' do
|
61
|
+
expect(rack.session["sso_session_id"]).to be_nil
|
62
|
+
rack.call
|
63
|
+
expect(rack.session["sso_session_id"]).to_not be_nil
|
64
|
+
end
|
65
|
+
end
|
36
66
|
end
|
@@ -1,31 +1,56 @@
|
|
1
1
|
require 'rails_helper'
|
2
2
|
|
3
|
-
# These tests are moot
|
4
3
|
RSpec.describe Sso::Warden::Hooks::BeforeLogout do
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
5
|
+
let(:proc) { described_class.to_proc }
|
6
|
+
let(:calling) { proc.call(user, warden, options) }
|
7
|
+
let(:session_params) { { "sso_session_id" => session.id } }
|
8
|
+
let!(:session) { Fabricate('Sso::Session') }
|
9
|
+
|
10
|
+
let(:user) { double :user }
|
11
|
+
let(:warden) { double :warden, request: {}, session: session_params, authenticated?: true }
|
12
|
+
let(:options) { { 'scope' => :user } }
|
13
|
+
subject(:rack) { described_class.new(user, warden, options) }
|
14
|
+
|
15
|
+
before do
|
16
|
+
Timecop.freeze
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '.to_proc' do
|
20
|
+
it 'is a proc' do
|
21
|
+
expect(proc).to be_instance_of Proc
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#call' do
|
26
|
+
it 'accepts the three warden arguments and returns nothing' do
|
27
|
+
expect(calling).to be_nil
|
28
|
+
end
|
29
|
+
|
30
|
+
context "when logged_in" do
|
31
|
+
before() { allow(rack).to receive(:logged_in?).and_return(true) }
|
32
|
+
|
33
|
+
it "run #logout" do
|
34
|
+
expect(::Sso::Session).to receive(:logout).with(session.id)
|
35
|
+
calling
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'revokes the passport' do
|
39
|
+
rack.call
|
40
|
+
session.reload
|
41
|
+
expect(session.revoked_at.to_i).to eq Time.now.to_i
|
42
|
+
expect(session.revoke_reason).to eq 'logout'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "when logged_out" do
|
47
|
+
before() { allow(rack).to receive(:logged_in?).and_return(false) }
|
48
|
+
|
49
|
+
it 'no error occurs' do
|
50
|
+
expect(rack.call).to be_nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
30
55
|
|
31
56
|
end
|
@@ -1,6 +1,20 @@
|
|
1
1
|
require 'rails_helper'
|
2
2
|
|
3
3
|
RSpec.describe Sso::Client, :type => :model do
|
4
|
+
let(:user) { Fabricate(:user) }
|
5
|
+
let(:application) { Fabricate('Doorkeeper::Application') }
|
6
|
+
let(:access_token) { Fabricate('Doorkeeper::AccessToken',
|
7
|
+
resource_owner_id: user.id) }
|
8
|
+
let(:access_grant) { Fabricate('Doorkeeper::AccessGrant',
|
9
|
+
application_id: application.id,
|
10
|
+
resource_owner_id: user.id,
|
11
|
+
redirect_uri: 'http://localhost:3002/oauth/callback'
|
12
|
+
) }
|
13
|
+
|
14
|
+
# Set up Session
|
15
|
+
let(:session) { Fabricate('Sso::Session', owner: user) }
|
16
|
+
|
17
|
+
|
4
18
|
describe "associations" do
|
5
19
|
it { is_expected.to belong_to(:session).class_name('Sso::Session').with_foreign_key(:sso_session_id) }
|
6
20
|
it { is_expected.to belong_to(:application).class_name('Doorkeeper::Application') }
|
@@ -12,4 +26,35 @@ RSpec.describe Sso::Client, :type => :model do
|
|
12
26
|
it { is_expected.to validate_uniqueness_of(:access_grant_id).allow_nil }
|
13
27
|
it { is_expected.to validate_uniqueness_of(:access_token_id).allow_nil }
|
14
28
|
end
|
29
|
+
|
30
|
+
describe "::find_by_grant_token" do
|
31
|
+
subject!(:client) { Fabricate('Sso::Client', session: session,
|
32
|
+
application_id: application.id,
|
33
|
+
access_grant_id: access_grant.id,
|
34
|
+
access_token_id: access_token.id) }
|
35
|
+
|
36
|
+
it { expect(::Sso::Client.find_by_grant_token(access_grant.token)).to eq client}
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "::find_by_access_token" do
|
40
|
+
subject!(:client) { Fabricate('Sso::Client', session: session,
|
41
|
+
application_id: application.id,
|
42
|
+
access_grant_id: access_grant.id,
|
43
|
+
access_token_id: access_token.id) }
|
44
|
+
|
45
|
+
it { expect(::Sso::Client.find_by_access_token(access_token.token)).to eq client }
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
describe "#update_access_token" do
|
50
|
+
subject!(:client) { Fabricate('Sso::Client', session: session,
|
51
|
+
application_id: application.id,
|
52
|
+
access_grant_id: access_grant.id) }
|
53
|
+
|
54
|
+
it "updates client with access token" do
|
55
|
+
expect(client.update_access_token(access_token.token)).to be_truthy
|
56
|
+
expect(client.access_token).to eq access_token
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
15
60
|
end
|
@@ -97,34 +97,6 @@ RSpec.describe Sso::Session, :type => :model do
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
100
|
-
# describe "::generate" do
|
101
|
-
# let(:master_sso_session) { Fabricate('Sso::Session') }
|
102
|
-
# let(:user) { Fabricate(:user) }
|
103
|
-
# let(:attributes) { { ip: "10.1.1.1", agent: "Safari" } }
|
104
|
-
# let(:access_token) { Fabricate("Doorkeeper::AccessToken", resource_owner_id: user.id) }
|
105
|
-
# let(:access_grant) { Fabricate('Doorkeeper::AccessGrant',
|
106
|
-
# application_id: nil,
|
107
|
-
# resource_owner_id: user.id,
|
108
|
-
# redirect_uri: 'http://localhost:3002/oauth/callback'
|
109
|
-
# ) }
|
110
|
-
|
111
|
-
# let(:session) { Sso::Session.generate(user, access_token, attributes) }
|
112
|
-
|
113
|
-
# before do
|
114
|
-
# master_sso_session.clients.create(access_token: access_token, access_grant: access_grant )
|
115
|
-
# # Notice: We assume our warden/doorkeeper is ok and a master with access grant/token is generated
|
116
|
-
# master_sso_session.access_token_id = access_token.id
|
117
|
-
# master_sso_session.access_grant_id = access_grant.id
|
118
|
-
# master_sso_session.save
|
119
|
-
# end
|
120
|
-
|
121
|
-
# describe "creates a new session" do
|
122
|
-
# it { expect(session.access_token_id).to eq access_token.id }
|
123
|
-
# it { expect(session.application_id).to eq access_token.application.id }
|
124
|
-
# it { expect(session.group_id).to eq master_sso_session.group_id }
|
125
|
-
# end
|
126
|
-
# end
|
127
|
-
|
128
100
|
describe "::logout" do
|
129
101
|
let!(:sso_session) { Fabricate('Sso::Session') }
|
130
102
|
let!(:user) { sso_session.owner }
|
@@ -149,52 +121,6 @@ RSpec.describe Sso::Session, :type => :model do
|
|
149
121
|
end
|
150
122
|
end
|
151
123
|
|
152
|
-
# describe "::update_master_with_grant" do
|
153
|
-
# let(:user) { Fabricate(:user) }
|
154
|
-
# let(:attributes) { { ip: "10.1.1.1", agent: "Safari" } }
|
155
|
-
# let(:access_token) { Fabricate("Doorkeeper::AccessToken", resource_owner_id: user.id) }
|
156
|
-
# let(:access_grant) { Fabricate('Doorkeeper::AccessGrant',
|
157
|
-
# application_id: nil,
|
158
|
-
# resource_owner_id: user.id,
|
159
|
-
# redirect_uri: 'http://localhost:3002/oauth/callback'
|
160
|
-
# ) }
|
161
|
-
# let!(:master_sso_session) { Sso::Session.generate_master(user, attributes) }
|
162
|
-
|
163
|
-
# context "successful" do
|
164
|
-
# it "updates master_sso_session.access_grant_id" do
|
165
|
-
# expect{ Sso::Session.update_master_with_grant(master_sso_session.id, access_grant) }.to change{ master_sso_session.reload.access_grant_id }.from(nil).to(access_grant.id)
|
166
|
-
# end
|
167
|
-
# end
|
168
|
-
# end
|
169
|
-
|
170
|
-
# describe "::update_master_with_access_token" do
|
171
|
-
# let(:user) { Fabricate(:user) }
|
172
|
-
# let(:attributes) { { ip: "10.1.1.1", agent: "Safari" } }
|
173
|
-
# let(:access_token) { Fabricate("Doorkeeper::AccessToken", resource_owner_id: user.id) }
|
174
|
-
# let(:access_grant) { Fabricate('Doorkeeper::AccessGrant',
|
175
|
-
# application_id: nil,
|
176
|
-
# resource_owner_id: user.id,
|
177
|
-
# redirect_uri: 'http://localhost:3002/oauth/callback'
|
178
|
-
# ) }
|
179
|
-
# let!(:master) { Sso::Session.generate_master(user, attributes) }
|
180
|
-
|
181
|
-
# before do
|
182
|
-
# # Notice: We assume our warden/doorkeeper is ok and a master with grant is generated
|
183
|
-
# master.access_grant_id = access_grant.id
|
184
|
-
# master.save
|
185
|
-
# end
|
186
|
-
|
187
|
-
# context "oauth_token not available" do
|
188
|
-
# it "returns false" do
|
189
|
-
# expect( Sso::Session.update_master_with_access_token(access_token.token, 123)).to be_falsey
|
190
|
-
# end
|
191
|
-
# end
|
192
|
-
|
193
|
-
# it "updates master.access_token_it" do
|
194
|
-
# expect{ Sso::Session.update_master_with_access_token(access_grant.token, access_token.token) }.to change{ master.reload.access_token_id }.from(nil).to(access_token.id)
|
195
|
-
# end
|
196
|
-
# end
|
197
|
-
|
198
124
|
end
|
199
125
|
|
200
126
|
# == Schema Information
|
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.2.
|
4
|
+
version: 0.2.5
|
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-
|
11
|
+
date: 2015-07-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: warden
|
@@ -347,6 +347,7 @@ files:
|
|
347
347
|
- lib/sso/warden/hooks/after_authentication.rb
|
348
348
|
- lib/sso/warden/hooks/before_logout.rb
|
349
349
|
- lib/sso/warden/hooks/session_check.rb
|
350
|
+
- lib/sso/warden/support.rb
|
350
351
|
- lib/tasks/sso_tasks.rake
|
351
352
|
- spec/api/schemas/session.json
|
352
353
|
- spec/controllers/sso/sessions_controller_spec.rb
|
@@ -360,6 +361,8 @@ files:
|
|
360
361
|
- spec/lib/doorkeeper/access_grant_mixin_spec.rb
|
361
362
|
- spec/lib/doorkeeper/access_token_mixin_spec.rb
|
362
363
|
- spec/lib/doorkeeper/application_mixin_spec.rb
|
364
|
+
- spec/lib/doorkeeper/authorizations_controller_mixin_spec.rb
|
365
|
+
- spec/lib/doorkeeper/tokens_controller_mixin_spec.rb
|
363
366
|
- spec/lib/sso/warden/hooks/after_authentication_spec.rb
|
364
367
|
- spec/lib/sso/warden/hooks/before_logout_spec.rb
|
365
368
|
- spec/models/sso/client_spec.rb
|
@@ -418,6 +421,8 @@ test_files:
|
|
418
421
|
- spec/lib/doorkeeper/access_grant_mixin_spec.rb
|
419
422
|
- spec/lib/doorkeeper/access_token_mixin_spec.rb
|
420
423
|
- spec/lib/doorkeeper/application_mixin_spec.rb
|
424
|
+
- spec/lib/doorkeeper/authorizations_controller_mixin_spec.rb
|
425
|
+
- spec/lib/doorkeeper/tokens_controller_mixin_spec.rb
|
421
426
|
- spec/lib/sso/warden/hooks/after_authentication_spec.rb
|
422
427
|
- spec/lib/sso/warden/hooks/before_logout_spec.rb
|
423
428
|
- spec/models/sso/client_spec.rb
|