gds-sso 0.1.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|