doorkeeper_sso 0.0.4 → 0.1.0.pre.alpha

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1325cddaeea3ad9c0db0f7421de65c7d671f4e90
4
- data.tar.gz: f0c5fe37e55ee02487802801fda7c05ff6a9e679
3
+ metadata.gz: bb363d678a52d56ddf6c80dc8c1cff69deadd606
4
+ data.tar.gz: 1d6ac0652e3f375e675f62517f2f3a8b7fbd19f8
5
5
  SHA512:
6
- metadata.gz: 35345790590a3d6a0a534ae30dd7717793ef3cf12036f6baf0780ebb03c014ec51110aa97574ed7ff7e299eacfb82afa4dca32fb4e772dd8131a48655788221b
7
- data.tar.gz: 0da08dc94ecc077d572615e0dbf0ff0194529cd4dc5a57f23be4b4fb7d835e7352ab40f74acc61abd9fe0151e27d2591472049b19331aa6f8b067d47897491b6
6
+ metadata.gz: 4cddcc1c8862063eb257c05822e7bc0976e03eb7ea9ca69c2fea503994090b9258d53b5fe047072f23b73611fc5e53e3d1403761ba911a2558d19cdb845a20ec
7
+ data.tar.gz: 7b20aa56f12c66ef5dad229e625f85ea94d7a3f78e41061037e8def66057d1d0d01b416415d4eebb701860ebf5177f1d38797b1a17117a522c72825447635c7b
@@ -1,29 +1,32 @@
1
- class Sso::SessionsController < ApplicationController
1
+ module Sso
2
+ class SessionsController < ApplicationController
2
3
 
3
- before_action :authenticate_user!, only: :show
4
- before_action :doorkeeper_authorize!, only: :create
5
- before_action :find_user, only: :create
4
+ before_action :authenticate_user!, only: :show
5
+ before_action :doorkeeper_authorize!, only: :create
6
+ before_action :find_user, only: :create
6
7
 
7
- # TODO: Security issue?
8
- protect_from_forgery with: :null_session
8
+ # TODO: Security issue?
9
+ protect_from_forgery with: :null_session
9
10
 
10
- respond_to :json
11
+ respond_to :json
11
12
 
12
- # Returns a 200 if access is granted
13
- def show
14
- render :nothing => true
15
- end
13
+ # Returns a 200 if access is granted
14
+ def show
15
+ render :nothing => true
16
+ end
16
17
 
17
- # Generate an SSO:Session
18
- def create
19
- @session = Sso::Session.generate(@user, doorkeeper_token, params )
20
- respond_with @session, :location => sso.sessions_url
21
- end
18
+ # Generate an SSO:Session
19
+ def create
20
+ render json: {}
21
+ # @session = Sso::Session.generate(@user, doorkeeper_token, params )
22
+ # respond_with @session, :location => sso.sessions_url
23
+ end
22
24
 
23
- protected
25
+ protected
24
26
 
25
- def find_user
26
- @user = User.find(doorkeeper_token.resource_owner_id)
27
- end
27
+ def find_user
28
+ @user = User.find(doorkeeper_token.resource_owner_id)
29
+ end
28
30
 
31
+ end
29
32
  end
@@ -1,4 +1,24 @@
1
1
  module Sso
2
2
  module ApplicationHelper
3
+ # Can search for named routes directly in the main app, omitting
4
+ # the "main_app." prefix
5
+ def method_missing method, *args, &block
6
+ if main_app_url_helper?(method)
7
+ main_app.send(method, *args)
8
+ else
9
+ super
10
+ end
11
+ end
12
+
13
+ def respond_to?(method)
14
+ main_app_url_helper?(method) or super
15
+ end
16
+
17
+ private
18
+
19
+ def main_app_url_helper?(method)
20
+ (method.to_s.end_with?('_path') or method.to_s.end_with?('_url')) and
21
+ main_app.respond_to?(method)
22
+ end
3
23
  end
4
24
  end
