rails_sso 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +19 -8
- data/Rakefile +0 -15
- data/app/controllers/rails_sso/sessions_controller.rb +2 -3
- data/app/services/rails_sso/fetch_user.rb +19 -0
- data/{lib → app/services}/rails_sso/update_user.rb +3 -3
- data/lib/rails_sso/access_token.rb +52 -0
- data/lib/rails_sso/helpers.rb +31 -17
- data/lib/rails_sso/version.rb +1 -1
- data/lib/rails_sso.rb +5 -2
- data/test/controllers/rails_sso/sessions_controller_test.rb +43 -0
- data/test/dummy/app/controllers/application_controller.rb +4 -0
- data/test/dummy/config/initializers/sso.rb +13 -0
- data/test/dummy/config/routes.rb +2 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/test.log +2017 -0
- data/test/services/rails_sso/fetch_user_test.rb +46 -0
- data/test/services/rails_sso/update_user_test.rb +79 -0
- data/test/test_helper.rb +1 -0
- metadata +75 -6
- data/lib/rails_sso/fetch_user.rb +0 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d21cea945bc44cb3fb84f1d2da048091d6f4661
|
4
|
+
data.tar.gz: 9f4bef5ac2353b226593a063a301cad4f618818a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a2dd465782b4e9372594fbfd531edf0d769f0f285fbf663e8e2855ad12c348cfb0e8614ba75dc573b8d0fcd622ff0f7946efcc6e0b306cd24db7f56c26b9799
|
7
|
+
data.tar.gz: 8efb688b7383bcb5aa783e610d94317ecd22fb7aa5f514d829da0cde7836f76ed3a42a5567a17a88516fb38b96314ace659d81bd829eec0e514c49c8691e694f
|
data/README.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# SSO client Rails Engine
|
2
2
|
|
3
|
+
[![Dependency Status](https://gemnasium.com/monterail/rails_sso.svg)](https://gemnasium.com/monterail/rails_sso)
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/rails_sso.svg)](http://badge.fury.io/rb/rails_sso)
|
5
|
+
|
6
|
+
## About
|
7
|
+
|
8
|
+
*SOON*
|
9
|
+
|
3
10
|
## Installation
|
4
11
|
|
5
12
|
Add engine and [omniauth](https://github.com/intridea/omniauth-oauth2) provider gems to your project:
|
@@ -26,6 +33,8 @@ RailsSso.configure do |config|
|
|
26
33
|
config.provider_profile_path = '/api/v1/profile'
|
27
34
|
# set if you support single sign out
|
28
35
|
config.provider_sign_out_path = '/api/v1/session'
|
36
|
+
# enable cache (will use Rails.cache store)
|
37
|
+
config.use_cache = Rails.application.config.action_controller.perform_caching
|
29
38
|
|
30
39
|
# user fields to synchronize from API
|
31
40
|
config.user_fields = [
|
@@ -56,9 +65,11 @@ Available helpers for controllers and views:
|
|
56
65
|
* `current_user`
|
57
66
|
* `user_signed_in?`
|
58
67
|
|
59
|
-
Available filters for controllers:
|
68
|
+
Available filters and helpers for controllers:
|
60
69
|
|
61
70
|
* `authenticate_user!`
|
71
|
+
* `save_access_token!`
|
72
|
+
* `invalidate_access_token!`
|
62
73
|
|
63
74
|
Available helpers for views:
|
64
75
|
|
@@ -69,11 +80,11 @@ Available helpers for views:
|
|
69
80
|
|
70
81
|
Required methods:
|
71
82
|
|
72
|
-
* `
|
73
|
-
* `
|
83
|
+
* `find_by_sso_id(id)`
|
84
|
+
* `create_with_sso_id(id, attrs)`
|
74
85
|
* `update(record, attrs)`
|
75
86
|
|
76
|
-
Example:
|
87
|
+
Example with `ActiveRecord` user model:
|
77
88
|
|
78
89
|
```ruby
|
79
90
|
# app/repositories/user_repository.rb
|
@@ -85,13 +96,13 @@ class UserRepository
|
|
85
96
|
self.adapter = adapter
|
86
97
|
end
|
87
98
|
|
88
|
-
def
|
89
|
-
adapter.find_by(
|
99
|
+
def find_by_sso_id(id)
|
100
|
+
adapter.find_by(sso_id: id)
|
90
101
|
end
|
91
102
|
|
92
|
-
def
|
103
|
+
def create_with_sso_id(id, attrs)
|
93
104
|
adapter.new(attrs) do |user|
|
94
|
-
user.
|
105
|
+
user.sso_id = id
|
95
106
|
user.save!
|
96
107
|
end
|
97
108
|
end
|
data/Rakefile
CHANGED
@@ -4,21 +4,6 @@ rescue LoadError
|
|
4
4
|
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
5
|
end
|
6
6
|
|
7
|
-
require 'rdoc/task'
|
8
|
-
|
9
|
-
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
-
rdoc.rdoc_dir = 'rdoc'
|
11
|
-
rdoc.title = 'RailsSso'
|
12
|
-
rdoc.options << '--line-numbers'
|
13
|
-
rdoc.rdoc_files.include('README.rdoc')
|
14
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
-
end
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
7
|
Bundler::GemHelper.install_tasks
|
23
8
|
|
24
9
|
require 'rake/testtask'
|
@@ -3,14 +3,13 @@ module RailsSso
|
|
3
3
|
skip_before_action :authenticate_user!, only: [:create]
|
4
4
|
|
5
5
|
def create
|
6
|
-
|
7
|
-
session[:refresh_token] = auth_hash.credentials.refresh_token
|
6
|
+
save_access_token!(auth_hash.credentials)
|
8
7
|
|
9
8
|
redirect_to root_path
|
10
9
|
end
|
11
10
|
|
12
11
|
def destroy
|
13
|
-
|
12
|
+
invalidate_access_token!
|
14
13
|
|
15
14
|
redirect_to root_path
|
16
15
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RailsSso
|
2
|
+
class FetchUser
|
3
|
+
def initialize(access_token)
|
4
|
+
@access_token = access_token
|
5
|
+
end
|
6
|
+
|
7
|
+
def call
|
8
|
+
yield(get)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
attr_reader :access_token
|
14
|
+
|
15
|
+
def get
|
16
|
+
access_token.get(RailsSso.provider_profile_path).parsed
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,16 +1,16 @@
|
|
1
1
|
module RailsSso
|
2
2
|
class UpdateUser
|
3
3
|
def initialize(data, options = {})
|
4
|
-
@id, @data = data.
|
4
|
+
@id, @data = data['id'], data.except('id')
|
5
5
|
@fields, @repository = options.values_at(:fields, :repository)
|
6
6
|
end
|
7
7
|
|
8
8
|
def call
|
9
|
-
if user = repository.
|
9
|
+
if user = repository.find_by_sso_id(id)
|
10
10
|
repository.update(user, params)
|
11
11
|
user
|
12
12
|
else
|
13
|
-
repository.
|
13
|
+
repository.create_with_sso_id(id, params)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'faraday-http-cache'
|
2
|
+
|
3
|
+
module RailsSso
|
4
|
+
class AccessToken
|
5
|
+
attr_reader :token, :refresh_token
|
6
|
+
|
7
|
+
delegate :get, :patch, :post, :put, :delete, to: :access_token
|
8
|
+
|
9
|
+
def self.from_access_token(access_token)
|
10
|
+
new(access_token.token, access_token.refresh_token)
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(token, refresh_token)
|
14
|
+
@token, @refresh_token = token, refresh_token
|
15
|
+
end
|
16
|
+
|
17
|
+
def refresh!
|
18
|
+
self.class.from_access_token(access_token.refresh!)
|
19
|
+
end
|
20
|
+
|
21
|
+
def access_token
|
22
|
+
@access_token ||= OAuth2::AccessToken.new(client, token, {
|
23
|
+
refresh_token: refresh_token
|
24
|
+
})
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def client
|
30
|
+
strategy.client.tap do |c|
|
31
|
+
if RailsSso.use_cache
|
32
|
+
c.options[:connection_build] = Proc.new do |conn|
|
33
|
+
conn.use :http_cache,
|
34
|
+
store: Rails.cache,
|
35
|
+
logger: Rails.logger,
|
36
|
+
shared_cache: false
|
37
|
+
|
38
|
+
conn.adapter Faraday.default_adapter
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def strategy
|
45
|
+
@strategy ||= strategy_class.new(nil, RailsSso.provider_key, RailsSso.provider_secret)
|
46
|
+
end
|
47
|
+
|
48
|
+
def strategy_class
|
49
|
+
"OmniAuth::Strategies::#{RailsSso.provider_name.classify}".constantize
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/rails_sso/helpers.rb
CHANGED
@@ -7,7 +7,9 @@ module RailsSso
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def current_user
|
10
|
-
@current_user ||= fetch_user
|
10
|
+
@current_user ||= fetch_user do |user|
|
11
|
+
update_user(user).call
|
12
|
+
end
|
11
13
|
end
|
12
14
|
|
13
15
|
def user_signed_in?
|
@@ -18,7 +20,11 @@ module RailsSso
|
|
18
20
|
redirect_to sign_in_path unless user_signed_in?
|
19
21
|
end
|
20
22
|
|
21
|
-
def
|
23
|
+
def access_token
|
24
|
+
RailsSso::AccessToken.new(session[:access_token], session[:refresh_token])
|
25
|
+
end
|
26
|
+
|
27
|
+
def invalidate_access_token!
|
22
28
|
if RailsSso.provider_sign_out_path
|
23
29
|
access_token.delete(RailsSso.provider_sign_out_path)
|
24
30
|
end
|
@@ -26,32 +32,40 @@ module RailsSso
|
|
26
32
|
reset_session
|
27
33
|
end
|
28
34
|
|
29
|
-
|
35
|
+
def save_access_token!(access_token)
|
36
|
+
session[:access_token] = access_token.token
|
37
|
+
session[:refresh_token] = access_token.refresh_token
|
38
|
+
end
|
30
39
|
|
31
|
-
def
|
32
|
-
|
40
|
+
def refresh_access_token!
|
41
|
+
save_access_token!(access_token.refresh!)
|
33
42
|
|
34
|
-
|
43
|
+
yield if block_given?
|
35
44
|
rescue ::OAuth2::Error
|
36
45
|
nil
|
37
46
|
end
|
38
47
|
|
39
|
-
|
40
|
-
OAuth2::AccessToken.new(oauth_client, session[:access_token], {
|
41
|
-
refresh_token: session[:refresh_token]
|
42
|
-
})
|
43
|
-
end
|
48
|
+
private
|
44
49
|
|
45
|
-
def
|
46
|
-
|
50
|
+
def fetch_user(&block)
|
51
|
+
return unless session[:access_token]
|
52
|
+
|
53
|
+
RailsSso::FetchUser.new(access_token).call(&block)
|
54
|
+
rescue ::OAuth2::Error
|
55
|
+
refresh_access_token! do
|
56
|
+
RailsSso::FetchUser.new(access_token).call(&block)
|
57
|
+
end
|
47
58
|
end
|
48
59
|
|
49
|
-
def
|
50
|
-
|
60
|
+
def update_user(data)
|
61
|
+
RailsSso::UpdateUser.new(data, update_user_options).call
|
51
62
|
end
|
52
63
|
|
53
|
-
def
|
54
|
-
|
64
|
+
def update_user_options
|
65
|
+
{
|
66
|
+
fields: RailsSso.user_fields,
|
67
|
+
repository: RailsSso.user_repository.new
|
68
|
+
}
|
55
69
|
end
|
56
70
|
end
|
57
71
|
end
|
data/lib/rails_sso/version.rb
CHANGED
data/lib/rails_sso.rb
CHANGED
@@ -14,6 +14,9 @@ module RailsSso
|
|
14
14
|
mattr_accessor :user_fields
|
15
15
|
@@user_fields = [:email]
|
16
16
|
|
17
|
+
mattr_accessor :use_cache
|
18
|
+
@@use_cache = false
|
19
|
+
|
17
20
|
def self.configure
|
18
21
|
yield self
|
19
22
|
end
|
@@ -27,8 +30,8 @@ module RailsSso
|
|
27
30
|
end
|
28
31
|
end
|
29
32
|
|
33
|
+
require 'omniauth-oauth2'
|
30
34
|
require 'rails_sso/version'
|
31
35
|
require 'rails_sso/engine'
|
32
36
|
require 'rails_sso/helpers'
|
33
|
-
require 'rails_sso/
|
34
|
-
require 'rails_sso/fetch_user'
|
37
|
+
require 'rails_sso/access_token'
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class RailsSso::SessionsControllerTest < ActionController::TestCase
|
4
|
+
def setup
|
5
|
+
@routes = RailsSso::Engine.routes
|
6
|
+
|
7
|
+
@auth_hash = OmniAuth::AuthHash.new({
|
8
|
+
provider: 'developer',
|
9
|
+
uid: '1',
|
10
|
+
name: 'Kowalski',
|
11
|
+
email: 'jan@kowalski.pl',
|
12
|
+
key: 'value'
|
13
|
+
})
|
14
|
+
|
15
|
+
OmniAuth.config.mock_auth[:developer] = @auth_hash
|
16
|
+
|
17
|
+
request.env['omniauth.auth'] = OmniAuth.config.mock_auth[:developer]
|
18
|
+
end
|
19
|
+
|
20
|
+
def teardown
|
21
|
+
OmniAuth.config.mock_auth[:developer] = nil
|
22
|
+
end
|
23
|
+
|
24
|
+
test 'create should save access token and redirect to root path' do
|
25
|
+
@controller.expects(:save_access_token!).with(@auth_hash.credentials).once
|
26
|
+
|
27
|
+
get :create, { provider: 'developer' }
|
28
|
+
|
29
|
+
assert_redirected_to main_app.root_path
|
30
|
+
end
|
31
|
+
|
32
|
+
test 'destroy should invalidate access token and redirect to root path' do
|
33
|
+
@controller.expects(:invalidate_access_token!).once
|
34
|
+
|
35
|
+
delete :destroy, {}, { access_token: 'abc', refresh_token: 'def' }
|
36
|
+
|
37
|
+
assert_redirected_to main_app.root_path
|
38
|
+
end
|
39
|
+
|
40
|
+
def main_app
|
41
|
+
Rails.application.class.routes.url_helpers
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
RailsSso.configure do |config|
|
2
|
+
config.provider_name = 'developer'
|
3
|
+
config.provider_key = 'key'
|
4
|
+
config.provider_secret = 'secret'
|
5
|
+
config.provider_profile_path = '/api/v1/me'
|
6
|
+
config.provider_sign_out_path = '/api/v1/me'
|
7
|
+
config.use_cache = false
|
8
|
+
config.user_fields = [
|
9
|
+
:email,
|
10
|
+
:name
|
11
|
+
]
|
12
|
+
config.user_repository = 'UserRepository'
|
13
|
+
end
|
data/test/dummy/config/routes.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
Rails.application.routes.draw do
|
2
|
+
mount RailsSso::Engine => '/sso', as: 'sso'
|
2
3
|
# The priority is based upon order of creation: first created -> highest priority.
|
3
4
|
# See how all your routes lay out with "rake routes".
|
4
5
|
|
@@ -53,4 +54,5 @@ Rails.application.routes.draw do
|
|
53
54
|
# # (app/controllers/admin/products_controller.rb)
|
54
55
|
# resources :products
|
55
56
|
# end
|
57
|
+
root to: 'application#index'
|
56
58
|
end
|
File without changes
|