omniauth_openid_connect 0.3.3 → 0.3.4

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
  SHA256:
3
- metadata.gz: 1782deb4f35b91b78092d0d12a274e5a2cf8e072a287f38446a33f675c5a9fa3
4
- data.tar.gz: fbcd06a634f452db1b5172f5ef0fd06fe154aab1b4305271c37d6f066349165a
3
+ metadata.gz: 0ffa620976c79075bcc1be6d53c4e4cd6f44cecb4c387902c07d2eeb633289aa
4
+ data.tar.gz: 910ddf1c62c01806349f1079f20f2bb51b96cf95a74e98d584335a16dd7af6f6
5
5
  SHA512:
6
- metadata.gz: 367cfbd61e617f8f8f6cae9a6b4f6ee0b6c225bc551d60b1815964eefd63d3088dcbcbf6202bf44f82ae21fc7ae1ec7e303f8d9dd39946556b77c6bfafee9d00
7
- data.tar.gz: 322d7f6656131e37c4edc0850d8917c3a1fdc0ed5a3cc2065c0a3ac61228849a0fe892e917df2dbc5f379f8a04ba08366b24d595e7f4a0d0e345d5cab7d8f786
6
+ metadata.gz: a4268d78d21672332b24a63aea04b43a0f8c531c8a9e89f9187402406bbb4e5538b576cb60fcacecebf9b57e91c14b9f31136eee3aa7c6aeda7571130ad77b9b
7
+ data.tar.gz: 858664147722cb80f5adf5b632ccde44ebfd79e29f0058be65a6bfe4847494cacec5255b96e646b3a18e2533489dc9a09fe31995e3aec0eebe9facbcbb37f69a
@@ -0,0 +1,59 @@
1
+ # Description: The name of the check that will be created.
2
+ # Valid Options: A reasonably sized string.
3
+ # Default: 'Rubocop Action'
4
+ check_name: 'Rubocop Results'
5
+
6
+ # Description: Versions required to run your RuboCop checks.
7
+ # Valid options: RuboCop and any RuboCop extension, by default the latest gem version will be used. You can explicitly state that
8
+ # (not required) or use a version number, like '1.5.1'.
9
+ # Default:
10
+ # versions:
11
+ # - rubocop: 'latest'
12
+ versions:
13
+ - rubocop
14
+ - rubocop-minitest
15
+ - rubocop-performance: '1.5.1'
16
+
17
+ # Description: Rubocop configuration file path relative to the workspace.
18
+ # Valid options: A valid file path inside of the workspace.
19
+ # Default: nil
20
+ # Note: This does not need to be filled out for Rubocop to still find your config.
21
+ # Resource: https://rubocop.readthedocs.io/en/stable/configuration/
22
+ rubocop_config_path: '.rubocop.yml'
23
+
24
+ # Run all cops enabled by configuration except this list.
25
+ # Valid options: list of valid cop(s) and/or departments.
26
+ # Default: nil
27
+ # Resource: https://rubocop.readthedocs.io/en/stable/cops/
28
+ # rubocop_excluded_cops:
29
+ # - 'Style/FrozenStringLiteralComment'
30
+
31
+ # Minimum severity for exit with error code
32
+ # Valid options: 'refactor', 'convention', 'warning', 'error', or 'fatal'.
33
+ # Default: 'warning'
34
+ # Resource: https://rubocop.readthedocs.io/en/stable/configuration/#severity
35
+ # rubocop_fail_level: 'warning'
36
+
37
+ # Whether or not to use --force-exclusion when building the rubocop command. Use this if you are only linting modified
38
+ # files and typically excluded files have been changed. For example, if you exclude db/schema.rb in your rubocop.yml
39
+ # but a change gets made, then with the check_scope config set to 'modified' rubocop will lint db/schema.rb. If you set
40
+ # this to true, rubocop will ignore it.
41
+ # Valid options: true || false
42
+ # Default: false
43
+
44
+ # Instead of installing gems from rubygems, we can run `bundle install` on your project,
45
+ # you would need to do this if you are using something like 'rubocop-github' or if you don't
46
+ # want to list out dependencies with the `versions` key.
47
+ # Valid options: true || false
48
+ # Default: false
49
+ # bundle: false
50
+
51
+ # The scope of code that Rubocop should lint. Use this if you only want to lint changed files. If this is not set
52
+ # or not equal to 'modified', Rubocop is run against the entire codebase. Note that this will not work on the master branch.
53
+ # Valid options: 'modified'
54
+ # Default: nil
55
+
56
+ # The base branch against which changes will be compared, if check_scope config is set to 'modified'.
57
+ # This setting is not used if check_scope != 'modified'.
58
+ # Valid options: 'origin/another_branch'
59
+ # Default: 'origin/master'
data/.github/stale.yml ADDED
@@ -0,0 +1,17 @@
1
+ # Number of days of inactivity before an issue becomes stale
2
+ daysUntilStale: 60
3
+ # Number of days of inactivity before a stale issue is closed
4
+ daysUntilClose: 7
5
+ # Issues with these labels will never be considered stale
6
+ exemptLabels:
7
+ - pinned
8
+ - security
9
+ # Label to use when marking an issue as stale
10
+ staleLabel: wontfix
11
+ # Comment to post when marking an issue as stale. Set to `false` to disable
12
+ markComment: >
13
+ This issue has been automatically marked as stale because it has not had
14
+ recent activity. It will be closed if no further activity occurs. Thank you
15
+ for your contributions.
16
+ # Comment to post when closing a stale issue. Set to `false` to disable
17
+ closeComment: false
@@ -0,0 +1,22 @@
1
+ name: Rubocop check
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - "*"
7
+ push:
8
+ branches:
9
+ - master
10
+ jobs:
11
+ build:
12
+ name: RuboCop Action
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - name: Checkout Action
16
+ uses: actions/checkout@v1
17
+ - name: Rubocop Linter Action
18
+ uses: andrewmcodes/rubocop-linter-action@v3.2.0
19
+ with:
20
+ action_config_path: '.github/config/rubocop_linter_action.yml'
21
+ env:
22
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
data/.travis.yml CHANGED
@@ -3,3 +3,6 @@ rvm:
3
3
  - 2.4