@@ -63,13 +63,13 @@ module Sso
63
63
  end
64
64
 
65
65
  def update_master_with_access_token(grant_token, access_token)
66
- oauth_grant = Doorkeeper::AccessGrant.by_token(grant_token)
67
- oauth_token = Doorkeeper::AccessToken.by_token(access_token)
66
+ oauth_grant = ::Doorkeeper::AccessGrant.by_token(grant_token)
67
+ oauth_token = ::Doorkeeper::AccessToken.by_token(access_token)
68
68
  return false if oauth_token.blank? or oauth_grant.blank?
69
69
 
70
70
  master_sso_session = active.master.find_by!(access_grant_id: oauth_grant.id)
71
71
 
72
- if master_sso_session.update_attribute(:access_token_id, oauth_token.id)
72
+ if master_sso_session.update_attributes(access_token_id: oauth_token.id, application_id: oauth_token.application_id)
73
73
  debug { "#register_access_token : #{master_sso_session.id} with Access Token ID #{oauth_token.id} which is #{oauth_token.token}" }
74
74
  else
75
75
  error { "#register_access_token : FAILED to update oauth_access_token_id" }
@@ -0,0 +1,24 @@
1
+ module Sso
2
+ module Doorkeeper
3
+ module AuthorizationsControllerMixin
4
+ extend ActiveSupport::Concern
5
+ include ::Sso::Logging
6
+
7
+ included do
8
+ after_action :after_grant_create, only: [:new, :create]
9
+ end
10
+
11
+ protected
12
+
13
+ def after_grant_create
14
+ debug { "AuthorizationsController#Create : after_action" }
15
+ code_response = authorization.instance_variable_get("@response")
16
+ if code_response
17
+ warden_session = session["warden.user.user.session"]
18
+ debug { "Sso::Session.update_master_with_grant - #{warden_session["sso_session_id"].inspect}, #{code_response.auth.token.inspect}" }
19
+ Sso::Session.update_master_with_grant(warden_session["sso_session_id"], code_response.auth.token)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,41 @@
1
+ module Sso
2
+ module Doorkeeper
3
+ module TokensControllerMixin
4
+ included do
5
+ after_action :after_token_create, only: :create
6
+ end
7
+
8
+ protected
9
+
10
+ def after_token_create
11
+ debug { "TokensController#Create : after_action" }
12
+ handle_authorization_grant_flow
13
+ end
14
+
15
+ def handle_authorization_grant_flow
16
+ # We cannot rely on session[:sso_session_id] here because the end-user might have cookies disabled.
17
+ # The only thing we can rely on to identify the user/Passport is the incoming grant token.
18
+ debug { %(Detected outgoing "Access Token" #{outgoing_access_token.inspect}) }
19
+ if sso_session = Sso::Session.update_master_with_access_token(grant_token, outgoing_access_token)
20
+ debug { "::Sso::Session.register_access_token success for access_token: #{outgoing_access_token}" }
21
+ else
22
+ debug { "::Sso::Session.register_access_token failed. #{sso_session.errors.inspect}" }
23
+ warden.logout
24
+ end
25
+ end
26
+
27
+ def grant_token
28
+ params["code"]
29
+ end
30
+
31
+ def grant_type
32
+ params["grant_type"]
33
+ end
34
+
35
+ def outgoing_access_token
36
+ @response_hash ||= JSON.parse(response.body)
37
+ @response_hash["access_token"]
38
+ end
39
+ end
40
+ end
41
+ end
data/lib/sso/engine.rb CHANGED
@@ -1,5 +1,19 @@
1
1
  module Sso
2
2
  class Engine < ::Rails::Engine
3
3
  isolate_namespace Sso
4
+
5
+ config.after_initialize do
6
+
7
+ ::Doorkeeper::TokensController.send(:include, AbstractController::Callbacks)
8
+ ::Doorkeeper::TokensController.send(:include, Sso::Doorkeeper::TokensControllerMixin)
9
+ ::Doorkeeper::AuthorizationsController.send(:include, Sso::Doorkeeper::AuthorizationsControllerMixin)
10
+
11
+ ::Warden::Manager.after_authentication(scope: :user, &::Sso::Warden::Hooks::AfterAuthentication.to_proc)
12
+ ::Warden::Manager.before_logout(scope: :user, &::Sso::Warden::Hooks::BeforeLogout.to_proc)
13
+
14
+ # TODO : Why does it need a passport strategy
15
+ # Warden::Strategies.add :passport, ::Sso::Server::Warden::Strategies::Passport
16
+
17
+ end
4
18
  end
5
19
  end
data/lib/sso/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Sso
2
- VERSION = "0.0.4"
2
+ VERSION = "0.1.0-alpha"
3
3
  end
@@ -0,0 +1,34 @@
1
+ module Sso
2
+ module Warden
3
+ module Hooks
4
+ class AfterAuthentication
5
+ include ::Sso::Logging
6
+
7
+ attr_reader :user, :warden, :options
8
+
9
+ def self.to_proc
10
+ proc do |user, warden, options|
11
+ new(user: user, warden: warden, options: options).call
12
+ end
13
+ end
14
+
15
+ def initialize(user:, warden:, options:)
16
+ @user, @warden, @options = user, warden, options
17
+ end
18
+
19
+ def call
20
+ debug { "Starting hook because this is considered the first login of the current session..." }
21
+ request = warden.request
22
+ session = warden.session(:user)
23
+
24
+ debug { "Generating a Sso:Session for user #{user.id.inspect} for the session cookie at the Sso server..." }
25
+ attributes = { ip: request.ip, agent: request.user_agent }
26
+
27
+ sso_session = Sso::Session.generate_master(user, attributes)
28
+ debug { "Sso:Session with ID #{sso_session.id} generated successfuly. Persisting it in session..." }
29
+ session["sso_session_id"] = sso_session.id.to_s
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ module Sso
2
+ module Warden
3
+ module Hooks
4
+ class BeforeLogout
5
+ include ::Sso::Logging
6
+
7
+ attr_reader :user, :warden, :options
8
+ delegate :request, to: :warden
9
+ delegate :params, to: :request
10
+ delegate :session, to: :request
11
+
12
+ def self.to_proc
13
+ proc do |user, warden, options|
14
+ new(user: user, warden: warden, options: options).call
15
+ end
16
+ end
17
+
18
+ def initialize(user:, warden:, options:)
19
+ @user, @warden, @options = user, warden, options
20
+ end
21
+
22
+ def call
23
+ # Only run if user is logged in
24
+ if warden.authenticated?(:user) && (session = warden.session(:user))
25
+ debug { 'Destroy all Sso::Session groups before logout' }
26
+ debug { session.inspect }
27
+ Sso::Session.logout(session["sso_session_id"])
28
+ #Passports.logout passport_id: params['passport_id'], provider_passport_id: session['sso_session_id']
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
data/lib/sso.rb CHANGED
@@ -1,5 +1,10 @@
1
1
  require "sso/engine"
2
2
  require "sso/logging"
3
+ require "sso/warden/hooks/after_authentication"
4
+ require "sso/warden/hooks/before_logout"
5
+ require "sso/doorkeeper/authorizations_controller_mixin"
6
+ require "sso/doorkeeper/tokens_controller_mixin"
7
+
3
8
 
4
9
  module Sso
5
10
  def self.table_name_prefix
@@ -0,0 +1,14 @@
1
+ class ApplicationController < ActionController::Base
2
+ # Prevent CSRF attacks by raising an exception.
3
+ # For APIs, you may want to use :null_session instead.
4
+ protect_from_forgery with: :exception
5
+
6
+ before_action :configure_permitted_parameters, if: :devise_controller?
7
+
8
+ protected
9
+
10
+ def configure_permitted_parameters
11
+ devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:first_name, :last_name, :email, :password, :password_confirmation) }
12
+ end
13
+
14
+ 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.0.4
4
+ version: 0.1.0.pre.alpha
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-04-15 00:00:00.000000000 Z
11
+ date: 2015-04-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -275,14 +275,8 @@ files:
275
275
  - Rakefile
