omniauth_crowd 2.2.3 → 2.3.0

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: 59c97cc073c410612b365745b87b17e917845178
4
- data.tar.gz: e98defefdd3a85dcb46dbcf896cdb2e3e7fa3c75
3
+ metadata.gz: d6496c1f734a4cc164441c2cceb75039fa3751b2
4
+ data.tar.gz: 9d8e8b2cff8787f2d346dcb45f06486a1596d08d
5
5
  SHA512:
6
- metadata.gz: b2ea0383c88b06a00874e5053164c938f075b2df3ebd8b0ce0b50633d28653236d371616654d984e73c24cdc19eb4bca7626549fd2d2bd05803a8b0d6bc5fbe6
7
- data.tar.gz: 7e10ab76e6cf238e4b97e92cc9a10948eb2458ca56f9914f733a6271d7da3db1a30f4ed3e44545968c0bee3e1c5c3f945ee544dffe2b7baa7cb665d1bf30fabc
6
+ metadata.gz: 598ab5299d7381c0804b8afc81bd7227eea20d868ff2afd3dd38d4e9c518c6486706dc90a7d1b936c46c86e2d6bd6763fa2a7df0285bc6928564fb530a0e4cb2
7
+ data.tar.gz: 7f88dc8845d027da6983af8a3e05e3c544e5dea8075977eb376708917140298fbd3f30b26173f929877433057aaf1ca56cf8fdec588f933eea463c268f4e638d
data/.travis.yml CHANGED
@@ -1,6 +1,10 @@
1
1
  language: ruby
2
+ before_install:
3
+ - gem install bundler -v '~> 1.11'
2
4
  rvm:
3
5
  - "1.9.3"
4
6
  - "2.0.0"
5
7
  - "2.1.2"
8
+ - "2.2.4"
9
+ - "2.3.0"
6
10
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- omniauth_crowd (2.2.3)
4
+ omniauth_crowd (2.3.0)
5
5
  activesupport
6
6
  nokogiri (>= 1.4.4)
7
7
  omniauth (~> 1.0)
@@ -9,49 +9,51 @@ PATH
9
9
  GEM
10
10
  remote: http://rubygems.org/
11
11
  specs:
12
- activesupport (4.1.4)
13
- i18n (~> 0.6, >= 0.6.9)
12
+ activesupport (4.2.5.1)
13
+ i18n (~> 0.7)
14
14
  json (~> 1.7, >= 1.7.7)
15
15
  minitest (~> 5.1)
16
- thread_safe (~> 0.1)
16
+ thread_safe (~> 0.3, >= 0.3.4)
17
17
  tzinfo (~> 1.1)
18
- addressable (2.3.6)
19
- crack (0.4.2)
18
+ addressable (2.4.0)
19
+ crack (0.4.3)
20
20
  safe_yaml (~> 1.0.0)
21
21
  diff-lcs (1.2.5)
22
- hashie (3.2.0)
23
- i18n (0.6.11)
24
- json (1.8.1)
25
- mini_portile (0.6.0)
26
- minitest (5.4.0)
27
- nokogiri (1.6.3.1)
28
- mini_portile (= 0.6.0)
29
- omniauth (1.2.2)
22
+ hashdiff (0.3.0)
23
+ hashie (3.4.3)
24
+ i18n (0.7.0)
25
+ json (1.8.3)
26
+ mini_portile2 (2.0.0)
27
+ minitest (5.8.4)
28
+ nokogiri (1.6.7.2)
29
+ mini_portile2 (~> 2.0.0.rc2)
30
+ omniauth (1.3.1)
30
31
  hashie (>= 1.2, < 4)
31
- rack (~> 1.0)
32
- rack (1.5.2)
33
- rack-test (0.6.2)
32
+ rack (>= 1.0, < 3)
33
+ rack (1.6.4)
34
+ rack-test (0.6.3)
34
35
  rack (>= 1.0)
35
- rake (10.3.2)
36
+ rake (10.5.0)
36
37
  rspec (3.0.0)
37
38
  rspec-core (~> 3.0.0)
38
39
  rspec-expectations (~> 3.0.0)
39
40
  rspec-mocks (~> 3.0.0)
40
- rspec-core (3.0.3)
41
+ rspec-core (3.0.4)
41
42
  rspec-support (~> 3.0.0)
