doorkeeper_sso 0.2.3 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|