276
276
  - app/assets/javascripts/sso/application.js
277
277
  - app/assets/stylesheets/sso/application.css
278
- - app/controllers/application_controller.rb
279
- - app/controllers/doorkeeper/authorizations_controller.rb
280
- - app/controllers/doorkeeper/tokens_controller.rb
281
278
  - app/controllers/sso/sessions_controller.rb
282
279
  - app/helpers/sso/application_helper.rb
283
- - app/middleware/sso/access_token_marker.rb
284
- - app/middleware/sso/authorization_grant_marker.rb
285
- - app/middleware/sso/passport_verification.rb
286
280
  - app/models/sso/session.rb
287
281
  - app/views/layouts/doorkeeper/admin.html.erb
288
282
  - app/views/layouts/doorkeeper/application.html.erb
@@ -291,9 +285,13 @@ files:
291
285
  - db/migrate/20150414102248_create_sso_sessions.rb
292
286
  - lib/doorkeeper_sso.rb
293
287
  - lib/sso.rb
288
+ - lib/sso/doorkeeper/authorizations_controller_mixin.rb
289
+ - lib/sso/doorkeeper/tokens_controller_mixin.rb
294
290
  - lib/sso/engine.rb
295
291
  - lib/sso/logging.rb
296
292
  - lib/sso/version.rb
