auth0 5.12.0 → 5.14.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
  SHA256:
3
- metadata.gz: 6c2af1fc93dab97200124859fd5580e1ad973e831caa3784b96f65fc35d75a67
4
- data.tar.gz: 26b20a1047ee3922c1aad85941dbf9315d726a25d01ed52c95fc6b9f90da373b
3
+ metadata.gz: b34c959171acbebc0ef4f851232de93af1d70318bb762243903d5269275843fa
4
+ data.tar.gz: 2856980051e6dec9ede6569c185516ffd08d2dfa4918a96a5fc4d0f96e17d44c
5
5
  SHA512:
6
- metadata.gz: 15d0e7917d187ad06e04f3a17cd8d076486fc82c3e6c40a217c2994b15f7b4a0a31c58f621e9d8ad40072af451c56e6696e7fced2a3e8b0bffc67a6645afe0b4
7
- data.tar.gz: 60e8606c4bdaef79ef5747783ef32cd9d342bc14726aa13593277f16483a0baff0bc928fff9115f6ac8c97537f9dcc503dbb2b9b5571ba8bac0cf39f7cc49356
6
+ metadata.gz: 9e551b02de8f4464e4c688259dc0840844aa3cc80111a78254a7082a67b76209e1a991cbe241d7fc3839fea0fac00bdaf0917863d306c54bd51def3db524cc79
7
+ data.tar.gz: '092c26e20e6b6a850fde55c8beb8f4535a31e20db4144dd001feada3ca4256223580d56e82176ab4264d9146dd0de42610eb77a0ebf7fce9002e489681f9b7ae'
data/.circleci/config.yml CHANGED
@@ -6,7 +6,7 @@ orbs:
6
6
  matrix_ruby_versions: &matrix_ruby_versions
7
7
  matrix:
8
8
  parameters:
9
- ruby_version: ["2.7", "3.0", "3.1", "3.2"]
9
+ ruby_version: ["3.0", "3.1", "3.2"]
10
10
  # Default version of ruby to use for lint and publishing
11
11
  default_ruby_version: &default_ruby_version "3.2"
12
12
 
@@ -41,7 +41,8 @@ jobs:
41
41
  - vendor/bundle
42
42
  # Must define DOMAIN, CLIENT_ID, CLIENT_SECRET and MASTER_JWT env
43
43
  - run: bundle exec rake test
44
- - codecov/upload
44
+ - codecov/upload:
45
+ file: /home/circleci/project/coverage/coverage.xml
45
46
 
46
47
  workflows:
47
48
  tests:
@@ -1,7 +1,7 @@
1
1
  # See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/ruby/.devcontainer/base.Dockerfile
2
2
 
3
3
  # [Choice] Ruby version (use -bullseye variants on local arm64/Apple Silicon): 3, 3.1, 3.0, 2, 2.7, 3-bullseye, 3.1-bullseye, 3.0-bullseye, 2-bullseye, 2.7-bullseye, 3-buster, 3.1-buster, 3.0-buster, 2-buster, 2.7-buster
4
- ARG VARIANT="3.1-bullseye"
4
+ ARG VARIANT="3.2-bullseye"
5
5
  FROM mcr.microsoft.com/vscode/devcontainers/ruby:0-${VARIANT}
6
6
 
7
7
  # [Choice] Node.js version: none, lts/*, 16, 14, 12, 10