42
- rspec-expectations (3.0.3)
43
+ rspec-expectations (3.0.4)
43
44
  diff-lcs (>= 1.2.0, < 2.0)
44
45
  rspec-support (~> 3.0.0)
45
- rspec-mocks (3.0.3)
46
+ rspec-mocks (3.0.4)
46
47
  rspec-support (~> 3.0.0)
47
- rspec-support (3.0.3)
48
- safe_yaml (1.0.3)
49
- thread_safe (0.3.4)
48
+ rspec-support (3.0.4)
49
+ safe_yaml (1.0.4)
50
+ thread_safe (0.3.5)
50
51
  tzinfo (1.2.2)
51
52
  thread_safe (~> 0.1)
52
- webmock (1.18.0)
53
+ webmock (1.24.1)
53
54
  addressable (>= 2.3.6)
54
55
  crack (>= 0.3.2)
56
+ hashdiff
55
57
 
56
58
  PLATFORMS
57
59
  ruby
@@ -64,3 +66,6 @@ DEPENDENCIES
64
66
  rake
65
67
  rspec (~> 3.0.0)
66
68
  webmock
69
+
70
+ BUNDLED WITH
71
+ 1.11.2
@@ -18,7 +18,13 @@ module OmniAuth
18
18
 
19
19
  def request_phase
20
20
  if env['REQUEST_METHOD'] == 'GET'
21
- get_credentials
21
+
22
+ if @configuration.use_sso? && request.cookies[@configuration.session_cookie]
23
+ redirect callback_url
24
+ else
25
+ get_credentials
26
+ end
27
+
22
28
  elsif (env['REQUEST_METHOD'] == 'POST') && (not request.params['username'])
23
29
  get_credentials
24
30
  else
@@ -27,17 +33,52 @@ module OmniAuth
27
33
  end
28
34
  end
29
35
 
36
+ def get_client_ip
37
+ env['HTTP_X_FORWARDED_FOR'] ? env['HTTP_X_FORWARDED_FOR'] : env['REMOTE_ADDRESS']
38
+ end
39
+
40
+ def get_sso_tokens
41
+ env['HTTP_COOKIE'].split(';').select { |val|
42
+ val.strip.start_with?(@configuration.session_cookie)
43
+ }.map { |val|
44
+ val.strip.split('=').last
45
+ }
46
+ end
47
+
30
48
  def get_credentials
49
+
50
+ configuration = @configuration
51
+
31
52
  OmniAuth::Form.build(:title => (options[:title] || "Crowd Authentication")) do
32
53
  text_field 'Login', 'username'
33
54
  password_field 'Password', 'password'
55
+
56
+ if configuration.use_sso? && configuration.sso_url
57
+ fieldset 'SSO' do
58
+ html "<a href=\"#{configuration.sso_url}/users/auth/crowd/callback\">" + (configuration.sso_url_image ? "<img src=\"#{configuration.sso_url_image}\" />" : '') + "</a>"
59
+ end
60
+ end
61
+
34
62
  end.to_response
35
- end
36
63
 
64
+ end
65
+
37
66
  def callback_phase
67
+
38
68
  creds = session.delete 'omniauth.crowd'
39
- return fail!(:no_credentials) unless creds
40
- validator = CrowdValidator.new(@configuration, creds['username'], creds['password'])
69
+ username = creds.nil? ? nil : creds['username']
70
+ password = creds.nil? ? nil : creds['password']
71
+
72
+ unless creds
73
+ if @configuration.use_sso? && request.cookies[@configuration.session_cookie]
74
+ validator = CrowdValidator.new(@configuration, username, password, get_client_ip, get_sso_tokens)
75
+ else
76
+ return fail!(:no_credentials)
77
+ end
78
+ else
79
+ validator = CrowdValidator.new(@configuration, username, password, get_client_ip, nil)
80
+ end
81
+
41
82
  @user_info = validator.user_info
42
83
 
43
84
  return fail!(:invalid_credentials) if @user_info.nil? || @user_info.empty?
@@ -8,8 +8,9 @@ module OmniAuth
8
8
  DEFAULT_AUTHENTICATION_URL = "%s/rest/usermanagement/latest/authentication"
9
9
  DEFAULT_USER_GROUP_URL = "%s/rest/usermanagement/latest/user/group/direct"
