omniauth_crowd 2.2.3 → 2.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.
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