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 +4 -4
- data/.circleci/config.yml +3 -2
- data/.devcontainer/Dockerfile +1 -1
- data/.github/ISSUE_TEMPLATE/Bug Report.yml +67 -0
- data/.github/ISSUE_TEMPLATE/Feature Request.yml +53 -0
- data/.github/ISSUE_TEMPLATE/config.yml +1 -1
- data/.semgrepignore +6 -0
- data/CHANGELOG.md +15 -0
- data/EXAMPLES.md +10 -8
- data/Gemfile.lock +51 -46
- data/auth0.gemspec +1 -1
- data/examples/ruby-api/Gemfile.lock +1 -1
- data/lib/auth0/api/authentication_endpoints.rb +37 -0
- data/lib/auth0/mixins/httpproxy.rb +5 -2
- data/lib/auth0/mixins/validation.rb +19 -6
- data/lib/auth0/version.rb +1 -1
- data/spec/lib/auth0/api/authentication_endpoints_spec.rb +90 -0
- data/spec/lib/auth0/mixins/httpproxy_spec.rb +38 -77
- data/spec/lib/auth0/mixins/validation_spec.rb +68 -18
- data/spec/support/dummy_class_for_tokens.rb +1 -0
- metadata +8 -7
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -39
- data/.github/ISSUE_TEMPLATE/report_a_bug.md +0 -55
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b34c959171acbebc0ef4f851232de93af1d70318bb762243903d5269275843fa
|
4
|
+
data.tar.gz: 2856980051e6dec9ede6569c185516ffd08d2dfa4918a96a5fc4d0f96e17d44c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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: ["
|
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:
|
data/.devcontainer/Dockerfile
CHANGED
@@ -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.
|
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
|
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
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: "{
|
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: "{
|
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`
|
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
|
173
|
+
### Organization claim validation
|
174
174
|
|
175
|
-
If an org_id claim is present in the
|
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.
|
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.
|
4
|
+
auth0 (5.14.0)
|
5
5
|
addressable (~> 2.8)
|
6
|
-
jwt (~> 2.
|
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.
|
15
|
-
actionview (= 7.0.
|
16
|
-
activesupport (= 7.0.
|
17
|
-
rack (~> 2.0, >= 2.2.
|
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.
|
22
|
-
activesupport (= 7.0.
|
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.
|
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.
|
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.
|
65
|
+
i18n (1.14.1)
|
66
66
|
concurrent-ruby (~> 1.0)
|
67
67
|
io-console (0.6.0)
|
68
|
-
irb (1.
|
69
|
-
reline (>= 0.3.
|
68
|
+
irb (1.7.3)
|
69
|
+
reline (>= 0.3.6)
|
70
70
|
json (2.6.3)
|
71
|
-
jwt (2.7.
|
72
|
-
|
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.
|
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.
|
80
|
+
minitest (5.18.1)
|
80
81
|
multi_json (1.15.0)
|
81
82
|
netrc (0.11.0)
|
82
|
-
nokogiri (1.
|
83
|
+
nokogiri (1.15.3-x86_64-linux)
|
83
84
|
racc (~> 1.4)
|
84
|
-
parallel (1.
|
85
|
-
parser (3.2.
|
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.
|
91
|
-
racc (1.
|
92
|
-
rack (2.2.
|
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.
|
96
|
-
activesupport (>=
|
97
|
+
rails-dom-testing (2.1.1)
|
98
|
+
activesupport (>= 5.0.0)
|
99
|
+
minitest
|
97
100
|
nokogiri (>= 1.6)
|
98
|
-
rails-html-sanitizer (1.
|
99
|
-
loofah (~> 2.
|
100
|
-
|
101
|
-
|
102
|
-
|
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.
|
110
|
-
reline (0.3.
|
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.
|
127
|
+
rspec-core (3.12.2)
|
124
128
|
rspec-support (~> 3.12.0)
|
125
|
-
rspec-expectations (3.12.
|
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.
|
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.
|
132
|
-
rubocop (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.
|
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.
|
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.
|
147
|
+
rubocop-ast (1.29.0)
|
143
148
|
parser (>= 3.2.1.0)
|
144
|
-
rubocop-rails (2.
|
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.
|
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.
|
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.
|
177
|
-
zeitwerk (2.6.
|
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.
|
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.
|
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'
|
@@ -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.
|
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
|
-
|
192
|
-
|
193
|
-
|
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
|
-
|
196
|
-
|
197
|
-
|
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
@@ -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
|
-
|
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"
|
257
|
-
expect(RestClient::Request).to receive(:execute).with(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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
|
-
|
289
|
-
token
|
290
|
-
|
291
|
-
|
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
|
-
|
294
|
-
|
295
|
-
|
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
|
-
|
298
|
-
|
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
|
-
|
301
|
-
|
302
|
-
|
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
|
-
|
305
|
-
|
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
|
-
|
308
|
-
|
309
|
-
|
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
|
-
|
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
|
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.
|
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-
|
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.
|
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.
|
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.
|
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:**
|