293
+ - lib/sso/warden/hooks/after_authentication.rb
294
+ - lib/sso/warden/hooks/before_logout.rb
297
295
  - lib/tasks/sso_tasks.rake
298
296
  - spec/controllers/sso/sessions_controller_spec.rb
299
297
  - spec/fabricators/api_application_fabricator.rb
@@ -310,6 +308,7 @@ files:
310
308
  - spec/support/fabrication.rb
311
309
  - spec/support/vcr.rb
312
310
  - spec/test_app/Rakefile
311
+ - spec/test_app/app/controllers/application_controller.rb
313
312
  - spec/test_app/app/models/user.rb
314
313
  - spec/test_app/config/database.yml
315
314
  - spec/test_app/config/initializers/devise.rb
@@ -332,9 +331,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
332
331
  version: '0'
333
332
  required_rubygems_version: !ruby/object:Gem::Requirement
334
333
  requirements:
335
- - - ">="
334
+ - - ">"
336
335
  - !ruby/object:Gem::Version
337
- version: '0'
336
+ version: 1.3.1
338
337
  requirements: []
339
338
  rubyforge_project:
340
339
  rubygems_version: 2.4.5
@@ -356,6 +355,7 @@ test_files:
356
355
  - spec/support/devise.rb
357
356
  - spec/support/fabrication.rb
358
357
  - spec/support/vcr.rb
358
+ - spec/test_app/app/controllers/application_controller.rb
359
359
  - spec/test_app/app/models/user.rb
360
360
  - spec/test_app/config/database.yml
361
361
  - spec/test_app/config/initializers/devise.rb
@@ -364,3 +364,4 @@ test_files:
364
364
  - spec/test_app/db/schema.rb
365
365
  - spec/test_app/public/favicon.ico
366
366
  - spec/test_app/Rakefile