10
10
  DEFAULT_CONTENT_TYPE = 'application/xml'
11
+ DEFAULT_SESSION_COOKIE = 'crowd.token_key'
11
12
 
12
- attr_reader :crowd_application_name, :crowd_password, :disable_ssl_verification, :include_users_groups, :use_sessions, :session_url, :content_type
13
+ attr_reader :crowd_application_name, :crowd_password, :disable_ssl_verification, :include_users_groups, :use_sessions, :session_url, :content_type, :session_cookie, :sso_url, :sso_url_image
13
14
 
14
15
  alias :"disable_ssl_verification?" :disable_ssl_verification
15
16
  alias :"include_users_groups?" :include_users_groups
@@ -29,6 +30,10 @@ module OmniAuth
29
30
  # @option params [String, nil] :crowd_user_group_url (:crowd_server_url + '/rest/usermanagement/latest/user/group/direct') the URL to which to
30
31
  # use for retrieving users groups optional if `:crowd_server_url` is specified, or if `:include_user_groups` is false
31
32
  # required otherwise.
33
+ # @option params [Boolean, false] :use_sessions Use Crowd sessions. If the user logins with user and password create a new Crowd session. Update the session if only a session token is sent (Cookie name set by option session_cookie)
34
+ # @option params [String, 'crowd.token_key'] :session_cookie Session cookie name. Defaults to: 'crowd.token_key'
35
+ # @option params [String, nil] :sso_url URL of the external SSO page. If this parameter is defined the login form will have a link which will redirect to the SSO page. The SSO must return to the URL of the page using omniauth_crowd (Path portion '/users/auth/crowd/callback' is appended to the URL)
36
+ # @option params [String, nil] :sso_url_image Optional image URL to be used in SSO link in the login form
32
37
  def initialize(params)
33
38
  parse_params params
34
39
  end
@@ -46,6 +51,10 @@ module OmniAuth
46
51
  @user_group_url.nil? ? nil : append_username( @user_group_url, username)
47
52
  end
48
53
 
54
+ def use_sso?()
55
+ @use_sessions && @sso_url ? true : false
56
+ end
57
+
49
58
  private
50
59
  def parse_params(options)
51
60
  options= {:include_user_groups => true}.merge(options || {})
@@ -56,6 +65,9 @@ module OmniAuth
56
65
  @crowd_password = options[:application_password]
57
66
  @use_sessions = options[:use_sessions]
58
67
  @content_type = options[:content_type] || DEFAULT_CONTENT_TYPE
68
+ @session_cookie = options[:session_cookie] || DEFAULT_SESSION_COOKIE
69
+ @sso_url = options[:sso_url]
70
+ @sso_url_image = options[:sso_url_image]
59
71
 
60
72
  unless options.include?(:crowd_server_url) || options.include?(:crowd_authentication_url)
61
73
  raise ArgumentError.new("Either :crowd_server_url or :crowd_authentication_url MUST be provided")
@@ -6,22 +6,16 @@ module OmniAuth
6
6
  module Strategies
7
7
  class Crowd
8
8
  class CrowdValidator
9
- SESSION_REQUEST_BODY = <<-BODY.strip
10
- <authentication-context>
11
- <username>%s</username>
12
- <password>%s</password>
13
- </authentication-context>
14
- BODY
15
9
  AUTHENTICATION_REQUEST_BODY = "<password><value>%s</value></password>"
16
- def initialize(configuration, username, password)
17
- @configuration, @username, @password = configuration, username, password
10
+ def initialize(configuration, username, password, client_ip, tokens)
11
+ @configuration, @username, @password, @client_ip, @tokens = configuration, username, password, client_ip, tokens
18
12
  @authentiction_uri = URI.parse(@configuration.authentication_url(@username))
19
13
  @session_uri = URI.parse(@configuration.session_url) if @configuration.use_sessions
20
- @user_group_uri = @configuration.include_users_groups? ? URI.parse(@configuration.user_group_url(@username)) : nil
21
14
  end
22
15
 
23
16
  def user_info
24
17
  user_info_hash = retrieve_user_info!
18
+
25
19
  if user_info_hash && @configuration.include_users_groups?
26
20
  user_info_hash = add_user_groups!(user_info_hash)
