gds-sso 0.1.1 → 0.3.0
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.
- data/README.md +6 -0
- data/lib/gds-sso.rb +16 -12
- data/lib/gds-sso/api_access.rb +12 -0
- data/lib/gds-sso/config.rb +7 -0
- data/lib/gds-sso/failure_app.rb +5 -5
- data/lib/gds-sso/omniauth_strategy.rb +13 -1
- data/lib/gds-sso/version.rb +5 -0
- data/lib/gds-sso/warden_config.rb +63 -4
- data/test/test_omniauth_strategy.rb +10 -3
- metadata +88 -62
data/README.md
CHANGED
@@ -23,11 +23,17 @@ Create a `config/initializers/gds-sso.rb` that looks like:
|
|
23
23
|
|
24
24
|
GDS::SSO.config do |config|
|
25
25
|
config.user_model = 'User'
|
26
|
+
|
26
27
|
# set up ID and Secret in a way which doesn't require it to be checked in to source control...
|
27
28
|
config.oauth_id = ENV['OAUTH_ID']
|
28
29
|
config.oauth_secret = ENV['OAUTH_SECRET']
|
30
|
+
|
29
31
|
# optional config for location of sign-on-o-tron
|
30
32
|
config.oauth_root_url = "http://localhost:3001"
|
33
|
+
|
34
|
+
# optional config for API Access (requests which accept application/json)
|
35
|
+
config.basic_auth_user = 'api'
|
36
|
+
config.basic_auth_password = 'secret'
|
31
37
|
end
|
32
38
|
|
33
39
|
The user model needs to respond to klass.find_by_uid(uid), and must include the GDS::SSO::User module.
|
data/lib/gds-sso.rb
CHANGED
@@ -10,31 +10,35 @@ module GDS
|
|
10
10
|
autoload :FailureApp, 'gds-sso/failure_app'
|
11
11
|
autoload :ControllerMethods, 'gds-sso/controller_methods'
|
12
12
|
autoload :User, 'gds-sso/user'
|
13
|
+
autoload :ApiAccess, 'gds-sso/api_access'
|
14
|
+
|
15
|
+
# User to return as logged in during tests
|
16
|
+
mattr_accessor :test_user
|
13
17
|
|
14
18
|
def self.config
|
15
19
|
yield GDS::SSO::Config
|
16
20
|
end
|
17
21
|
|
18
|
-
def self.default_strategy
|
19
|
-
if ['development', 'test'].include?(Rails.env) && ENV['GDS_SSO_STRATEGY'] != 'real'
|
20
|
-
:mock_gds_sso
|
21
|
-
else
|
22
|
-
:gds_sso
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
22
|
class Engine < ::Rails::Engine
|
27
23
|
# Force routes to be loaded if we are doing any eager load.
|
28
24
|
# TODO - check this one - Stolen from Devise because it looked sensible...
|
29
25
|
config.before_eager_load { |app| app.reload_routes! }
|
30
|
-
|
26
|
+
|
31
27
|
config.app_middleware.use ::OmniAuth::Builder do
|
32
28
|
provider :gds, GDS::SSO::Config.oauth_id, GDS::SSO::Config.oauth_secret
|
33
29
|
end
|
34
30
|
|
35
|
-
|
36
|
-
|
37
|
-
|
31
|
+
def self.use_mock_strategies?
|
32
|
+
['development', 'test'].include?(Rails.env) && ENV['GDS_SSO_STRATEGY'] != 'real'
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.default_strategies
|
36
|
+
use_mock_strategies? ? [:mock_gds_sso, :mock_gds_sso_api_access] : [:gds_sso, :gds_sso_api_access]
|
37
|
+
end
|
38
|
+
|
39
|
+
config.app_middleware.use Warden::Manager do |config|
|
40
|
+
config.default_strategies *self.default_strategies
|
41
|
+
config.failure_app = GDS::SSO::FailureApp
|
38
42
|
end
|
39
43
|
end
|
40
44
|
end
|
data/lib/gds-sso/config.rb
CHANGED
@@ -15,6 +15,13 @@ module GDS
|
|
15
15
|
mattr_accessor :oauth_root_url
|
16
16
|
@@oauth_root_url = "http://localhost:3001"
|
17
17
|
|
18
|
+
# Basic Auth Credentials (for api access when request accept
|
19
|
+
# header is application/json)
|
20
|
+
mattr_accessor :basic_auth_user
|
21
|
+
mattr_accessor :basic_auth_password
|
22
|
+
mattr_accessor :basic_auth_realm
|
23
|
+
@@basic_auth_realm = "API Access"
|
24
|
+
|
18
25
|
def self.user_klass
|
19
26
|
user_model.to_s.constantize
|
20
27
|
end
|
data/lib/gds-sso/failure_app.rb
CHANGED
@@ -9,14 +9,13 @@ module GDS
|
|
9
9
|
include ActionController::RackDelegation
|
10
10
|
include ActionController::UrlFor
|
11
11
|
include ActionController::Redirecting
|
12
|
+
include ActionController::HttpAuthentication::Basic::ControllerMethods
|
12
13
|
include Rails.application.routes.url_helpers
|
13
14
|
|
14
15
|
def self.call(env)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
def respond
|
19
|
-
redirect
|
16
|
+
if ! ::GDS::SSO::ApiAccess.api_call?(env)
|
17
|
+
action(:redirect).call(env)
|
18
|
+
end
|
20
19
|
end
|
21
20
|
|
22
21
|
def redirect
|
@@ -33,6 +32,7 @@ module GDS
|
|
33
32
|
def store_location!
|
34
33
|
session["return_to"] = env['warden.options'][:attempted_path] if request.get?
|
35
34
|
end
|
35
|
+
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
@@ -8,6 +8,7 @@ require 'multi_json'
|
|
8
8
|
# use OmniAuth::Builder :gds, 'API Key', 'Secret Key'
|
9
9
|
|
10
10
|
class OmniAuth::Strategies::Gds < OmniAuth::Strategies::OAuth2
|
11
|
+
|
11
12
|
# @param [Rack Application] app standard middleware application parameter
|
12
13
|
# @param [String] api_key the application id as [provided by GDS]
|
13
14
|
# @param [String] secret_key the application secret as [provided by Bitly]
|
@@ -16,12 +17,23 @@ class OmniAuth::Strategies::Gds < OmniAuth::Strategies::OAuth2
|
|
16
17
|
:site => "#{GDS::SSO::Config.oauth_root_url}/",
|
17
18
|
:authorize_url => "#{GDS::SSO::Config.oauth_root_url}/oauth/authorize",
|
18
19
|
:token_url => "#{GDS::SSO::Config.oauth_root_url}/oauth/access_token",
|
19
|
-
:access_token_url => "#{GDS::SSO::Config.oauth_root_url}/oauth/access_token"
|
20
|
+
:access_token_url => "#{GDS::SSO::Config.oauth_root_url}/oauth/access_token",
|
21
|
+
:ssl => {
|
22
|
+
:verify => false
|
23
|
+
}
|
20
24
|
}
|
21
25
|
|
22
26
|
super(app, :gds, api_key, secret_key, client_options, options, &block)
|
23
27
|
end
|
24
28
|
|
29
|
+
def call(env)
|
30
|
+
if GDS::SSO::ApiAccess.api_call?(env)
|
31
|
+
@app.call(env)
|
32
|
+
else
|
33
|
+
super
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
25
37
|
protected
|
26
38
|
|
27
39
|
def fetch_user_data
|
@@ -2,7 +2,7 @@ require 'warden'
|
|
2
2
|
require 'omniauth/oauth'
|
3
3
|
|
4
4
|
Warden::Manager.serialize_into_session do |user|
|
5
|
-
user.uid
|
5
|
+
user.respond_to?(:uid) ? user.uid : nil
|
6
6
|
end
|
7
7
|
|
8
8
|
Warden::Manager.serialize_from_session do |uid|
|
@@ -11,10 +11,12 @@ end
|
|
11
11
|
|
12
12
|
Warden::Strategies.add(:gds_sso) do
|
13
13
|
def valid?
|
14
|
-
|
14
|
+
! ::GDS::SSO::ApiAccess.api_call?(env)
|
15
15
|
end
|
16
16
|
|
17
17
|
def authenticate!
|
18
|
+
Rails.logger.debug("Authenticating with gds_sso strategy")
|
19
|
+
|
18
20
|
if request.env['omniauth.auth'].nil?
|
19
21
|
fail!("No credentials, bub")
|
20
22
|
else
|
@@ -32,12 +34,69 @@ Warden::Strategies.add(:gds_sso) do
|
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
37
|
+
Warden::Strategies.add(:gds_sso_api_access) do
|
38
|
+
def valid?
|
39
|
+
::GDS::SSO::ApiAccess.api_call?(env)
|
40
|
+
end
|
41
|
+
|
42
|
+
def authenticate!
|
43
|
+
Rails.logger.debug("Authenticating with gds_sso_api_access strategy")
|
44
|
+
|
45
|
+
auth = Rack::Auth::Basic::Request.new(env)
|
46
|
+
|
47
|
+
return custom!(unauthorized) unless auth.provided?
|
48
|
+
return fail!(:bad_request) unless auth.basic?
|
49
|
+
|
50
|
+
if valid_api_user?(*auth.credentials)
|
51
|
+
success!(auth.credentials[0])
|
52
|
+
else
|
53
|
+
custom!(unauthorized)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def valid_api_user?(username, password)
|
58
|
+
username.to_s.strip != '' &&
|
59
|
+
password.to_s.strip != '' &&
|
60
|
+
username == ::GDS::SSO::Config.basic_auth_user &&
|
61
|
+
password == ::GDS::SSO::Config.basic_auth_password
|
62
|
+
end
|
63
|
+
|
64
|
+
def unauthorized
|
65
|
+
[
|
66
|
+
401,
|
67
|
+
{
|
68
|
+
'Content-Type' => 'text/plain',
|
69
|
+
'Content-Length' => '0',
|
70
|
+
'WWW-Authenticate' => %(Basic realm="#{GDS::SSO::Config.basic_auth_realm}")
|
71
|
+
},
|
72
|
+
[]
|
73
|
+
]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
35
77
|
Warden::Strategies.add(:mock_gds_sso) do
|
36
78
|
def valid?
|
37
|
-
|
79
|
+
! ::GDS::SSO::ApiAccess.api_call?(env)
|
80
|
+
end
|
81
|
+
|
82
|
+
def authenticate!
|
83
|
+
Rails.logger.debug("Authenticating with mock_gds_sso strategy")
|
84
|
+
test_user = GDS::SSO.test_user || GDS::SSO::Config.user_klass.first
|
85
|
+
if test_user
|
86
|
+
success!(test_user)
|
87
|
+
else
|
88
|
+
raise "GDS-SSO running in mock mode and no test user found. Normally we'd load the first user in the database. Create a user in the database."
|
89
|
+
end
|
38
90
|
end
|
91
|
+
end
|
39
92
|
|
93
|
+
Warden::Strategies.add(:mock_gds_sso_api_access) do
|
94
|
+
def valid?
|
95
|
+
::GDS::SSO::ApiAccess.api_call?(env)
|
96
|
+
end
|
97
|
+
|
40
98
|
def authenticate!
|
41
|
-
|
99
|
+
Rails.logger.debug("Authenticating with mock_gds_sso_api_access strategy")
|
100
|
+
success!(GDS::SSO.test_user || GDS::SSO::Config.user_klass.first)
|
42
101
|
end
|
43
102
|
end
|
@@ -5,17 +5,24 @@ require 'gds-sso/omniauth_strategy'
|
|
5
5
|
|
6
6
|
class TestOmniAuthStrategy < Test::Unit::TestCase
|
7
7
|
def setup
|
8
|
-
@
|
8
|
+
@app = stub("app")
|
9
|
+
@strategy = OmniAuth::Strategies::Gds.new(@app, :gds, 'client_id', 'client_secret')
|
9
10
|
@strategy.stubs(:fetch_user_data).returns({'user' => {'uid' => 'abcde', 'version' => 1, 'name' => 'Matt Patterson', 'email' => 'matt@alphagov.co.uk', 'github' => 'fidothe', 'twitter' => 'fidothe'}}.to_json)
|
10
11
|
end
|
11
12
|
|
12
|
-
def
|
13
|
+
def test_build_auth_hash_returns_name_and_email
|
13
14
|
assert_equal 'Matt Patterson', @strategy.send(:build_auth_hash)['user_info']['name']
|
14
15
|
assert_equal 'matt@alphagov.co.uk', @strategy.send(:build_auth_hash)['user_info']['email']
|
15
16
|
end
|
16
17
|
|
17
|
-
def
|
18
|
+
def test_build_auth_hash_contains_extra_info
|
18
19
|
expected = {'uid' => 'abcde', 'version' => 1, 'name' => 'Matt Patterson', 'email' => 'matt@alphagov.co.uk', 'github' => 'fidothe', 'twitter' => 'fidothe'}
|
19
20
|
assert_equal expected, @strategy.send(:build_auth_hash)['extra']['user_hash']
|
20
21
|
end
|
22
|
+
|
23
|
+
def test_oauth_bypassed_if_json_is_accepted_by_request
|
24
|
+
@app.expects(:call)
|
25
|
+
rack_env = { "HTTP_ACCEPT" => 'application/json' }
|
26
|
+
@strategy.call(rack_env)
|
27
|
+
end
|
21
28
|
end
|
metadata
CHANGED
@@ -1,108 +1,125 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: gds-sso
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.1
|
3
|
+
version: !ruby/object:Gem::Version
|
5
4
|
prerelease:
|
5
|
+
version: 0.3.0
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Matt Patterson
|
9
9
|
- James Stewart
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
|
14
|
+
date: 2012-01-10 00:00:00 Z
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
16
17
|
name: rails
|
17
|
-
requirement: &
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
18
19
|
none: false
|
19
|
-
requirements:
|
20
|
-
- -
|
21
|
-
- !ruby/object:Gem::Version
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
22
23
|
version: 3.0.0
|
23
24
|
type: :runtime
|
24
25
|
prerelease: false
|
25
|
-
version_requirements: *
|
26
|
-
- !ruby/object:Gem::Dependency
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
27
28
|
name: warden
|
28
|
-
requirement: &
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
29
30
|
none: false
|
30
|
-
requirements:
|
31
|
-
- -
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version:
|
31
|
+
requirements:
|
32
|
+
- - "="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 1.0.6
|
34
35
|
type: :runtime
|
35
36
|
prerelease: false
|
36
|
-
version_requirements: *
|
37
|
-
- !ruby/object:Gem::Dependency
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
38
39
|
name: oauth2
|
39
|
-
requirement: &
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
40
41
|
none: false
|
41
|
-
requirements:
|
42
|
-
- - =
|
43
|
-
- !ruby/object:Gem::Version
|
42
|
+
requirements:
|
43
|
+
- - "="
|
44
|
+
- !ruby/object:Gem::Version
|
44
45
|
version: 0.4.1
|
45
46
|
type: :runtime
|
46
47
|
prerelease: false
|
47
|
-
version_requirements: *
|
48
|
-
- !ruby/object:Gem::Dependency
|
48
|
+
version_requirements: *id003
|
49
|
+
- !ruby/object:Gem::Dependency
|
49
50
|
name: oa-oauth
|
50
|
-
requirement: &
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
51
52
|
none: false
|
52
|
-
requirements:
|
53
|
-
- - =
|
54
|
-
- !ruby/object:Gem::Version
|
53
|
+
requirements:
|
54
|
+
- - "="
|
55
|
+
- !ruby/object:Gem::Version
|
55
56
|
version: 0.2.6
|
56
57
|
type: :runtime
|
57
58
|
prerelease: false
|
58
|
-
version_requirements: *
|
59
|
-
- !ruby/object:Gem::Dependency
|
59
|
+
version_requirements: *id004
|
60
|
+
- !ruby/object:Gem::Dependency
|
60
61
|
name: oa-core
|
61
|
-
requirement: &
|
62
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
62
63
|
none: false
|
63
|
-
requirements:
|
64
|
-
- - =
|
65
|
-
- !ruby/object:Gem::Version
|
64
|
+
requirements:
|
65
|
+
- - "="
|
66
|
+
- !ruby/object:Gem::Version
|
66
67
|
version: 0.2.6
|
67
68
|
type: :runtime
|
68
69
|
prerelease: false
|
69
|
-
version_requirements: *
|
70
|
-
- !ruby/object:Gem::Dependency
|
70
|
+
version_requirements: *id005
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: rack-accept
|
73
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ~>
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: 0.4.4
|
79
|
+
type: :runtime
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: *id006
|
82
|
+
- !ruby/object:Gem::Dependency
|
71
83
|
name: rake
|
72
|
-
requirement: &
|
84
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
73
85
|
none: false
|
74
|
-
requirements:
|
86
|
+
requirements:
|
75
87
|
- - ~>
|
76
|
-
- !ruby/object:Gem::Version
|
88
|
+
- !ruby/object:Gem::Version
|
77
89
|
version: 0.9.2
|
78
90
|
type: :development
|
79
91
|
prerelease: false
|
80
|
-
version_requirements: *
|
81
|
-
- !ruby/object:Gem::Dependency
|
92
|
+
version_requirements: *id007
|
93
|
+
- !ruby/object:Gem::Dependency
|
82
94
|
name: mocha
|
83
|
-
requirement: &
|
95
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
84
96
|
none: false
|
85
|
-
requirements:
|
97
|
+
requirements:
|
86
98
|
- - ~>
|
87
|
-
- !ruby/object:Gem::Version
|
99
|
+
- !ruby/object:Gem::Version
|
88
100
|
version: 0.9.0
|
89
101
|
type: :development
|
90
102
|
prerelease: false
|
91
|
-
version_requirements: *
|
103
|
+
version_requirements: *id008
|
92
104
|
description: Client for GDS' OAuth 2-based SSO
|
93
|
-
email:
|
105
|
+
email:
|
94
106
|
- matt@constituentparts.com
|
95
107
|
- james.stewart@digital.cabinet-office.gov.uk
|
96
108
|
executables: []
|
109
|
+
|
97
110
|
extensions: []
|
111
|
+
|
98
112
|
extra_rdoc_files: []
|
99
|
-
|
113
|
+
|
114
|
+
files:
|
115
|
+
- lib/gds-sso/api_access.rb
|
100
116
|
- lib/gds-sso/config.rb
|
101
117
|
- lib/gds-sso/controller_methods.rb
|
102
118
|
- lib/gds-sso/failure_app.rb
|
103
119
|
- lib/gds-sso/omniauth_strategy.rb
|
104
120
|
- lib/gds-sso/routes.rb
|
105
121
|
- lib/gds-sso/user.rb
|
122
|
+
- lib/gds-sso/version.rb
|
106
123
|
- lib/gds-sso/warden_config.rb
|
107
124
|
- lib/gds-sso.rb
|
108
125
|
- README.md
|
@@ -113,29 +130,38 @@ files:
|
|
113
130
|
- test/test_user.rb
|
114
131
|
homepage: https://github.com/alphagov/gds-sso
|
115
132
|
licenses: []
|
133
|
+
|
116
134
|
post_install_message:
|
117
135
|
rdoc_options: []
|
118
|
-
|
136
|
+
|
137
|
+
require_paths:
|
119
138
|
- lib
|
120
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
139
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
121
140
|
none: false
|
122
|
-
requirements:
|
123
|
-
- -
|
124
|
-
- !ruby/object:Gem::Version
|
125
|
-
|
126
|
-
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
hash: -376516686123011262
|
145
|
+
segments:
|
146
|
+
- 0
|
147
|
+
version: "0"
|
148
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
149
|
none: false
|
128
|
-
requirements:
|
129
|
-
- -
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
hash: -376516686123011262
|
154
|
+
segments:
|
155
|
+
- 0
|
156
|
+
version: "0"
|
132
157
|
requirements: []
|
158
|
+
|
133
159
|
rubyforge_project: gds-sso
|
134
|
-
rubygems_version: 1.8.
|
160
|
+
rubygems_version: 1.8.13
|
135
161
|
signing_key:
|
136
162
|
specification_version: 3
|
137
163
|
summary: Client for GDS' OAuth 2-based SSO
|
138
|
-
test_files:
|
164
|
+
test_files:
|
139
165
|
- test/test_helper.rb
|
140
166
|
- test/test_omniauth_strategy.rb
|
141
167
|
- test/test_user.rb
|