4
4
  - 2.5
5
5
  - 2.6
6
+ - 2.7
7
+ - jruby-head
8
+ - ruby-head
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ # v0.3.4 (21.05.2020)
2
+
3
+ - Try to verify id_token when response_type is code [#44](https://github.com/m0n9oose/omniauth_openid_connect/pull/44)
4
+ - Provide more information on error [#49](https://github.com/m0n9oose/omniauth_openid_connect/pull/49)
5
+ - Update configuration documentation [#53](https://github.com/m0n9oose/omniauth_openid_connect/pull/53)
6
+ - Add documentation about the send_scope_to_token_endpoint config property [#52](https://github.com/m0n9oose/omniauth_openid_connect/pull/52)
7
+ - refactor: take uid_field from raw_attributes [#54](https://github.com/m0n9oose/omniauth_openid_connect/pull/54)
8
+ - chore(ci): add 2.7, ruby-head and jruby-head [#55](https://github.com/m0n9oose/omniauth_openid_connect/pull/55)
9
+
1
10
  # v0.3.3 (09.11.2019)
2
11
 
3
12
  - Pass `acr_values` to authorize url [#43](https://github.com/m0n9oose/omniauth_openid_connect/pull/43)
data/README.md CHANGED
@@ -19,6 +19,10 @@ And then execute:
19
19
  Or install it yourself as:
20
20
 
21
21
  $ gem install omniauth_openid_connect
22
+
23
+ ## Supported Ruby Versions
24
+
25
+ OmniAuth::OpenIDConnect is tested under 2.4, 2.5, 2.6, 2.7
22
26
 
23
27
  ## Usage
24
28
 
@@ -40,7 +44,44 @@ config.omniauth :openid_connect, {
40
44
  }
41
45
  ```
42
46
 
43
- Configuration details:
47
+ ### Options Overview
48
+
49
+ | Field | Description | Required | Default | Example/Options |
50
+ |------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|----------------------------|-----------------------------------------------------|
51
+ | name | Arbitrary string to identify connection and identify it from other openid_connect providers | no | String: openid_connect | :my_idp |
52
+ | issuer | Root url for the authorization server | yes | | https://myprovider.com |
53
+ | discovery | Should OpenID discovery be used. This is recommended if the IDP provides a discovery endpoint. See client config for how to manually enter discovered values. | no | false | one of: true, false |
54
+ | client_auth_method | Which authentication method to use to authenticate your app with the authorization server | no | Sym: basic | "basic", "jwks" |
55
+ | scope | Which OpenID scopes to include (:openid is always required) | no | Array<sym> [:openid] | [:openid, :profile, :email] |
56
+ | response_type | Which OAuth2 response type to use with the authorization request | no | String: code | one of: 'code', 'id_token' |
57
+ | state | A value to be used for the OAuth2 state parameter on the authorization request. Can be a proc that generates a string. | no | Random 16 character string | Proc.new { SecureRandom.hex(32) } |
58
+ | response_mode | The response mode per [spec](https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html) | no | nil | one of: :query, :fragment, :form_post, :web_message |
59
+ | display | An optional parameter to the authorization request to determine how the authorization and consent page | no | nil | one of: :page, :popup, :touch, :wap |
60
+ | prompt | An optional parameter to the authrization request to determine what pages the user will be shown | no | nil | one of: :none, :login, :consent, :select_account |
61
+ | send_scope_to_token_endpoint | Should the scope parameter be sent to the authorization token endpoint? | no | true | one of: true, false |
62
+ | post_logout_redirect_uri | The logout redirect uri to use per the [session management draft](https://openid.net/specs/openid-connect-session-1_0.html) | no | empty | https://myapp.com/logout/callback |
63
+ | uid_field | The field of the user info response to be used as a unique id | no | 'sub' | "sub", "preferred_username" |
64
+ | client_options | A hash of client options detailed in its own section | yes | | |
65
+
66
+ ### Client Config Options
67
+
68
+ These are the configuration options for the client_options hash of the configuration.
69
+
70
+ | Field | Description | Default | Replaced by discovery? |
71
+ |------------------------|-----------------------------------------------------------------|------------|------------------------|
72
+ | identifier | The OAuth2 client_id | | |
73
+ | secret | The OAuth2 client secret | | |
74
+ | redirect_uri | The OAuth2 authorization callback url in your app | | |
75
+ | scheme | The http scheme to use | https | |
76
+ | host | The host of the authorization server | nil | |
77
+ | port | The port for the authorization server | 443 | |
78
+ | authorization_endpoint | The authorize endpoint on the authorization server | /authorize | yes |
79
+ | token_endpoint | The token endpoint on the authorization server | /token | yes |
80
+ | userinfo_endpoint | The user info endpoint on the authorization server | /userinfo | yes |
81
+ | jwks_uri | The jwks_uri on the authorization server | /jwk | yes |
82
+ | end_session_endpoint | The url to call to log the user out at the authorization server | nil | yes |
83
+
84
+ ### Additional Configuration Notes
44
85
  * `name` is arbitrary, I recommend using the name of your provider. The name
45
86
  configuration exists because you could be using multiple OpenID Connect
46
87
  providers in a single app.
@@ -67,6 +108,10 @@ Configuration details:
67
108
  that appears in the `user_info` details.
68
109
  * The `issuer` property should exactly match the provider's issuer link.
69
110
  * The `response_mode` option is optional and specifies how the result of the authorization request is formatted.
111
+ * Some OpenID Connect providers require the `scope` attribute in requests to the token endpoint, even if
112
+ this is not in the protocol specifications. In those cases, the `send_scope_to_token_endpoint`
113
+ property can be used to add the attribute to the token request. Initial value is `true`, which means that the
114
+ scope attribute is included by default.
70
115
 
71
116
  For the full low down on OpenID Connect, please check out
72
117
  [the spec](http://openid.net/specs/openid-connect-core-1_0.html).
@@ -2,6 +2,6 @@
2
2
 
3
3
  module OmniAuth
4
4
  module OpenIDConnect
5
- VERSION = '0.3.3'
5
+ VERSION = '0.3.4'
6
6
  end
7
7
  end
@@ -54,13 +54,11 @@ module OmniAuth
54
54
  option :send_scope_to_token_endpoint, true
55
55
  option :client_auth_method
56
56
  option :post_logout_redirect_uri
57
+ option :extra_authorize_params, {}
57
58
  option :uid_field, 'sub'
58
59
 
59
60
  def uid
60
- user_info.public_send(options.uid_field.to_s)
61
- rescue NoMethodError
62
- log :warn, "User sub:#{user_info.sub} missing info field: #{options.uid_field}"
63
- user_info.sub
61
+ user_info.raw_attributes[options.uid_field.to_sym] || user_info.sub
64
62
  end
65
63
 
66
64
  info do
@@ -110,14 +108,14 @@ module OmniAuth
110
108
  error_description = params['error_description'] || params['error_reason']
111
109
  invalid_state = params['state'].to_s.empty? || params['state'] != stored_state
112
110
 
113
- raise CallbackError.new(params['error'], error_description, params['error_uri']) if error
114
- raise CallbackError, 'Invalid state parameter' if invalid_state
111
+ raise CallbackError, error: params['error'], reason: error_description, uri: params['error_uri'] if error
112
+ raise CallbackError, error: :csrf_detected, reason: "Invalid 'state' parameter" if invalid_state
115
113
 
116
114
  return unless valid_response_type?
117
115
 
118
116
  options.issuer = issuer if options.issuer.nil? || options.issuer.empty?
119
117
 
120
- verify_id_token!
118
+ verify_id_token!(params['id_token']) if configured_response_type == 'id_token'
121
119
  discover!
122
120
  client.redirect_uri = redirect_uri
123
121
 
@@ -126,8 +124,10 @@ module OmniAuth
126
124
  client.authorization_code = authorization_code
127
125
  access_token
128
126
  super
129
- rescue CallbackError, ::Rack::OAuth2::Client::Error => e
130
- fail!(:invalid_credentials, e)
127
+ rescue CallbackError => e
128
+ fail!(e.error, e)
129
+ rescue ::Rack::OAuth2::Client::Error => e
130
+ fail!(e.response[:error], e)
131
131
  rescue ::Timeout::Error, ::Errno::ETIMEDOUT => e
132
132
  fail!(:timeout, e)
133
133
  rescue ::SocketError => e
@@ -170,6 +170,9 @@ module OmniAuth
170
170
  hd: options.hd,
171
171
  acr_values: options.acr_values,
172
172
  }
173
+
174
+ opts.merge!(options.extra_authorize_params) unless options.extra_authorize_params.empty?
175
+
173
176
  client.authorization_uri(opts.reject { |_k, v| v.nil? })
174
177
  end
175
178
 
@@ -202,10 +205,16 @@ module OmniAuth
202
205
  end
203
206
 
204
207
  def access_token
205
- @access_token ||= client.access_token!(
208
+ return @access_token if @access_token
209
+
210
+ @access_token = client.access_token!(
206
211
  scope: (options.scope if options.send_scope_to_token_endpoint),
207
212
  client_auth_method: options.client_auth_method
208
213
  )
214
+
215
+ verify_id_token!(decode_id_token(@access_token.id_token)) if configured_response_type == 'code'
216
+
217
+ @access_token
209
218
  end
210
219
 
211
220
  def decode_id_token(id_token)
@@ -320,21 +329,19 @@ module OmniAuth
320
329
  @configured_response_type ||= options.response_type.to_s
321
330
  end
322
331
 
323
- def verify_id_token!
324
- return unless configured_response_type == 'id_token'
325
-
326
- decode_id_token(params['id_token']).verify!(issuer: options.issuer,
327
- client_id: client_options.identifier,
328
- nonce: stored_nonce)
332
+ def verify_id_token!(id_token)
333
+ decode_id_token(id_token).verify!(issuer: options.issuer,
334
+ client_id: client_options.identifier,
335
+ nonce: stored_nonce)
329
336
  end
330
337
 
331
338
  class CallbackError < StandardError
332
339
  attr_accessor :error, :error_reason, :error_uri
333
340
 
334
- def initialize(error, error_reason = nil, error_uri = nil)
335
- self.error = error
336
- self.error_reason = error_reason
337
- self.error_uri = error_uri
341
+ def initialize(data)
342
+ self.error = data[:error]
343
+ self.error_reason = data[:reason]
344
+ self.error_uri = data[:uri]
338
345
  end
339
346
 
340
347
  def message
@@ -143,6 +143,13 @@ module OmniAuth
143
143
  assert(strategy.authorize_uri =~ /acr_values=/, 'URI must contain acr_values')
144
144
  end
145
145
 
146
+ def test_option_custom_attributes
147
+ strategy.options.client_options[:host] = 'foobar.com'
148
+ strategy.options.extra_authorize_params = {resource: 'xyz'}
149
+
150
+ assert(strategy.authorize_uri =~ /resource=xyz/, 'URI must contain custom params')
151
+ end
152
+
146
153
  def test_uid
147
154
  assert_equal user_info.sub, strategy.uid
148
155
 
@@ -163,7 +170,7 @@ module OmniAuth
163
170
  strategy.options.issuer = 'example.com'
164
171
  strategy.options.client_signing_alg = :RS256
165
172
  strategy.options.client_jwk_signing_key = File.read('test/fixtures/jwks.json')
166
- strategy.options.response_type = :code
173
+ strategy.options.response_type = 'code'
167
174
 
168
175
  strategy.unstub(:user_info)
169
176
  access_token = stub('OpenIDConnect::AccessToken')
@@ -175,6 +182,12 @@ module OmniAuth
175
182
  client.expects(:access_token!).at_least_once.returns(access_token)
176
183
  access_token.expects(:userinfo!).returns(user_info)
177
184
 
185
+ id_token = stub('OpenIDConnect::ResponseObject::IdToken')
186
+ id_token.stubs(:raw_attributes).returns('sub' => 'sub', 'name' => 'name', 'email' => 'email')
187
+ id_token.stubs(:verify!).with(issuer: strategy.options.issuer, client_id: @identifier, nonce: nonce).returns(true)
188
+ ::OpenIDConnect::ResponseObject::IdToken.stubs(:decode).returns(id_token)
189
+ id_token.expects(:verify!)
190
+
178
191
  strategy.call!('rack.session' => { 'omniauth.state' => state, 'omniauth.nonce' => nonce })
179
192
  strategy.callback_phase
180
193
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniauth_openid_connect
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Bohn
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-11-09 00:00:00.000000000 Z
12
+ date: 2020-05-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: addressable
@@ -201,6 +201,9 @@ executables: []
201
201
  extensions: []
202
202
  extra_rdoc_files: []
203
203
  files:
204
+ - ".github/config/rubocop_linter_action.yml"
205
+ - ".github/stale.yml"
206
+ - ".github/workflows/rubocop.yml"
204
207
  - ".gitignore"
205
208
  - ".rubocop.yml"
206
209
  - ".travis.yml"
@@ -241,7 +244,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
241
244
  - !ruby/object:Gem::Version
242
245
  version: '0'
243
246
  requirements: []
244
- rubygems_version: 3.0.2
247
+ rubygems_version: 3.0.6
245
248
  signing_key:
246
249
  specification_version: 4
247
250
  summary: OpenID Connect Strategy for OmniAuth