27
21
  else
@@ -29,27 +23,36 @@ BODY
29
23
  end
30
24
 
31
25
  if user_info_hash && @configuration.use_sessions?
32
- user_info_hash = add_session!(user_info_hash)
26
+ user_info_hash = set_session!(user_info_hash)
33
27
  end
34
28
 
35
29
  user_info_hash
36
30
  end
37
31
 
38
32
  private
39
- def add_session!(user_info_hash)
40
- response = make_session_request
33
+ def set_session!(user_info_hash)
34
+
35
+ response = nil
36
+
37
+ if user_info_hash["sso_token"]
38
+ response = make_session_request(user_info_hash["sso_token"])
39
+ else
40
+ response = make_session_request(nil)
41
+ end
42
+
41
43
  if response.kind_of?(Net::HTTPSuccess) && response.body
42
44
  doc = Nokogiri::XML(response.body)
43
45
  user_info_hash["sso_token"] = doc.xpath('//token/text()').to_s
44
46
  else
45
- OmniAuth.logger.send(:warn, "(crowd) [add_session!] response code: #{response.code.to_s}")
46
- OmniAuth.logger.send(:warn, "(crowd) [add_session!] response body: #{response.body}")
47
+ OmniAuth.logger.send(:warn, "(crowd) [set_session!] response code: #{response.code.to_s}")
48
+ OmniAuth.logger.send(:warn, "(crowd) [set_session!] response body: #{response.body}")
47
49
  end
50
+
48
51
  user_info_hash
49
52
  end
50
53
 
51
54
  def add_user_groups!(user_info_hash)
52
- response = make_user_group_request
55
+ response = make_user_group_request(user_info_hash['user'])
53
56
  unless response.code.to_i != 200 || response.body.nil? || response.body == ''
54
57
  doc = Nokogiri::XML(response.body)
55
58
  user_info_hash["groups"] = doc.xpath("//groups/group/@name").map(&:to_s)
@@ -59,18 +62,32 @@ BODY
59
62
 
60
63
  def retrieve_user_info!
61
64
  response = make_authorization_request
62
- unless response.code.to_i != 200 || response.body.nil? || response.body == ''
63
- doc = Nokogiri::XML(response.body)
64
- {
65
- "user" => doc.xpath("//user/@name").to_s,
66
- "name" => doc.xpath("//user/display-name/text()").to_s,
67
- "first_name" => doc.xpath("//user/first-name/text()").to_s,
68
- "last_name" => doc.xpath("//user/last-name/text()").to_s,
69
- "email" => doc.xpath("//user/email/text()").to_s
70
- }
65
+
66
+ unless response === nil
67
+ unless response.code.to_i != 200 || response.body.nil? || response.body == ''
68
+
69
+ doc = Nokogiri::XML(response.body)
70
+ result = {
71
+ "user" => doc.xpath("//user/@name").to_s,
72
+ "name" => doc.xpath("//user/display-name/text()").to_s,
73
+ "first_name" => doc.xpath("//user/first-name/text()").to_s,
74
+ "last_name" => doc.xpath("//user/last-name/text()").to_s,
75
+ "email" => doc.xpath("//user/email/text()").to_s
76
+ }
77
+
78
+ if doc.at_xpath("//token")
79
+ result["sso_token"] = doc.xpath("//token/text()").to_s
80
+ end
81
+
82
+ result
83
+
84
+ else
85
+ OmniAuth.logger.send(:warn, "(crowd) [retrieve_user_info!] response code: #{response.code.to_s}")
86
+ OmniAuth.logger.send(:warn, "(crowd) [retrieve_user_info!] response body: #{response.body}")
87
+ nil
88
+ end
71
89
  else
72
- OmniAuth.logger.send(:warn, "(crowd) [retrieve_user_info!] response code: #{response.code.to_s}")
73
- OmniAuth.logger.send(:warn, "(crowd) [retrieve_user_info!] response body: #{response.body}")
90
+ OmniAuth.logger.send(:warn, "(crowd) [retrieve_user_info!] None of the session tokens were valid")
74
91
  nil
75
92
  end
76
93
  end
@@ -91,18 +108,58 @@ BODY
91
108
  end
92
109
  end
93
110
 