@@ -0,0 +1,67 @@
1
+ name: 🐞 Report a bug
2
+ description: Have you found a bug or issue? Create a bug report for this library
3
+ labels: ["bug"]
4
+
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ **Please do not report security vulnerabilities here**. The [Responsible Disclosure Program](https://auth0.com/responsible-disclosure-policy) details the procedure for disclosing security issues.
10
+
11
+ - type: checkboxes
12
+ id: checklist
13
+ attributes:
14
+ label: Checklist
15
+ options:
16
+ - label: I have looked into the [Readme](https://github.com/auth0/ruby-auth0#readme) and [Examples](https://github.com/auth0/ruby-auth0/blob/master/EXAMPLES.md), and have not found a suitable solution or answer.
17
+ required: true
18
+ - label: I have looked into the [API documentation](https://www.rubydoc.info/gems/auth0) and have not found a suitable solution or answer.
19
+ required: true
20
+ - label: I have searched the [issues](https://github.com/auth0/ruby-auth0/issues) and have not found a suitable solution or answer.
21
+ required: true
22
+ - label: I have searched the [Auth0 Community](https://community.auth0.com) forums and have not found a suitable solution or answer.
23
+ required: true
24
+ - label: I agree to the terms within the [Auth0 Code of Conduct](https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md).
25
+ required: true
26
+
27
+ - type: textarea
28
+ id: description
29
+ attributes:
30
+ label: Description
31
+ description: Provide a clear and concise description of the issue, including what you expected to happen.
32
+ validations:
33
+ required: true
34
+
35
+ - type: textarea
36
+ id: reproduction
37
+ attributes:
38
+ label: Reproduction
39
+ description: Detail the steps taken to reproduce this error, and whether this issue can be reproduced consistently or if it is intermittent.
40
+ placeholder: |
41
+ 1. Step 1...
42
+ 2. Step 2...
43
+ 3. ...
44
+ validations:
45
+ required: true
46
+
47
+ - type: textarea
48
+ id: additional-context
49
+ attributes:
50
+ label: Additional context
51
+ description: Other libraries that might be involved, or any other relevant information you think would be useful.
52
+ validations:
53
+ required: false
54
+
55
+ - type: input
56
+ id: environment-version
57
+ attributes:
58
+ label: ruby-auth0 version
59
+ validations:
60
+ required: true
61
+
62
+ - type: input
63
+ id: environment-ruby-version
64
+ attributes:
65
+ label: Ruby version
66
+ validations:
67
+ required: true
@@ -0,0 +1,53 @@
1
+ name: 🧩 Feature request
2
+ description: Suggest an idea or a feature for this library
3
+ labels: ["feature request"]
4
+
5
+ body:
6
+ - type: checkboxes
7
+ id: checklist
8
+ attributes:
9
+ label: Checklist
10
+ options:
11
+ - label: I have looked into the [Readme](https://github.com/auth0/ruby-auth0#readme) and [Examples](https://github.com/auth0/ruby-auth0/blob/master/EXAMPLES.md), and have not found a suitable solution or answer.
12
+ required: true
13
+ - label: I have looked into the [API documentation](https://www.rubydoc.info/gems/auth0) and have not found a suitable solution or answer.
14
+ required: true
15
+ - label: I have searched the [issues](https://github.com/auth0/ruby-auth0/issues) and have not found a suitable solution or answer.
16
+ required: true
17
+ - label: I have searched the [Auth0 Community](https://community.auth0.com) forums and have not found a suitable solution or answer.
18
+ required: true
19
+ - label: I agree to the terms within the [Auth0 Code of Conduct](https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md).
20
+ required: true
21
+
22
+ - type: textarea
23
+ id: description
24
+ attributes:
25
+ label: Describe the problem you'd like to have solved
26
+ description: A clear and concise description of what the problem is.
27
+ placeholder: I'm always frustrated when...
28
+ validations:
29
+ required: true
30
+
31
+ - type: textarea
32
+ id: ideal-solution
33
+ attributes:
34
+ label: Describe the ideal solution
35
+ description: A clear and concise description of what you want to happen.
36
+ validations:
37
+ required: true
38
+
39
+ - type: textarea
40
+ id: alternatives-and-workarounds
41
+ attributes:
42
+ label: Alternatives and current workarounds
43
+ description: A clear and concise description of any alternatives you've considered or any workarounds that are currently in place.
44
+ validations:
45
+ required: false
46
+
47
+ - type: textarea
48
+ id: additional-context
49
+ attributes:
50
+ label: Additional context
51
+ description: Add any other context or screenshots about the feature request here.
52
+ validations:
53
+ required: false
@@ -1,7 +1,7 @@
1
1
  blank_issues_enabled: false
2
2
  contact_links:
3
3
  - name: Auth0 Community
4
- url: https://community.auth0.com/c/sdks/5
4
+ url: https://community.auth0.com
5
5
  about: Discuss this SDK in the Auth0 Community forums
6
6
  - name: SDK API Documentation
7
7
  url: https://www.rubydoc.info/gems/auth0
data/.semgrepignore ADDED
@@ -0,0 +1,6 @@
1
+ .bundle/
2
+ .circleci/
3
+ .devcontainer/
4
+ .github/
5
+ examples/
6
+ spec/
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Change Log
2
2
 
3
+ ## [v5.14.0](https://github.com/auth0/ruby-auth0/tree/v5.14.0) (2023-07-13)
4
+ [Full Changelog](https://github.com/auth0/ruby-auth0/compare/v5.13.0...v5.14.0)
5
+
6
+ **Added**
7
+ - [SDK-4386] Support Organization Name in Authorize [\#495](https://github.com/auth0/ruby-auth0/pull/495) ([stevehobbsdev](https://github.com/stevehobbsdev))
8
+
9
+ ## [v5.13.0](https://github.com/auth0/ruby-auth0/tree/v5.13.0) (2023-04-24)
10
+ [Full Changelog](https://github.com/auth0/ruby-auth0/compare/v5.12.0...v5.13.0)
11
+
12
+ **Added**
13
+ - [SDK-4142] Add support for /oauth/par [\#470](https://github.com/auth0/ruby-auth0/pull/470) ([stevehobbsdev](https://github.com/stevehobbsdev))
14
+
15
+ **Deprecated**
16
+ - Drop support for 2.7 in CI build [\#467](https://github.com/auth0/ruby-auth0/pull/467) ([stevehobbsdev](https://github.com/stevehobbsdev))
17
+
3
18
  ## [v5.12.0](https://github.com/auth0/ruby-auth0/tree/v5.12.0) (2023-03-13)
4
19
  [Full Changelog](https://github.com/auth0/ruby-auth0/compare/v5.11.0...v5.12.0)
5
20
 
data/EXAMPLES.md CHANGED
@@ -85,7 +85,7 @@ Note that Organizations is currently only available to customers on our Enterpri
85
85
 
86
86
  ### Logging in with an Organization
87
87
 
88
- Configure the Authentication API client and pass your Organization ID to the authorize url:
88
+ Configure the Authentication API client and pass your Organization ID or name to the authorize url:
89
89
 
90
90
  ```ruby
91
91
  require 'auth0'
@@ -94,7 +94,7 @@ require 'auth0'
94
94
  client_id: '{YOUR_APPLICATION_CLIENT_ID}',
95
95
  client_secret: '{YOUR_APPLICATION_CLIENT_SECRET}',
96
96
  domain: '{YOUR_TENANT}.auth0.com',
97
- organization: "{YOUR_ORGANIZATION_ID}"
97
+ organization: "{YOUR_ORGANIZATION_ID_OR_NAME}"
98
98
  )
99
99
 
100
100
  universal_login_url = @auth0_client.authorization_url("https://{YOUR_APPLICATION_CALLBACK_URL}")
@@ -113,7 +113,7 @@ require 'auth0'
113
113
  client_id: '{YOUR_APPLICATION_CLIENT_ID}',
114
114
  client_secret: '{YOUR_APPLICATION_CLIENT_ID}',
115
115
  domain: '{YOUR_TENANT}.auth0.com',
116
- organization: "{YOUR_ORGANIZATION_ID}"
116
+ organization: "{YOUR_ORGANIZATION_ID_OR_NAME}"
117
117
  )
118
118
 
119
119
  universal_login_url = @auth0_client.authorization_url("https://{YOUR_APPLICATION_CALLBACK_URL}", {
@@ -148,7 +148,7 @@ The method takes the following optional keyword parameters:
148
148
  | `max_age` | Integer | The `max_age` value you sent in the call to `/authorize`, if any. | `nil` |
149
149
  | `issuer` | String | By default the `iss` claim will be checked against the URL of your **Auth0 Domain**. Use this parameter to override that. | `nil` |
150
150
  | `audience` | String | By default the `aud` claim will be compared to your **Auth0 Client ID**. Use this parameter to override that. | `nil` |
151
- | `organization` | String | By default the `org_id` claim will be compared to your **Organization ID**. Use this parameter to override that. | `nil` |
151
+ | `organization` | String | By default the `org_id` or `org_name` claims will be compared to the `organization` value specified at client creation. Use this parameter to override that. | `nil` |
152
152
 
153
153
  You can check the signing algorithm value under **Advanced Settings > OAuth > JsonWebToken Signature Algorithm** in your Auth0 application settings panel. [We recommend](https://auth0.com/docs/tokens/concepts/signing-algorithms#our-recommendation) that you make use of asymmetric signing algorithms like `RS256` instead of symmetric ones like `HS256`.
154
154
 
@@ -170,15 +170,17 @@ rescue Auth0::InvalidIdToken => e
170
170
  end
171
171
  ```
172
172
 
173
- ### Organization ID Token Validation
173
+ ### Organization claim validation
174
174
 
175
- If an org_id claim is present in the Access Token, then the claim should be validated by the API to ensure that the value received is expected or known.
175
+ If an `org_id` or `org_name` claim is present in the access token, then the claim should be validated by the API to ensure that the value received is expected or known.
176
176
 
177
177
  In particular:
178
178
 
179
179
  - The issuer (iss) claim should be checked to ensure the token was issued by Auth0
180
180
 
181
- - the org_id claim should be checked to ensure it is a value that is already known to the application. This could be validated against a known list of organization IDs, or perhaps checked in conjunction with the current request URL. e.g. the sub-domain may hint at what organization should be used to validate the Access Token.
181
+ - the `org_id` or `org_name` claim should be checked to ensure it is a value that is already known to the application. Which claim you check depends on the organization value being validated: if it starts with `org_`, validate against the `org_id` claim. Otherwise, validate against `org_name`. Further, `org_name` validation should be done using a **case-insensitive** check, whereas `org_id` should be an exact case-sensitive match.
182
+
183
+ This could be validated against a known list of organization IDs or names, or perhaps checked in conjunction with the current request URL. e.g. the sub-domain may hint at what organization should be used to validate the Access Token.
182
184
 
183
185
  Normally, validating the issuer would be enough to ensure that the token was issued by Auth0. In the case of organizations, additional checks should be made so that the organization within an Auth0 tenant is expected.
184
186
 
@@ -186,7 +188,7 @@ If the claim cannot be validated, then the application should deem the token inv
186
188
 
187
189
  ```ruby
188
190
  begin
189
- @auth0_client.validate_id_token 'YOUR_ID_TOKEN', organization: '{Expected org_id}'
191
+ @auth0_client.validate_id_token 'YOUR_ID_TOKEN', organization: '{Expected org_id or org_name}'
190
192
  rescue Auth0::InvalidIdToken => e
191
193
  # In this case the ID Token contents should not be trusted
192
194
  end
data/Gemfile.lock CHANGED
@@ -1,9 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- auth0 (5.12.0)
4
+ auth0 (5.14.0)
5
5
  addressable (~> 2.8)
6
- jwt (~> 2.5)
6
+ jwt (~> 2.7)
7
7
  rest-client (~> 2.1)
8
8
  retryable (~> 3.0)
9
9
  zache (~> 0.12)
@@ -11,25 +11,25 @@ PATH
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
- actionpack (7.0.4.2)
15
- actionview (= 7.0.4.2)
16
- activesupport (= 7.0.4.2)
17
- rack (~> 2.0, >= 2.2.0)
14
+ actionpack (7.0.6)
15
+ actionview (= 7.0.6)
16
+ activesupport (= 7.0.6)
17
+ rack (~> 2.0, >= 2.2.4)
18
18
  rack-test (>= 0.6.3)
19
19
  rails-dom-testing (~> 2.0)
20
20
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
21
- actionview (7.0.4.2)
22
- activesupport (= 7.0.4.2)
21
+ actionview (7.0.6)
22
+ activesupport (= 7.0.6)
23
23
  builder (~> 3.1)
24
24
  erubi (~> 1.4)
25
25
  rails-dom-testing (~> 2.0)
26
26
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
27
- activesupport (7.0.4.2)
27
+ activesupport (7.0.6)
28
28
  concurrent-ruby (~> 1.0, >= 1.0.2)
29
29
  i18n (>= 1.6, < 2)
30
30
  minitest (>= 5.1)
31
31
  tzinfo (~> 2.0)
32
- addressable (2.8.1)
32
+ addressable (2.8.4)
33
33
  public_suffix (>= 2.0.2, < 6.0)
34
34
  ast (2.4.2)
35
35
  builder (3.2.4)
@@ -62,52 +62,56 @@ GEM
62
62
  http-accept (1.7.0)
63
63
  http-cookie (1.0.5)
64
64
  domain_name (~> 0.5)
65
- i18n (1.12.0)
65
+ i18n (1.14.1)
66
66
  concurrent-ruby (~> 1.0)
67
67
  io-console (0.6.0)
68
- irb (1.6.3)
69
- reline (>= 0.3.0)
68
+ irb (1.7.3)
69
+ reline (>= 0.3.6)
70
70
  json (2.6.3)
71
- jwt (2.7.0)
72
- loofah (2.19.1)
71
+ jwt (2.7.1)
72
+ language_server-protocol (3.17.0.3)
73
+ loofah (2.21.3)
73
74
  crass (~> 1.0.2)
74
- nokogiri (>= 1.5.9)
75
+ nokogiri (>= 1.12.0)
75
76
  method_source (1.0.0)
76
77
  mime-types (3.4.1)
77
78
  mime-types-data (~> 3.2015)
78
79
  mime-types-data (3.2023.0218.1)
79
- minitest (5.18.0)
80
+ minitest (5.18.1)
80
81
  multi_json (1.15.0)
81
82
  netrc (0.11.0)
82
- nokogiri (1.14.2-x86_64-linux)
83
+ nokogiri (1.15.3-x86_64-linux)
83
84
  racc (~> 1.4)
84
- parallel (1.22.1)
85
- parser (3.2.1.1)
85
+ parallel (1.23.0)
86
+ parser (3.2.2.3)
86
87
  ast (~> 2.4.1)
88
+ racc
87
89
  pp (0.4.0)
88
90
  prettyprint
89
91
  prettyprint (0.1.1)
90
- public_suffix (5.0.1)
91
- racc (1.6.2)
92
- rack (2.2.6.3)
92
+ public_suffix (5.0.3)
93
+ racc (1.7.1)
94
+ rack (2.2.7)
93
95
  rack-test (0.8.3)
94
96
  rack (>= 1.0, < 3)
95
- rails-dom-testing (2.0.3)
96
- activesupport (>= 4.2.0)
97
+ rails-dom-testing (2.1.1)
98
+ activesupport (>= 5.0.0)
99
+ minitest
97
100
  nokogiri (>= 1.6)
98
- rails-html-sanitizer (1.5.0)
99
- loofah (~> 2.19, >= 2.19.1)
100
- railties (7.0.4.2)
101
- actionpack (= 7.0.4.2)
102
- activesupport (= 7.0.4.2)
101
+ rails-html-sanitizer (1.6.0)
102
+ loofah (~> 2.21)
103
+ nokogiri (~> 1.14)
104
+ railties (7.0.6)
105
+ actionpack (= 7.0.6)
106
+ activesupport (= 7.0.6)
103
107
  method_source
104
108
  rake (>= 12.2)
105
109
  thor (~> 1.0)
106
110
  zeitwerk (~> 2.5)
107
111
  rainbow (3.1.1)
108
112
  rake (13.0.6)
109
- regexp_parser (2.7.0)
110
- reline (0.3.2)
113
+ regexp_parser (2.8.1)
114
+ reline (0.3.6)
111
115
  io-console (~> 0.5)
112
116
  rest-client (2.1.0)
113
117
  http-accept (>= 1.7.0, < 2.0)
@@ -120,28 +124,29 @@ GEM
120
124
  rspec-core (~> 3.12.0)
121
125
  rspec-expectations (~> 3.12.0)
122
126
  rspec-mocks (~> 3.12.0)
123
- rspec-core (3.12.1)
127
+ rspec-core (3.12.2)
124
128
  rspec-support (~> 3.12.0)
125
- rspec-expectations (3.12.2)
129
+ rspec-expectations (3.12.3)
126
130
  diff-lcs (>= 1.2.0, < 2.0)
127
131
  rspec-support (~> 3.12.0)
128
- rspec-mocks (3.12.4)
132
+ rspec-mocks (3.12.6)
129
133
  diff-lcs (>= 1.2.0, < 2.0)
130
134
  rspec-support (~> 3.12.0)
131
- rspec-support (3.12.0)
132
- rubocop (1.48.1)
135
+ rspec-support (3.12.1)
136
+ rubocop (1.54.1)
133
137
  json (~> 2.3)
138
+ language_server-protocol (>= 3.17.0)
134
139
  parallel (~> 1.10)
135
- parser (>= 3.2.0.0)
140
+ parser (>= 3.2.2.3)
136
141
  rainbow (>= 2.2.2, < 4.0)
137
142
  regexp_parser (>= 1.8, < 3.0)
138
143
  rexml (>= 3.2.5, < 4.0)
139
- rubocop-ast (>= 1.26.0, < 2.0)
144
+ rubocop-ast (>= 1.28.0, < 2.0)
140
145
  ruby-progressbar (~> 1.7)
141
146
  unicode-display_width (>= 2.4.0, < 3.0)
142
- rubocop-ast (1.27.0)
147
+ rubocop-ast (1.29.0)
143
148
  parser (>= 3.2.1.0)
144
- rubocop-rails (2.18.0)
149
+ rubocop-rails (2.20.2)
145
150
  activesupport (>= 4.2.0)
146
151
  rack (>= 1.1)
147
152
  rubocop (>= 1.33.0, < 2.0)
@@ -158,7 +163,7 @@ GEM
158
163
  sync (0.5.0)
159
164
  term-ansicolor (1.7.1)
160
165
  tins (~> 1.0)
161
- thor (1.2.1)
166
+ thor (1.2.2)
162
167
  timecop (0.9.6)
163
168
  tins (1.32.1)
164
169
  sync
@@ -168,13 +173,13 @@ GEM
168
173
  unf_ext
169
174
  unf_ext (0.0.8.2)
170
175
  unicode-display_width (2.4.2)
171
- vcr (6.1.0)
176
+ vcr (6.2.0)
172
177
  webmock (3.18.1)
173
178
  addressable (>= 2.8.0)
174
179
  crack (>= 0.3.2)
175
180
  hashdiff (>= 0.4.0, < 2.0.0)
176
- zache (0.12.0)
177
- zeitwerk (2.6.7)
181
+ zache (0.13.0)
182
+ zeitwerk (2.6.8)
178
183
 
179
184
  PLATFORMS
180
185
  x86_64-linux
@@ -202,4 +207,4 @@ DEPENDENCIES
202
207
  webmock
203
208
 
204
209
  BUNDLED WITH
205
- 2.3.26
210
+ 2.4.10
data/auth0.gemspec CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
17
17
  s.require_paths = ['lib']
18
18
 
19
19
  s.add_runtime_dependency 'rest-client', '~> 2.1'
20
- s.add_runtime_dependency 'jwt', '~> 2.5'
20
+ s.add_runtime_dependency 'jwt', '~> 2.7'
21
21
  s.add_runtime_dependency 'zache', '~> 0.12'
22
22
  s.add_runtime_dependency 'addressable', '~> 2.8'
23
23
  s.add_runtime_dependency 'retryable', '~> 3.0'
@@ -8,7 +8,7 @@ GEM
8
8
  nio4r (2.5.8)
9
9
  puma (5.6.5)
10
10
  nio4r (~> 2.0)
11
- rack (2.2.6.3)
11
+ rack (2.2.6.4)
12
12
  rack-protection (2.2.3)
13
13
  rack
14
14
  ruby2_keywords (0.0.5)
@@ -323,6 +323,21 @@ module Auth0
323
323
  URI::HTTPS.build(host: @domain, path: '/authorize', query: to_query(request_params))
324
324
  end
325
325
 
326
+ # Return an authorization URL for PAR requests
327
+ # @see https://www.rfc-editor.org/rfc/rfc9126.html
328
+ # @param request_uri [string] The request_uri as obtained by calling `pushed_authorization_request`
329
+ # @param additional_parameters Any additional parameters to send
330
+ def par_authorization_url(request_uri)
331
+ raise Auth0::InvalidParameter, 'Must supply a valid request_uri' if request_uri.to_s.empty?
332
+
333
+ request_params = {
334
+ client_id: @client_id,
335
+ request_uri: request_uri,
336
+ }
337
+
338
+ URI::HTTPS.build(host: @domain, path: '/authorize', query: to_query(request_params))
339
+ end
340
+
326
341
  # Returns an Auth0 logout URL with a return URL.
327
342
  # @see https://auth0.com/docs/api/authentication#logout
328
343
  # @see https://auth0.com/docs/logout
@@ -344,6 +359,28 @@ module Auth0
344
359
  )
345
360
  end
346
361
 
362
+ # Make a request to the PAR endpoint and receive a `request_uri` to send to the '/authorize' endpoint.
363
+ # @see https://auth0.com/docs/api/authentication#authorization-code-grant
364
+ # @param redirect_uri [string] URL to redirect after authorization
365
+ # @param options [hash] Can contain response_type, connection, state, organization, invitation, and additional_parameters.
366
+ # @return [url] Authorization URL.
367
+ def pushed_authorization_request(parameters = {})
368
+ request_params = {
369
+ client_id: @client_id,
370
+ response_type: parameters.fetch(:response_type, 'code'),
371
+ connection: parameters.fetch(:connection, nil),
372
+ redirect_uri: parameters.fetch(:redirect_uri, nil),
373
+ state: parameters.fetch(:state, nil),
374
+ scope: parameters.fetch(:scope, nil),
375
+ organization: parameters.fetch(:organization, nil),
376
+ invitation: parameters.fetch(:invitation, nil)
377
+ }.merge(parameters.fetch(:additional_parameters, {}))
378
+
379
+ populate_client_assertion_or_secret(request_params)
380
+
381
+ request_with_retry(:post_form, '/oauth/par', request_params, {})
382
+ end
383
+
347
384
  # Return a SAMLP URL.
348
385
  # The SAML Request AssertionConsumerServiceURL will be used to POST back
349
386
  # the assertion and it must match with the application callback URL.
@@ -16,7 +16,7 @@ module Auth0
16
16
  BASE_DELAY = 100
17
17
 
18
18
  # proxying requests from instance methods to HTTP class methods
19
- %i(get post post_file put patch delete delete_with_body).each do |method|
19
+ %i(get post post_file post_form put patch delete delete_with_body).each do |method|
20
20
  define_method(method) do |uri, body = {}, extra_headers = {}|
21
21
  body = body.delete_if { |_, v| v.nil? }
22
22
  token = get_token()
@@ -85,9 +85,12 @@ module Auth0
85
85
  elsif method == :post_file
86
86
  body.merge!(multipart: true)
87
87
  # Ignore the default Content-Type headers and let the HTTP client define them
88
- post_file_headers = headers.slice(*headers.keys - ['Content-Type'])
88
+ post_file_headers = headers.except('Content-Type') if headers != nil
89
89
  # Actual call with the altered headers
90
90
  call(:post, encode_uri(uri), timeout, post_file_headers, body)
91
+ elsif method == :post_form
92
+ form_post_headers = headers.except('Content-Type') if headers != nil
93
+ call(:post, encode_uri(uri), timeout, form_post_headers, body.compact)
91
94
  else
92
95
  call(method, encode_uri(uri), timeout, headers, body.to_json)
93
96
  end
@@ -188,13 +188,26 @@ module Auth0
188
188
  end
189
189
 
190
190
  def validate_org(claims, expected)
191
- unless claims.key?('org_id') && claims['org_id'].is_a?(String)
192
- raise Auth0::InvalidIdToken, 'Organization Id (org_id) claim must be a string present in the ID token'
193
- end
191
+ validate_as_id = expected.start_with? 'org_'
192
+
193
+ if validate_as_id
194
+ unless claims.key?('org_id') && claims['org_id'].is_a?(String)
195
+ raise Auth0::InvalidIdToken, 'Organization Id (org_id) claim must be a string present in the ID token'
196
+ end
194
197
 
195
- unless expected == claims['org_id']
196
- raise Auth0::InvalidIdToken, "Organization Id (org_id) claim value mismatch in the ID token; expected \"#{expected}\","\
197
- " found \"#{claims['org_id']}\""
198
+ unless expected == claims['org_id']
199
+ raise Auth0::InvalidIdToken, "Organization Id (org_id) claim value mismatch in the ID token; expected \"#{expected}\","\
200
+ " found \"#{claims['org_id']}\""
201
+ end
202
+ else
203
+ unless claims.key?('org_name') && claims['org_name'].is_a?(String)
204
+ raise Auth0::InvalidIdToken, 'Organization Name (org_name) claim must be a string present in the ID token'
205
+ end
206
+
207
+ unless expected.downcase == claims['org_name'].downcase
208
+ raise Auth0::InvalidIdToken, "Organization Name (org_name) claim value mismatch in the ID token; expected \"#{expected}\","\
209
+ " found \"#{claims['org_name']}\""
210
+ end
198
211
  end
199
212
  end
200
213
 
data/lib/auth0/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # current version of gem
2
2
  module Auth0
3
- VERSION = '5.12.0'.freeze
3
+ VERSION = '5.14.0'.freeze
4
4
  end
@@ -6,6 +6,7 @@ describe Auth0::Api::AuthenticationEndpoints do
6
6
  let(:client_secret) { 'test-client-secret' }
7
7
  let(:api_identifier) { 'test-audience' }
8
8
  let(:domain) { 'samples.auth0.com' }
9
+ let(:request_uri) { 'urn:ietf:params:oauth:request_uri:the.request.uri' }
9
10
 
10
11
  let(:client_secret_config) { {
11
12
  domain: domain,
@@ -628,5 +629,94 @@ describe Auth0::Api::AuthenticationEndpoints do
628
629
  client_assertion_instance.send :start_passwordless_sms_flow, '123456789'
629
630
  end
630
631
  end
632
+
633
+ context 'par_authorization_url' do
634
+ it 'throws an exception if request_uri is nil' do
635
+ expect { client_secret_instance.send :par_authorization_url, nil}.to raise_error Auth0::InvalidParameter
636
+ end
637
+
638
+ it 'throws an exception if request_uri is empty' do
639
+ expect { client_secret_instance.send :par_authorization_url, ''}.to raise_error Auth0::InvalidParameter
640
+ end
641
+
642
+ it 'builds a URL containing the request_uri' do
643
+ url = client_secret_instance.send :par_authorization_url, request_uri
644
+ expect(CGI.unescape(url.to_s)).to eq("https://samples.auth0.com/authorize?client_id=#{client_id}&request_uri=#{request_uri}")
645
+ end
646
+ end
647
+
648
+ context 'pushed_authorization_request' do
649
+ it 'sends the request as a form post' do
650
+ expect(RestClient::Request).to receive(:execute) do |arg|
651
+ expect(arg[:url]).to eq('https://samples.auth0.com/oauth/par')
652
+ expect(arg[:method]).to eq(:post)
653
+
654
+ expect(arg[:payload]).to eq({
655
+ client_id: client_id,
656
+ client_secret: client_secret,
657
+ response_type: 'code',
658
+ })
659
+
660
+ StubResponse.new({}, true, 200)
661
+ end
662
+
663
+ client_secret_instance.send :pushed_authorization_request
664
+ end
665
+
666
+ it 'allows the RestClient to handle the correct header defaults' do
667
+ expect(RestClient::Request).to receive(:execute) do |arg|
668
+ expect(arg[:headers]).not_to have_key('Content-Type')
669
+
670
+ StubResponse.new({}, true, 200)
671
+ end
672
+
673
+ client_secret_instance.headers['Content-Type'] = 'application/x-www-form-urlencoded'
674
+ client_secret_instance.send :pushed_authorization_request
675
+ end
676
+
677
+ it 'sends the request as a form post with all known overrides' do
678
+ expect(RestClient::Request).to receive(:execute) do |arg|
679
+ expect(arg[:url]).to eq('https://samples.auth0.com/oauth/par')
680
+ expect(arg[:method]).to eq(:post)
681
+
682
+ expect(arg[:payload]).to eq({
683
+ client_id: client_id,
684
+ client_secret: client_secret,
685
+ connection: 'google-oauth2',
686
+ organization: 'org_id',
687
+ invitation: 'http://invite.url',
688
+ redirect_uri: 'http://localhost:3000',
689
+ response_type: 'id_token',
690
+ scope: 'openid',
691
+ state: 'random_value'
692
+ })
693
+
694
+ StubResponse.new({}, true, 200)
695
+ end
696
+
697
+ client_secret_instance.send(:pushed_authorization_request,
698
+ response_type: 'id_token',
699
+ redirect_uri: 'http://localhost:3000',
700
+ organization: 'org_id',
701
+ invitation: 'http://invite.url',
702
+ scope: 'openid',
703
+ state: 'random_value',
704
+ connection: 'google-oauth2')
705
+ end
706
+
707
+ it 'sends the request as a form post using client assertion' do
708
+ expect(RestClient::Request).to receive(:execute) do |arg|
709
+ expect(arg[:url]).to eq('https://samples.auth0.com/oauth/par')
710
+ expect(arg[:method]).to eq(:post)
711
+ expect(arg[:payload][:client_secret]).to be_nil
712
+ expect(arg[:payload][:client_assertion]).not_to be_nil
713
+ expect(arg[:payload][:client_assertion_type]).to eq Auth0::ClientAssertion::CLIENT_ASSERTION_TYPE
714
+
715
+ StubResponse.new({}, true, 200)
716
+ end
717
+
718
+ client_assertion_instance.send :pushed_authorization_request
719
+ end
720
+ end
631
721
  end
632
722
  end
@@ -250,25 +250,37 @@ describe Auth0::Mixins::HTTPProxy do
250
250
  end
251
251
  end
252
252
 
253
- %i(post put patch).each do |http_method|
253
+ def expected_payload(method, overrides = {})
254
+ if method == :post_form
255
+ {
256
+ method: :post,
257
+ url: 'https://auth0.com/test',
258
+ timeout: nil,
259
+ headers: nil,
260
+ payload: {}
261
+ }.merge(overrides)
262
+ else
263
+ {
264
+ method: method,
265
+ url: 'https://auth0.com/test',
266
+ timeout: nil,
267
+ headers: nil,
268
+ payload: '{}'
269
+ }.merge(overrides)
270
+ end
271
+ end
272
+
273
+ %i(post post_form put patch).each do |http_method|
254
274
  context ".#{http_method}" do
255
275
  it { expect(@instance).to respond_to(http_method.to_sym) }
256
- it "should call send http #{http_method} method to path defined through HTTP" do
257
- expect(RestClient::Request).to receive(:execute).with(method: http_method,
258
- url: 'https://auth0.com/test',
259
- timeout: nil,
260
- headers: nil,
261
- payload: '{}')
276
+ it "should call send http #{http_method} method to path defined through HTTP"do
277
+ expect(RestClient::Request).to receive(:execute).with(expected_payload(http_method))
262
278
  .and_return(StubResponse.new({}, true, 200))
263
279
  expect { @instance.send(http_method, '/test') }.not_to raise_error
264
280
  end
265
281
 
266
282
  it 'should not raise exception if data returned not in json format (should be fixed in v2)' do
267
- allow(RestClient::Request).to receive(:execute).with(method: http_method,
268
- url: 'https://auth0.com/test',
269
- timeout: nil,
270
- headers: nil,
271
- payload: '{}')
283
+ allow(RestClient::Request).to receive(:execute).with(expected_payload(http_method))
272
284
  .and_return(StubResponse.new('Some random text here', true, 200))
273
285
  expect { @instance.send(http_method, '/test') }.not_to raise_error
274
286
  expect(@instance.send(http_method, '/test')).to eql('Some random text here')
@@ -277,11 +289,7 @@ describe Auth0::Mixins::HTTPProxy do
277
289
  it "should raise Auth0::Unauthorized on send http #{http_method} method
278
290
  to path defined through HTTP when 401 status received" do
279
291
  @exception.response = StubResponse.new({}, false, 401)
280
- allow(RestClient::Request).to receive(:execute).with(method: http_method,
281
- url: 'https://auth0.com/test',
282
- timeout: nil,
283
- headers: nil,
284
- payload: '{}')
292
+ allow(RestClient::Request).to receive(:execute).with(expected_payload(http_method))
285
293
  .and_raise(@exception)
286
294
  expect { @instance.send(http_method, '/test') }.to raise_error(Auth0::Unauthorized)
287
295
  end
@@ -294,11 +302,7 @@ describe Auth0::Mixins::HTTPProxy do
294
302
  :x_ratelimit_reset => 1560564149
295
303
  }
296
304
  @exception.response = StubResponse.new({}, false, 429,headers)
297
- allow(RestClient::Request).to receive(:execute).with(method: http_method,
298
- url: 'https://auth0.com/test',
299
- timeout: nil,
300
- headers: nil,
301
- payload: '{}')
305
+ allow(RestClient::Request).to receive(:execute).with(expected_payload(http_method))
302
306
  .and_raise(@exception)
303
307
  expect { @instance.send(http_method, '/test') }.to raise_error { |error|
304
308
  expect(error).to be_a(Auth0::RateLimitEncountered)
@@ -317,11 +321,7 @@ describe Auth0::Mixins::HTTPProxy do
317
321
  it "should raise Auth0::NotFound on send http #{http_method} method
318
322
  to path defined through HTTP when 404 status received" do
319
323
  @exception.response = StubResponse.new({}, false, 404)
320
- allow(RestClient::Request).to receive(:execute).with(method: http_method,
321
- url: 'https://auth0.com/test',
322
- timeout: nil,
323
- headers: nil,
324
- payload: '{}')
324
+ allow(RestClient::Request).to receive(:execute).with(expected_payload(http_method))
325
325
  .and_raise(@exception)
326
326
  expect { @instance.send(http_method, '/test') }.to raise_error(Auth0::NotFound)
327
327
  end
@@ -329,22 +329,14 @@ describe Auth0::Mixins::HTTPProxy do
329
329
  it "should raise Auth0::Unsupported on send http #{http_method} method
330
330
  to path defined through HTTP when 418 or other unknown status received" do
331
331
  @exception.response = StubResponse.new({}, false, 418)
332
- allow(RestClient::Request).to receive(:execute).with(method: http_method,
333
- url: 'https://auth0.com/test',
334
- timeout: nil,
335
- headers: nil,
336
- payload: '{}')
332
+ allow(RestClient::Request).to receive(:execute).with(expected_payload(http_method))
337
333
  .and_raise(@exception)
338
334
  expect { @instance.send(http_method, '/test') }.to raise_error(Auth0::Unsupported)
339
335
  end
340
336
 
341
337
  it "should raise Auth0::RequestTimeout on send http #{http_method} method
342
338
  to path defined through HTTP when RestClient::RequestTimeout received" do
343
- allow(RestClient::Request).to receive(:execute).with(method: http_method,
344
- url: 'https://auth0.com/test',
345
- timeout: nil,
346
- headers: nil,
347
- payload: '{}')
339
+ allow(RestClient::Request).to receive(:execute).with(expected_payload(http_method))
348
340
  .and_raise(RestClient::Exceptions::OpenTimeout.new)
349
341
  expect { @instance.send(http_method, '/test') }.to raise_error(Auth0::RequestTimeout)
350
342
  end
@@ -352,11 +344,7 @@ describe Auth0::Mixins::HTTPProxy do
352
344
  it "should raise Auth0::BadRequest on send http #{http_method} method
353
345
  to path defined through HTTP when 400 status received" do
354
346
  @exception.response = StubResponse.new({}, false, 400)
355
- allow(RestClient::Request).to receive(:execute).with(method: http_method,
356
- url: 'https://auth0.com/test',
357
- timeout: nil,
358
- headers: nil,
359
- payload: '{}')
347
+ allow(RestClient::Request).to receive(:execute).with(expected_payload(http_method))
360
348
  .and_raise(@exception)
361
349
  expect { @instance.send(http_method, '/test') }.to raise_error(Auth0::BadRequest)
362
350
  end
@@ -364,20 +352,13 @@ describe Auth0::Mixins::HTTPProxy do
364
352
  it "should raise Auth0::ServerError on send http #{http_method} method
365
353
  to path defined through HTTP when 500 received" do
366
354
  @exception.response = StubResponse.new({}, false, 500)
367
- allow(RestClient::Request).to receive(:execute).with(method: http_method, url: 'https://auth0.com/test',
368
- timeout: nil,
369
- headers: nil,
370
- payload: '{}')
355
+ allow(RestClient::Request).to receive(:execute).with(expected_payload(http_method))
371
356
  .and_raise(@exception)
372
357
  expect { @instance.send(http_method, '/test') }.to raise_error(Auth0::ServerError)
373
358
  end
374
359
 
375
360
  it 'should normalize path with Addressable::URI' do
376
- expect(RestClient::Request).to receive(:execute).with(method: http_method,
377
- url: 'https://auth0.com/te%20st',
378
- timeout: nil,
379
- headers: nil,
380
- payload: '{}')
361
+ expect(RestClient::Request).to receive(:execute).with(expected_payload(http_method, url: 'https://auth0.com/te%20st'))
381
362
  .and_return(StubResponse.new({}, true, 200))
382
363
  expect { @instance.send(http_method, '/te st') }.not_to raise_error
383
364
  end
@@ -388,11 +369,7 @@ describe Auth0::Mixins::HTTPProxy do
388
369
  'message' => "Path validation error: 'String does not match pattern ^.+\\|.+$:
389
370
  3241312' on property id (The user_id of the user to retrieve).",
390
371
  'errorCode' => 'invalid_uri')
391
- expect(RestClient::Request).to receive(:execute).with(method: http_method,
392
- url: 'https://auth0.com/test',
393
- timeout: nil,
394
- headers: nil,
395
- payload: '{}')
372
+ expect(RestClient::Request).to receive(:execute).with(expected_payload(http_method))
396
373
  .and_return(StubResponse.new(res, true, 404))
397
374
  expect { @instance.send(http_method, '/test') }.to raise_error(Auth0::NotFound, res)
398
375
  end
@@ -404,11 +381,7 @@ describe Auth0::Mixins::HTTPProxy do
404
381
  retry_instance.base_uri = "https://auth0.com"
405
382
 
406
383
  @exception.response = StubResponse.new({}, false, 429)
407
- allow(RestClient::Request).to receive(:execute).with(method: http_method,
408
- url: 'https://auth0.com/test',
409
- timeout: nil,
410
- headers: nil,
411
- payload: '{}')
384
+ allow(RestClient::Request).to receive(:execute).with(expected_payload(http_method))
412
385
  .and_raise(@exception)
413
386
  expect(RestClient::Request).to receive(:execute).exactly(4).times
414
387
 
@@ -424,11 +397,7 @@ describe Auth0::Mixins::HTTPProxy do
424
397
  retry_instance.retry_count = 2
425
398
 
426
399
  @exception.response = StubResponse.new({}, false, 429)
427
- allow(RestClient::Request).to receive(:execute).with(method: http_method,
428
- url: 'https://auth0.com/test',
429
- timeout: nil,
430
- headers: nil,
431
- payload: '{}')
400
+ allow(RestClient::Request).to receive(:execute).with(expected_payload(http_method))
432
401
  .and_raise(@exception)
433
402
  expect(RestClient::Request).to receive(:execute).exactly(3).times
434
403
 
@@ -445,11 +414,7 @@ describe Auth0::Mixins::HTTPProxy do
445
414
 
446
415
  @exception.response = StubResponse.new({}, false, 429)
447
416
 
448
- allow(RestClient::Request).to receive(:execute).with(method: http_method,
449
- url: 'https://auth0.com/test',
450
- timeout: nil,
451
- headers: nil,
452
- payload: '{}')
417
+ allow(RestClient::Request).to receive(:execute).with(expected_payload(http_method))
453
418
  .and_raise(@exception)
454
419
 
455
420
  expect(RestClient::Request).to receive(:execute).exactly(1).times
@@ -467,11 +432,7 @@ describe Auth0::Mixins::HTTPProxy do
467
432
  @time_start
468
433
 
469
434
  @exception.response = StubResponse.new({}, false, 429)
470
- allow(RestClient::Request).to receive(:execute).with(method: http_method,
471
- url: 'https://auth0.com/test',
472
- timeout: nil,
473
- headers: nil,
474
- payload: '{}') do
435
+ allow(RestClient::Request).to receive(:execute).with(expected_payload(http_method)) do
475
436
 
476
437
  time_entries.push(Time.now.to_f - @time_start.to_f)
477
438
  @time_start = Time.now.to_f # restart the clock
@@ -492,6 +453,7 @@ describe Auth0::Mixins::HTTPProxy do
492
453
  end
493
454
  end
494
455
  end
456
+ end
495
457
 
496
458
  context "Renewing tokens" do
497
459
  let(:httpproxy_instance) {
@@ -546,7 +508,6 @@ describe Auth0::Mixins::HTTPProxy do
546
508
  end
547
509
  end
548
510
  end
549
- end
550
511
 
551
512
  context "Using cached tokens" do
552
513
  let(:httpproxy_instance) {
@@ -1,5 +1,6 @@
1
1
  # rubocop:disable Metrics/BlockLength
2
2
  require 'spec_helper'
3
+ require 'jwt'
3
4
 
4
5
  RSA_PUB_KEY_JWK_1 = { 'kty': "RSA", 'use': 'sig', 'n': "uGbXWiK3dQTyCbX5xdE4yCuYp0AF2d15Qq1JSXT_lx8CEcXb9RbDddl8jGDv-spi5qPa8qEHiK7FwV2KpRE983wGPnYsAm9BxLFb4YrLYcDFOIGULuk2FtrPS512Qea1bXASuvYXEpQNpGbnTGVsWXI9C-yjHztqyL2h8P6mlThPY9E9ue2fCqdgixfTFIF9Dm4SLHbphUS2iw7w1JgT69s7of9-I9l5lsJ9cozf1rxrXX4V1u_SotUuNB3Fp8oB4C1fLBEhSlMcUJirz1E8AziMCxS-VrRPDM-zfvpIJg3JljAh3PJHDiLu902v9w-Iplu1WyoB2aPfitxEhRN0Yw", 'e': 'AQAB', 'kid': 'test-key-1' }.freeze
5
6
  RSA_PUB_KEY_JWK_2 = { 'kty': "RSA", 'use': 'sig', 'n': "uGbXWiK3dQTyCbX5xdE4yCuYp0AF2d15Qq1JSXT_lx8CEcXb9RbDddl8jGDv-spi5qPa8qEHiK7FwV2KpRE983wGPnYsAm9BxLFb4YrLYcDFOIGULuk2FtrPS512Qea1bXASuvYXEpQNpGbnTGVsWXI9C-yjHztqyL2h8P6mlThPY9E9ue2fCqdgixfTFIF9Dm4SLHbphUS2iw7w1JgT69s7of9-I9l5lsJ9cozf1rxrXX4V1u_SotUuNB3Fp8oB4C1fLBEhSlMcUJirz1E8AziMCxS-VrRPDM-zfvpIJg3JljAh3PJHDiLu902v9w-Iplu1WyoB2aPfitxEhRN0Yw", 'e': 'AQAB', 'kid': 'test-key-2' }.freeze
@@ -13,8 +14,14 @@ LEEWAY = 60
13
14
  CLOCK = 1587592561 # Apr 22 2020 21:56:01 UTC
14
15
  CONTEXT = { algorithm: Auth0::Algorithm::HS256.secret(HMAC_SHARED_SECRET), leeway: LEEWAY, audience: 'tokens-test-123', issuer: 'https://tokens-test.auth0.com/', clock: CLOCK }.freeze
15
16
 
17
+ def build_id_token(payload = {})
18
+ default_payload = { iss: CONTEXT[:issuer], sub: 'user123', aud: CONTEXT[:audience], exp: CLOCK, iat: CLOCK }
19
+ JWT.encode(default_payload.merge(payload), HMAC_SHARED_SECRET, 'HS256')
20
+ end
21
+
16
22
  describe Auth0::Mixins::Validation::IdTokenValidator do
17
23
  subject { @instance }
24
+ let (:minimal_id_token) { build_id_token }
18
25
 
19
26
  context 'instance' do
20
27
  it 'is expected respond to :validate' do
@@ -285,30 +292,73 @@ describe Auth0::Mixins::Validation::IdTokenValidator do
285
292
  expect { instance.validate(token) }.to raise_exception("Authentication Time (auth_time) claim in the ID token indicates that too much time has passed since the last end-user authentication. Current time \"#{clock}\" is after last auth at \"#{auth_time}\"")
286
293
  end
287
294
 
288
- it 'is expected not to raise an error when org_id exsist in the token, but not required' do
289
- token = 'eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3Rva2Vucy10ZXN0LmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHwxMjM0NTY3ODkiLCJhdWQiOlsidG9rZW5zLXRlc3QtMTIzIiwiZXh0ZXJuYWwtdGVzdC05OTkiXSwiZXhwIjoxNjE2NjE3ODgxLCJpYXQiOjE2MTY0NDUwODEsIm5vbmNlIjoiYTFiMmMzZDRlNSIsImF6cCI6InRva2Vucy10ZXN0LTEyMyIsImF1dGhfdGltZSI6MTYxNjUzMTQ4MSwib3JnX2lkIjoidGVzdE9yZyJ9.AOafUKUNgaxUXpSRYFCeJERcwrQZ4q2NZlutwGXnh9I'
290
- expect { @instance.validate(token) }.not_to raise_exception
291
- end
295
+ context 'Organization claims validation' do
296
+ it 'is expected not to raise an error when org_id exsist in the token, but not required' do
297
+ token = build_id_token org_id: 'org_123'
298
+ expect { @instance.validate(token) }.not_to raise_exception
299
+ end
292
300
 
293
- it 'is expected to raise an error with a missing but required organization' do
294
- token = 'eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3Rva2Vucy10ZXN0LmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHwxMjM0NTY3ODkiLCJhdWQiOlsidG9rZW5zLXRlc3QtMTIzIiwiZXh0ZXJuYWwtdGVzdC05OTkiXSwiZXhwIjoxNjE2NjE4MTg1LCJpYXQiOjE2MTY0NDUzODUsIm5vbmNlIjoiYTFiMmMzZDRlNSIsImF6cCI6InRva2Vucy10ZXN0LTEyMyIsImF1dGhfdGltZSI6MTYxNjUzMTc4NX0.UMo5pmgceXO9lIKzbk7X0ZhE5DOe0IP2LfMKdUj03zQ'
295
- instance = Auth0::Mixins::Validation::IdTokenValidator.new(CONTEXT.merge({ organization: 'a1b2c3d4e5' }))
301
+ it 'is expected not to raise an error when org_name exists in the token, but not required' do
302
+ token = build_id_token org_name: 'my-organization'
303
+ expect { @instance.validate(token) }.not_to raise_exception
304
+ end
296
305
 
297
- expect { instance.validate(token) }.to raise_exception('Organization Id (org_id) claim must be a string present in the ID token')
298
- end
306
+ it 'is expected to raise an error with a missing but required organization ID' do
307
+ instance = Auth0::Mixins::Validation::IdTokenValidator.new(CONTEXT.merge({ organization: 'org_1234' }))
308
+ expect { instance.validate(minimal_id_token) }.to raise_exception('Organization Id (org_id) claim must be a string present in the ID token')
309
+ end
299
310
 
300
- it 'is expected to raise an error with an invalid organization' do
301
- token = 'eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3Rva2Vucy10ZXN0LmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHwxMjM0NTY3ODkiLCJhdWQiOlsidG9rZW5zLXRlc3QtMTIzIiwiZXh0ZXJuYWwtdGVzdC05OTkiXSwiZXhwIjoxNjE2NjE3ODgxLCJpYXQiOjE2MTY0NDUwODEsIm5vbmNlIjoiYTFiMmMzZDRlNSIsImF6cCI6InRva2Vucy10ZXN0LTEyMyIsImF1dGhfdGltZSI6MTYxNjUzMTQ4MSwib3JnX2lkIjoidGVzdE9yZyJ9.AOafUKUNgaxUXpSRYFCeJERcwrQZ4q2NZlutwGXnh9I'
302
- instance = Auth0::Mixins::Validation::IdTokenValidator.new(CONTEXT.merge({ organization: 'a1b2c3d4e5' }))
311
+ it 'is expected to raise an error with a missing but required organization name' do
312
+ instance = Auth0::Mixins::Validation::IdTokenValidator.new(CONTEXT.merge({ organization: 'my-organization' }))
313
+ expect { instance.validate(minimal_id_token) }.to raise_exception('Organization Name (org_name) claim must be a string present in the ID token')
314
+ end
303
315
 
304
- expect { instance.validate(token) }.to raise_exception('Organization Id (org_id) claim value mismatch in the ID token; expected "a1b2c3d4e5", found "testOrg"')
305
- end
316
+ it 'is expected to raise an error with an invalid organization ID' do
317
+ token = build_id_token org_id: 'org_1234'
318
+ instance = Auth0::Mixins::Validation::IdTokenValidator.new(CONTEXT.merge({ organization: 'org_5678' }))
319
+
320
+ expect { instance.validate(token) }.to raise_exception('Organization Id (org_id) claim value mismatch in the ID token; expected "org_5678", found "org_1234"')
321
+ end
322
+
323
+ it 'is expected to raise an error with an invalid organization name' do
324
+ token = build_id_token org_name: 'another-organization'
325
+ instance = Auth0::Mixins::Validation::IdTokenValidator.new(CONTEXT.merge({ organization: 'my-organization' }))
326
+
327
+ expect { instance.validate(token) }.to raise_exception('Organization Name (org_name) claim value mismatch in the ID token; expected "my-organization", found "another-organization"')
328
+ end
329
+
330
+ it 'is expected to NOT raise an error with a valid organization ID' do
331
+ token = build_id_token org_id: 'org_1234'
332
+ instance = Auth0::Mixins::Validation::IdTokenValidator.new(CONTEXT.merge({ organization: 'org_1234' }))
333
+
334
+ expect { instance.validate(token) }.not_to raise_exception
335
+ end
336
+
337
+ it 'is expected to NOT raise an error with a valid organization name' do
338
+ token = build_id_token org_name: 'my-organization'
339
+ instance = Auth0::Mixins::Validation::IdTokenValidator.new(CONTEXT.merge({ organization: 'my-organization' }))
340
+
341
+ expect { instance.validate(token) }.not_to raise_exception
342
+ end
343
+
344
+ it 'is expected to NOT raise an error with organization name in different casing' do
345
+ token = build_id_token org_name: 'MY-ORGANIZATION'
346
+ instance = Auth0::Mixins::Validation::IdTokenValidator.new(CONTEXT.merge({ organization: 'my-organization' }))
347
+
348
+ expect { instance.validate(token) }.not_to raise_exception
349
+ end
306
350
 
307
- it 'is expected to NOT raise an error with a valid organization' do
308
- token = 'eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3Rva2Vucy10ZXN0LmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHwxMjM0NTY3ODkiLCJhdWQiOlsidG9rZW5zLXRlc3QtMTIzIiwiZXh0ZXJuYWwtdGVzdC05OTkiXSwiZXhwIjoxNjE2NjE3ODgxLCJpYXQiOjE2MTY0NDUwODEsIm5vbmNlIjoiYTFiMmMzZDRlNSIsImF6cCI6InRva2Vucy10ZXN0LTEyMyIsImF1dGhfdGltZSI6MTYxNjUzMTQ4MSwib3JnX2lkIjoidGVzdE9yZyJ9.AOafUKUNgaxUXpSRYFCeJERcwrQZ4q2NZlutwGXnh9I'
309
- instance = Auth0::Mixins::Validation::IdTokenValidator.new(CONTEXT.merge({ organization: 'testOrg' }))
351
+ it 'validates org_id when both claims are present in the token' do
352
+ token = build_id_token org_name: 'my-organization', org_id: 'org_1234'
353
+ instance = Auth0::Mixins::Validation::IdTokenValidator.new(CONTEXT.merge({ organization: 'org_1234' }))
354
+ expect { instance.validate(token) }.not_to raise_exception
355
+ end
310
356
 
311
- expect { instance.validate(token) }.not_to raise_exception
357
+ it 'validates org_name when both claims are present in the token' do
358
+ token = build_id_token org_name: 'my-organization', org_id: 'org_1234'
359
+ instance = Auth0::Mixins::Validation::IdTokenValidator.new(CONTEXT.merge({ organization: 'my-organization' }))
360
+ expect { instance.validate(token) }.not_to raise_exception
361
+ end
312
362
  end
313
363
  end
314
364
  end
@@ -15,5 +15,6 @@ class DummyClassForTokens
15
15
  @token_expires_at = config[:token_expires_at]
16
16
  @client_assertion_signing_key = config[:client_assertion_signing_key]
17
17
  @client_assertion_signing_alg = config[:client_assertion_signing_alg] || 'RS256'
18
+ @headers ||= {}
18
19
  end
19
20
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: auth0
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.12.0
4
+ version: 5.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Auth0
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2023-03-13 00:00:00.000000000 Z
14
+ date: 2023-07-13 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rest-client
@@ -33,14 +33,14 @@ dependencies:
33
33
  requirements:
34
34
  - - "~>"
35
35
  - !ruby/object:Gem::Version
36
- version: '2.5'
36
+ version: '2.7'
37
37
  type: :runtime
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
40
40
  requirements:
41
41
  - - "~>"
42
42
  - !ruby/object:Gem::Version
43
- version: '2.5'
43
+ version: '2.7'
44
44
  - !ruby/object:Gem::Dependency
45
45
  name: zache
46
46
  requirement: !ruby/object:Gem::Requirement
@@ -237,9 +237,9 @@ files:
237
237
  - ".env.example"
238
238
  - ".gemrelease"
239
239
  - ".github/CODEOWNERS"
240
+ - ".github/ISSUE_TEMPLATE/Bug Report.yml"
241
+ - ".github/ISSUE_TEMPLATE/Feature Request.yml"
240
242
  - ".github/ISSUE_TEMPLATE/config.yml"
241
- - ".github/ISSUE_TEMPLATE/feature_request.md"
242
- - ".github/ISSUE_TEMPLATE/report_a_bug.md"
243
243
  - ".github/PULL_REQUEST_TEMPLATE.md"
244
244
  - ".github/dependabot.yml"
245
245
  - ".github/stale.yml"
@@ -248,6 +248,7 @@ files:
248
248
  - ".rspec"
249
249
  - ".rubocop.yml"
250
250
  - ".rubocop_todo.yml"
251
+ - ".semgrepignore"
251
252
  - ".shiprc"
252
253
  - CHANGELOG.md
253
254
  - CODE_OF_CONDUCT.md
@@ -614,7 +615,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
614
615
  - !ruby/object:Gem::Version
615
616
  version: '0'
616
617
  requirements: []
617
- rubygems_version: 3.3.26
618
+ rubygems_version: 3.4.10
618
619
  signing_key:
619
620
  specification_version: 4
620
621
  summary: Auth0 API Client
@@ -1,39 +0,0 @@
1
- ---
2
- name: Feature request
3
- about: Suggest an idea or a feature for this project
4
- title: ''
5
- labels: feature request
6
- assignees: ''
7
- ---
8
-
9
- <!--
10
- **Please do not report security vulnerabilities here**. The Responsible Disclosure Program (https://auth0.com/whitehat) details the procedure for disclosing security issues.
11
-
12
- Thank you in advance for helping us to improve this library! Your attention to detail here is greatly appreciated and will help us respond as quickly as possible. For general support or usage questions, use the Auth0 Community (https://community.auth0.com/) or Auth0 Support (https://support.auth0.com/). Finally, to avoid duplicates, please search existing Issues before submitting one here.
13
-
14
- By submitting an Issue to this repository, you agree to the terms within the Auth0 Code of Conduct (https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md).
15
- -->
16
-
17
- ### Describe the problem you'd like to have solved
18
-
19
- <!--
20
- > A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
21
- -->
22
-
23
- ### Describe the ideal solution
24
-
25
- <!--
26
- > A clear and concise description of what you want to happen.
27
- -->
28
-
29
- ## Alternatives and current work-arounds
30
-
31
- <!--
32
- > A clear and concise description of any alternatives you've considered or any work-arounds that are currently in place.
33
- -->
34
-
35
- ### Additional information, if any
36
-
37
- <!--
38
- > Add any other context or screenshots about the feature request here.
39
- -->
@@ -1,55 +0,0 @@
1
- ---
2
- name: Report a bug
3
- about: Have you found a bug or issue? Create a bug report for this SDK
4
- title: ''
5
- labels: bug report
6
- assignees: ''
7
- ---
8
-
9
- <!--
10
- **Please do not report security vulnerabilities here**. The Responsible Disclosure Program (https://auth0.com/whitehat) details the procedure for disclosing security issues.
11
-
12
- Thank you in advance for helping us to improve this library! Please read through the template below and answer all relevant questions. Your additional work here is greatly appreciated and will help us respond as quickly as possible. For general support or usage questions, use the Auth0 Community (https://community.auth0.com/) or Auth0 Support (https://support.auth0.com/). Finally, to avoid duplicates, please search existing Issues before submitting one here.
13
-
14
- By submitting an Issue to this repository, you agree to the terms within the Auth0 Code of Conduct (https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md).
15
- -->
16
-
17
- ### Describe the problem
18
-
19
- <!--
20
- > Provide a clear and concise description of the issue
21
- -->
22
-
23
- ### What was the expected behavior?
24
-
25
- <!--
26
- > Tell us about the behavior you expected to see
27
- -->
28
-
29
- ### Reproduction
30
- <!--
31
- > Detail the steps taken to reproduce this error, and whether this issue can be reproduced consistently or if it is intermittent.
32
- > **Note**: If clear, reproducable steps or the smallest sample app demonstrating misbehavior cannot be provided, we may not be able to follow up on this bug report.
33
-
34
- > Where possible, please include:
35
- >
36
- > - The smallest possible sample app that reproduces the undesirable behavior
37
- > - Log files (redact/remove sensitive information)
38
- > - Application settings (redact/remove sensitive information)
39
- > - Screenshots
40
- -->
41
-
42
- - Step 1..
43
- - Step 2..
44
- - ...
45
-
46
- ### Environment
47
-
48
- <!--
49
- > Please provide the following:
50
- -->
51
-
52
- - **Version of this library used:**
53
- - **Which framework are you using, if applicable:**
54
- - **Other modules/plugins/libraries that might be involved:**
55
- - **Any other relevant information you think would be useful:**