367
+ has_rdoc:
@@ -1,3 +0,0 @@
1
- class ApplicationController < ActionController::Base
2
-
3
- end
@@ -1,18 +0,0 @@
1
- module Doorkeeper
2
- class AuthorizationsController < Doorkeeper::ApplicationController
3
-
4
- after_action :after_grant_create, only: [:new, :create]
5
-
6
- protected
7
-
8
- def after_grant_create
9
- Rails.logger.info "AuthorizationsController#Create : after_action"
10
- code_response = authorization.instance_variable_get("@response")
11
- if code_response
12
- warden_session = session["warden.user.user.session"]
13
- Rails.logger.debug "Sso::Session.update_master_with_grant - #{warden_session["sso_session_id"].inspect}, #{code_response.auth.token.inspect}"
14
- Sso::Session.update_master_with_grant(warden_session["sso_session_id"], code_response.auth.token)
15
- end
16
- end
17
- end
18
- end
@@ -1,39 +0,0 @@
1
- module Doorkeeper
2
- class TokensController < Doorkeeper::ApplicationMetalController
3
- include AbstractController::Callbacks
4
-
5
- after_action :after_token_create, only: :create
6
-
7
- protected
8
-
9
- def after_token_create
10
- Rails.logger.info "TokensController#Create : after_action"
11
- handle_authorization_grant_flow
12
- end
13
-
14
- def handle_authorization_grant_flow
15
- # We cannot rely on session[:sso_session_id] here because the end-user might have cookies disabled.
16
- # The only thing we can rely on to identify the user/Passport is the incoming grant token.
17
- Rails.logger.debug { %(Detected outgoing "Access Token" #{outgoing_access_token.inspect}) }
18
- if sso_session = Sso::Session.update_master_with_access_token(grant_token, outgoing_access_token)
19
- Rails.logger.debug "::Sso::Session.register_access_token success for access_token: #{outgoing_access_token}"
20
- else
21
- Rails.logger.debug "::Sso::Session.register_access_token failed. #{sso_session.errors.inspect}"
22
- warden.logout
23
- end
24
- end
25
-
26
- def grant_token
27
- params["code"]
28
- end
29
-
30
- def grant_type
31
- params["grant_type"]
32
- end
33
-
34
- def outgoing_access_token
35
- @response_hash ||= JSON.parse(response.body)
36
- @response_hash["access_token"]
37
- end
38
- end
39
- end
@@ -1,103 +0,0 @@
1
- # app/middleware/sso/access_token_marker.rb
2
- # Middleware that catches outgoing Doorkeeper access tokens
3
-
4
- module Sso
5
- class AccessTokenMarker
6
-
7
- def initialize(app)
8
- @app = app
9
- end
10
-
11
- def call(env)
12
- @env = env
13
- @request = ::ActionDispatch::Request.new @env
14
- @response = @app.call @env
15
-
16
- return response unless request.method == 'POST'
17
- return response unless authorization_grant_flow? || password_credential_flow?
18
- return response unless response_code == 200
19
- return response unless response_body
20
- return response unless outgoing_access_token
21
-
22
- if authorization_grant_flow?
23
- Rails.logger.debug { %{Detected outgoing "Access Token" #{outgoing_access_token.inspect} of the "Authorization Code Grant" flow (belonging to "Authorization Grant Token" #{grant_token.inspect}). Augmenting related Passport with it.} }
24
- registration = ::Passports.register_access_token grant_token: grant_token, access_token: outgoing_access_token
25
-
26
- if registration.failure?
27
- Rails.logger.warn { "The passport could not be augmented. Destroying warden session." }
28
- warden.logout
29
- end
30
-
31
- elsif password_credential_flow?
32
- Rails.logger.debug { %{Detected outgoing "Access Token" #{outgoing_access_token.inspect} of the "Resource Owner Password Credentials Grant" flow. Generating new Passport with it.} }
33
- generation = ::Passports.generate_with_access_token access_token_string: outgoing_access_token, ip: request.ip, agent: request.user_agent
34
-
35
- if generation.failure?
36
- Rails.logger.warn { "The passport could not be generated. Destroying warden session." }
37
- warden.logout
38
- end
39
-
40
- else
41
- fail NotImplementedError
42
- end
43
-
44
- response
45
- end
46
-
47
- def request
48
- @request
49
- end
50
-
51
- def response
52
- @response
53
- end
54
-
55
- def response_body
56
- response.last.first.presence
57
- # raise response.last.inspect
58
- end
59
-
60
- def response_code
61
- response.first
62
- end
63
-
64
- def parsed_response_body
65
- # raise response_body.inspect
66
- return unless response_body
67
- ::JSON.parse response_body
68
- rescue JSON::ParserError => exception
69
- Trouble.notify exception
70
- nil
71
- end
72
-
73
- def outgoing_access_token
74
- return unless parsed_response_body
75
- parsed_response_body['access_token']
76
- end
77
-
78
- def warden
79
- request.env['warden']
80
- end
81
-
82
- def params
83
- request.params
84
- end
85
-
86
- def authorization_grant_flow?
87
- grant_token.present?
88
- end
89
-
90
- def password_credential_flow?
91
- grant_type == 'password'
92
- end
93
-
94
- def grant_token
95
- params['code']
96
- end
97
-
98
- def grant_type
99
- params['grant_type']
100
- end
101
-
102
- end
103
- end
@@ -1,87 +0,0 @@
1
- # app/middleware/sso/authorization_grant_maker.rb
2
- # Middleware that catches outgoing Doorkeeper authorization grants
3
-
4
- module Sso
5
- class AuthorizationGrantMarker
6
-
7
- def initialize(app)
8
- @app = app
9
- end
10
-
11
- def call(env)
12
- @env = env
13
- @response = @app.call @env
14
-
15
- return response unless outgoing_grant_token
16
-
17
- if passport_id
18
- Rails.logger.debug { %{Detected outgoing "Authorization Grant Token" #{outgoing_grant_token.inspect} of the "Authorization Code Grant" flow. Augmenting Passport #{passport_id.inspect} with it.} }
19
- registration = ::Passports.register_authorization_grant passport_id: passport_id, token: outgoing_grant_token
20
-
21
- if registration.failure?
22
- Rails.logger.warn { "The passport could not be augmented. Destroying warden session." }
23
- warden.logout
24
- end
25
- end
26
-
27
- response
28
- end
29
-
30
- def request
31
- ::ActionDispatch::Request.new @env
32
- end
33
-
34
- def response
35
- @response
36
- end
37
-
38
- def code
39
- response.first
40
- end
41
-
42
- def session
43
- request.session
44
- end
45
-
46
- def warden
47
- request.env['warden']
48
- end
49
-
50
- def passport_id
51
- session['passport_id']
52
- end
53
-
54
- def location_header
55
- unless code == 302
56
- #logger.debug { "Uninteresting response, because it is not a redirect" }
57
- return
58
- end
59
-
60
- response.second['Location']
61
- end
62
-
63
- def redirect_uri
64
- unless location_header
65
- #logger.debug { "Uninteresting response, because there is no Location header" }
66
- return
67
- end
68
-
69
- ::URI.parse location_header
70
- end
71
-
72
- def redirect_uri_params
73
- return unless redirect_uri
74
- ::Rack::Utils.parse_query redirect_uri.query
75
- end
76
-
77
- def outgoing_grant_token
78
- unless redirect_uri_params && redirect_uri_params['code']
79
- #logger.debug { "Uninteresting response, because there is no code parameter sent" }
80
- return
81
- end
82
-
83
- redirect_uri_params['code']
84
- end
85
-
86
- end
87
- end
@@ -1,25 +0,0 @@
1
- # app/middleware/sso/passport_verification.rb
2
- # A Middleware to verify incoming requests by client applications
3
- # which would like to verify the passport a user presented to them
4
-
5
- module Sso
6
- class PassportVerification
7
-
8
- def initialize(app)
9
- @app = app
10
- end
11
-
12
- def call(env)
13
- request = Rack::Request.new(env)
14
-
15
- if request.path == '/api/v1/passports/verify'
16
- logger.debug { "Detected Passport verification request." }
17
- env['warden'].authenticate! :passport
18
- else
19
- # logger.debug { "I'm not interested in this request to #{request.path}" }
20
- @app.call(env)
21
- end
22
- end
23
-
24
- end
25
- end