94
- def make_user_group_request
95
- make_request(@user_group_uri)
111
+ def make_user_group_request(username)
112
+ make_request(URI.parse(@configuration.user_group_url(username)))
96
113
  end
97
114
 
98
115
  def make_authorization_request
99
- make_request(@authentiction_uri, make_authentication_request_body(@password))
100
- end
101
116
 
102
- def make_session_request
103
- make_request(@session_uri, make_session_request_body(@username, @password))
117
+ if @configuration.use_sessions? && @tokens.kind_of?(Array)
118
+ make_session_retrieval_request
119
+ else
120
+ make_request(@authentiction_uri, make_authentication_request_body(@password))
121
+ end
104
122
  end
105
123
 
124
+ def make_session_request(token)
125
+
126
+ root = url = validation_factor = nil
127
+ doc = Nokogiri::XML::Document.new
128
+
129
+ if token === nil
130
+
131
+ url = @session_uri
132
+ root = doc.create_element('authentication-context')
133
+
134
+ doc.root = root
135
+ root.add_child(doc.create_element('username', @username))
136
+ root.add_child(doc.create_element('password', @password))
137
+
138
+ else
139
+ url = URI.parse(@session_uri.to_s() + "/#{token}")
140
+ end
141
+
142
+ if @configuration.use_sessions? || @client_ip
143
+
144
+ if root === nil
145
+ root = doc.create_element('validation-factors')
146
+ doc.root = root
147
+ else
148
+ root.add_child(doc.create_element('validation-factors'))
149
+ end
150
+
151
+ validation_factor = doc.create_element('validation-factor')
152
+ validation_factor.add_child(doc.create_element('name', 'remote_address'))
153
+ validation_factor.add_child(doc.create_element('value', @client_ip))
154
+
155
+ doc.xpath('//validation-factors').first.add_child(validation_factor)
156
+
157
+ end
158
+
159
+ make_request(url, doc.to_s)
160
+
161
+ end
162
+
106
163
  # create the body using Nokogiri so proper encoding of passwords can be ensured
107
164
  def make_authentication_request_body(password)
108
165
  request_body = Nokogiri::XML(AUTHENTICATION_REQUEST_BODY)
@@ -111,11 +168,17 @@ BODY
111
168
  return request_body.root.to_s # return the body without the xml header
112
169
  end
113
170
 
114
- def make_session_request_body(username,password)
115
- request_body = Nokogiri::XML(SESSION_REQUEST_BODY)
116
- request_body.at_css("username").content = username
117
- request_body.at_css("password").content = password
118
- return request_body.root.to_s
171
+ def make_session_retrieval_request
172
+
173
+ response = nil
174
+
175
+ @tokens.any? { |token|
176
+ response = make_request(URI.parse(@session_uri.to_s() + "/#{token}"))
177
+ response.code.to_i == 200 && !response.body.nil? && response.body != ''
178
+ }
179
+
180
+ response
181
+
119
182
  end
120
183
  end
121
184
  end
@@ -1,5 +1,5 @@
1
1
  module OmniAuth
2
2
  module Crowd
3
- VERSION = "2.2.3"
3
+ VERSION = "2.3.0"
4
4
  end
5
5
  end
@@ -9,12 +9,17 @@ describe OmniAuth::Strategies::Crowd, :type=>:strategy do
9
9
  [OmniAuth::Strategies::Crowd, {:crowd_server_url => @crowd_server_url,
10
10
  :application_name => @application_name,
11
11
  :application_password => @application_password,
12
- :use_sessions => @using_sessions}]
12
+ :use_sessions => @using_sessions,
13
+ :sso_url => @sso_url,
14
+ :sso_url_image => @sso_url_image
15
+ }]
13
16
  end
14
17
 
15
18
  @using_sessions = false
19
+ @sso_url = nil
20
+ @sso_url_image = nil
16
21
  let(:config) { OmniAuth::Strategies::Crowd::Configuration.new(strategy[1]) }
17
- let(:validator) { OmniAuth::Strategies::Crowd::CrowdValidator.new(config, 'foo', 'bar') }
22
+ let(:validator) { OmniAuth::Strategies::Crowd::CrowdValidator.new(config, 'foo', 'bar', nil, nil) }
18
23
 
19
24
  describe 'Authentication Request Body' do
20
25
 
@@ -37,28 +42,6 @@ BODY
37
42
  end
38
43
  end
39
44
 
40
- describe 'Session Request Body' do
41
- it 'should send username and password in session request' do
42
- body = <<-BODY.strip
43
- <authentication-context>
44
- <username>foo</username>
45
- <password>bar</password>
46
- </authentication-context>
47
- BODY
48
- expect(validator.send(:make_session_request_body, 'foo', 'bar')).to eq(body)
49
- end
50
-
51
- it 'should escape special characters username and password in session request' do
52
- body = <<-BODY.strip
53
- <authentication-context>
54
- <username>foo</username>
55
- <password>bar&lt;</password>
56
- </authentication-context>
57
- BODY
58
- expect(validator.send(:make_session_request_body, 'foo', 'bar<')).to eq(body)
59
- end
60
- end
61
-
62
45
  describe 'GET /auth/crowd' do
63
46
  it 'should show the login form' do
64
47
  get '/auth/crowd'
@@ -150,7 +133,7 @@ BODY
150
133
  describe 'GET /auth/crowd/callback with credentials will fail' do
151
134
  before do
152
135
  stub_request(:post, "https://bogus_app:bogus_app_password@crowd.example.org/rest/usermanagement/latest/authentication?username=foo").
153
- to_return(:code=>400)
136
+ to_return(:status=>400)
154
137
  get '/auth/crowd/callback', nil, 'rack.session'=>{'omniauth.crowd'=> {"username"=>"foo", "password"=>"ba"}}
155
138
  end
156
139
  it 'should fail' do
@@ -158,4 +141,247 @@ BODY
158
141
  expect(last_response.headers['Location']).to match(/invalid_credentials/)
159
142
  end
160
143
  end
144
+
145
+ describe 'GET /auth/crowd without credentials will redirect to login form' do
146
+
147
+ sso_url = 'https://foo.bar'
148
+
149
+ before do
150
+ @using_sessions = true
151
+ @sso_url = sso_url
152
+ end
153
+
154
+ it 'should have the SSO button in the response body' do
155
+
156
+ found_legend = found_anchor = nil
157
+
158
+ get '/auth/crowd'
159
+
160
+ Nokogiri::HTML(last_response.body).xpath('//html/body/form/fieldset/*').each do |element|
161
+
162
+ if element.name === 'legend' && element.content() === 'SSO'
163
+ found_legend = true
164
+ elsif element.name === 'a' && element.attr('href') === "#{sso_url}/users/auth/crowd/callback"
165
+ found_anchor = true
166
+ end
167
+ end
168
+
169
+ expect(found_legend).to(be(true))
170
+ expect(found_anchor).to(be(true))
171
+
172
+ end
173
+
174
+ after do
175
+ @using_sessions = false
176
+ @sso_url = nil
177
+ end
178
+
179
+ end
180
+
181
+ describe 'GET /auth/crowd without credentials will redirect to login form which has custom image in the SSO link' do
182
+
183
+ sso_url = 'https://foo.bar'
184
+ sso_url_image = 'https://foo.bar/image.png'
185
+
186
+ before do
187
+ @using_sessions = true
188
+ @sso_url = sso_url
189
+ @sso_url_image = 'https://foo.bar/image.png'
190
+ end
191
+
192
+ it 'should have the SSO button with a custom image in the response body' do
193
+
194
+ found_legend = found_anchor = found_image = false
195
+
196
+ get '/auth/crowd'
197
+
198
+ Nokogiri::HTML(last_response.body).xpath('//html/body/form/fieldset/*').each do |element|
199
+
200
+ if element.name === 'legend' && element.content() === 'SSO'
201
+ found_legend = true
202
+ elsif element.name === 'a' && element.attr('href') === "#{sso_url}/users/auth/crowd/callback"
203
+
204
+ found_anchor = true
205
+
206
+ if element.children.length === 1 && element.children.first.name === 'img' && element.children.first.attr('src') === sso_url_image
207
+ found_image = true
208
+ end
209
+
210
+ end
211
+ end
212
+
213
+ expect(found_legend).to(be(true))
214
+ expect(found_anchor).to(be(true))
215
+ expect(found_image).to(be(true))
216
+
217
+ end
218
+
219
+ after do
220
+ @using_sessions = false
221
+ @sso_url = nil
222
+ @sso_url_image = nil
223
+ end
224
+
225
+ end
226
+
227
+ describe 'GET /auth/crowd without credentials but with SSO cookie will redirect to callback' do
228
+
229
+ sso_url = 'https://foo.bar'
230
+
231
+ before do
232
+
233
+ @using_sessions = true
234
+ @sso_url = sso_url
235
+
236
+ set_cookie('crowd.token_key=foobar')
237
+
238
+ end
239
+
240
+ it 'should redirect to callback' do
241
+ get '/auth/crowd'
242
+ expect(last_response).to be_redirect
243
+ expect(last_response.headers['Location']).to eq('http://example.org/auth/crowd/callback')
244
+ end
245
+
246
+ after do
247
+
248
+ @using_sessions = false
249
+ @sso_url = nil
250
+
251
+ clear_cookies()
252
+
253
+ end
254
+
255
+ end
256
+
257
+ describe 'POST /auth/crowd/callback without credentials but with SSO cookie will redirect to login form because session is invalid' do
258
+
259
+ sso_url = 'https://foo.bar'
260
+ token = 'foobar'
261
+
262
+ before do
263
+
264
+ @using_sessions = true
265
+ @sso_url = sso_url
266
+
267
+ stub_request(:get, "https://bogus_app:bogus_app_password@crowd.example.org/rest/usermanagement/latest/session/#{token}").
268
+ to_return(:status => [404])
269
+
270
+ set_cookie("crowd.token_key=#{token}")
271
+
272
+ end
273
+
274
+ it 'should redirect to login form' do
275
+ post '/auth/crowd/callback'
276
+ expect(last_response).to be_redirect
277
+ expect(last_response.headers['Location']).to match(/invalid_credentials/)
278
+ end
279
+
280
+ after do
281
+
282
+ @using_sessions = false
283
+ @sso_url = nil
284
+
285
+ clear_cookies()
286
+
287
+ end
288
+
289
+ end
290
+
291
+ describe 'GET /auth/crowd/callback without credentials but with SSO cookie will succeed' do
292
+
293
+ sso_url = 'https://foo.bar'
294
+ token = 'rtk8eMvqq00EiGn5iJCMZQ00'
295
+
296
+ before do
297
+
298
+ @using_sessions = true
299
+ @sso_url = sso_url
300
+
301
+ stub_request(:get, "https://bogus_app:bogus_app_password@crowd.example.org/rest/usermanagement/latest/session/#{token}").
302
+ to_return(:status => 200, :body => File.read(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'session.xml')))
303
+ stub_request(:post, "https://bogus_app:bogus_app_password@crowd.example.org/rest/usermanagement/latest/session/#{token}").
304
+ to_return(:status => 200)
305
+ stub_request(:get, "https://bogus_app:bogus_app_password@crowd.example.org/rest/usermanagement/latest/user/group/direct?username=foo").
306
+ to_return(:body => File.read(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'groups.xml')))
307
+
308
+ set_cookie("crowd.token_key=#{token}")
309
+
310
+ end
311
+
312
+ it 'should return user data' do
313
+
314
+ auth = nil
315
+
316
+ get '/auth/crowd/callback'
317
+
318
+ auth = last_request.env['omniauth.auth']
319
+
320
+ expect(auth['provider']).to eq(:crowd)
321
+ expect(auth['uid']).to eq('foo')
322
+ expect(auth['info']).to be_kind_of(Hash)
323
+ expect(auth['info']['groups'].sort).to eq(["Developers", "jira-users"].sort)
324
+
325
+ end
326
+
327
+ after do
328
+
329
+ @using_sessions = false
330
+ @sso_url = nil
331
+
332
+ clear_cookies()
333
+
334
+ end
335
+
336
+ end
337
+
338
+ describe 'GET /auth/crowd/callback without credentials but with multiple SSO cookies will succeed because one of them is valid' do
339
+
340
+ sso_url = 'https://foo.bar'
341
+
342
+ before do
343
+
344
+ @using_sessions = true
345
+ @sso_url = sso_url
346
+
347
+ stub_request(:get, "https://bogus_app:bogus_app_password@crowd.example.org/rest/usermanagement/latest/session/foo").
348
+ to_return(:status => 404)
349
+ stub_request(:get, "https://bogus_app:bogus_app_password@crowd.example.org/rest/usermanagement/latest/session/fubar").
350
+ to_return(:status => 404)
351
+ stub_request(:get, "https://bogus_app:bogus_app_password@crowd.example.org/rest/usermanagement/latest/session/rtk8eMvqq00EiGn5iJCMZQ00").
352
+ to_return(:status => 200, :body => File.read(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'session.xml')))
353
+ stub_request(:post, "https://bogus_app:bogus_app_password@crowd.example.org/rest/usermanagement/latest/session/rtk8eMvqq00EiGn5iJCMZQ00").
354
+ to_return(:status => 200)
355
+ stub_request(:get, "https://bogus_app:bogus_app_password@crowd.example.org/rest/usermanagement/latest/user/group/direct?username=foo").
356
+ to_return(:body => File.read(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'groups.xml')))
357
+
358
+ header('Cookie', "crowd.token_key=foo;crowd.token_key=rtk8eMvqq00EiGn5iJCMZQ00;crowd.token_key=fubar")
359
+
360
+ end
361
+
362
+ it 'should return user data' do
363
+
364
+ auth = nil
365
+
366
+ get '/auth/crowd/callback'
367
+
368
+ auth = last_request.env['omniauth.auth']
369
+
370
+ expect(auth['provider']).to eq(:crowd)
371
+ expect(auth['uid']).to eq('foo')
372
+ expect(auth['info']).to be_kind_of(Hash)
373
+ expect(auth['info']['groups'].sort).to eq(["Developers", "jira-users"].sort)
374
+
375
+ end
376
+
377
+ after do
378
+
379
+ @using_sessions = false
380
+ @sso_url = nil
381
+
382
+ header('Cookie', nil)
383
+
384
+ end
385
+
386
+ end
161
387
  end
data/spec/spec_helper.rb CHANGED
@@ -3,6 +3,7 @@ Bundler.setup
3
3
  require 'rack/test'
4
4
  require 'webmock'
5
5
  require 'webmock/rspec'
6
+ require 'nokogiri'
6
7
 
7
8
  require 'omniauth_crowd'
8
9
  RSpec.configure do |config|
metadata CHANGED
@@ -1,139 +1,139 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniauth_crowd
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.3
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Di Marco
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-28 00:00:00.000000000 Z
11
+ date: 2016-03-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: omniauth
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: nokogiri
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: 1.4.4
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: 1.4.4
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: activesupport
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rack
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rack-test
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rspec
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - ~>
101
+ - - "~>"
102
102
  - !ruby/object:Gem::Version
103
103
  version: 3.0.0
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ~>
108
+ - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: 3.0.0
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: webmock
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - '>='
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
117
  version: '0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - '>='
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: bundler
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - '>'
129
+ - - ">"
130
130
  - !ruby/object:Gem::Version
131
131
  version: 1.0.0
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - '>'
136
+ - - ">"
137
137
  - !ruby/object:Gem::Version
138
138
  version: 1.0.0
139
139
  description: This is an OmniAuth provider for Atlassian Crowd's REST API. It allows
@@ -144,9 +144,9 @@ executables: []
144
144
  extensions: []
145
145
  extra_rdoc_files: []
146
146
  files:
147
- - .document
148
- - .gitignore
149
- - .travis.yml
147
+ - ".document"
148
+ - ".gitignore"
149
+ - ".travis.yml"
150
150
  - Gemfile
151
151
  - Gemfile.lock
152
152
  - LICENSE.txt
@@ -172,17 +172,17 @@ require_paths:
172
172
  - lib
173
173
  required_ruby_version: !ruby/object:Gem::Requirement
174
174
  requirements:
175
- - - '>='
175
+ - - ">="
176
176
  - !ruby/object:Gem::Version
177
177
  version: '0'
178
178
  required_rubygems_version: !ruby/object:Gem::Requirement
179
179
  requirements:
180
- - - '>='
180
+ - - ">="
181
181
  - !ruby/object:Gem::Version
182
182
  version: '0'
183
183
  requirements: []
184
184
  rubyforge_project:
185
- rubygems_version: 2.2.2
185
+ rubygems_version: 2.4.5.1
186
186
  signing_key:
187
187
  specification_version: 4
188
188
  summary: An OmniAuth provider for Atlassian Crowd REST API