rodauth-oauth 1.0.0.pre.beta1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/MIGRATION-GUIDE-v1.md +12 -0
- data/README.md +30 -15
- data/doc/release_notes/0_1_0.md +2 -2
- data/doc/release_notes/0_2_0.md +1 -1
- data/doc/release_notes/0_3_0.md +1 -1
- data/doc/release_notes/0_5_0.md +2 -2
- data/doc/release_notes/0_8_0.md +2 -2
- data/doc/release_notes/1_0_0.md +79 -0
- data/lib/generators/rodauth/oauth/templates/app/views/rodauth/authorize.html.erb +19 -7
- data/lib/generators/rodauth/oauth/templates/app/views/rodauth/authorize_error.erb +10 -0
- data/lib/generators/rodauth/oauth/templates/db/migrate/create_rodauth_oauth.rb +54 -43
- data/lib/rodauth/features/oauth_application_management.rb +2 -2
- data/lib/rodauth/features/oauth_authorization_code_grant.rb +31 -7
- data/lib/rodauth/features/oauth_authorize_base.rb +32 -10
- data/lib/rodauth/features/oauth_base.rb +36 -16
- data/lib/rodauth/features/oauth_dynamic_client_registration.rb +7 -4
- data/lib/rodauth/features/oauth_implicit_grant.rb +16 -5
- data/lib/rodauth/features/oauth_jwt.rb +3 -3
- data/lib/rodauth/features/oauth_jwt_base.rb +29 -6
- data/lib/rodauth/features/oauth_jwt_bearer_grant.rb +7 -4
- data/lib/rodauth/features/oauth_jwt_secured_authorization_request.rb +64 -10
- data/lib/rodauth/features/oauth_resource_indicators.rb +0 -4
- data/lib/rodauth/features/oauth_resource_server.rb +3 -3
- data/lib/rodauth/features/oauth_saml_bearer_grant.rb +2 -0
- data/lib/rodauth/features/oidc.rb +263 -187
- data/lib/rodauth/features/oidc_dynamic_client_registration.rb +65 -25
- data/lib/rodauth/features/oidc_rp_initiated_logout.rb +118 -0
- data/lib/rodauth/oauth/http_extensions.rb +15 -2
- data/lib/rodauth/oauth/ttl_store.rb +2 -0
- data/lib/rodauth/oauth/version.rb +1 -1
- data/locales/en.yml +4 -1
- data/locales/pt.yml +4 -1
- data/templates/authorize.str +17 -10
- data/templates/authorize_error.str +12 -0
- metadata +15 -12
- data/doc/release_notes/1_0_0_beta1.md +0 -38
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8288f66a0f7dd5400b60d2508a0247aefd37f1aa73322c19bf3b744d3e8b1ace
|
4
|
+
data.tar.gz: 6f2c333c4c2c3a4f92544f939ac1112d31c78a56779f22234bb7e7ce95105931
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 612b2651b4c29f98427a5113b403ce214d3d8513cd740977a834f5efdbb4aac46fc83f74f54a2b925836e6860cf008226232956ee5dc975f08cd88215aa198f2
|
7
|
+
data.tar.gz: 2940dd71610ea52f3c18ea942f0a2fd4122028f9c1c0bce5986506501c24c5603d981406e997b662e68986411244db442747e453ff65a49431551d56d8da0eac
|
data/CHANGELOG.md
CHANGED
@@ -1 +1 @@
|
|
1
|
-
See the Release Notes under https://gitlab.com/
|
1
|
+
See the Release Notes under https://gitlab.com/os85/rodauth-oauth/-/tree/master/doc/release_notes
|
data/MIGRATION-GUIDE-v1.md
CHANGED
@@ -90,6 +90,10 @@ The client secret is hashed (with bcrypt) before being stored, by default. While
|
|
90
90
|
oauth_applications_client_secret_hash_column nil
|
91
91
|
```
|
92
92
|
|
93
|
+
## oauth applications: oauth_applications_homepage_url_column no longer required
|
94
|
+
|
95
|
+
The homepage url is no longer considered a require prooperty of an OAuth client application.
|
96
|
+
|
93
97
|
## oauth grants: access token and refresh token hashed by default
|
94
98
|
|
95
99
|
access token and refresh token columns are now hashed by default, and point to the same column as the main counterpart:
|
@@ -205,6 +209,14 @@ JWKs URI endpoint has been moved to its plugin. If you require this functionalit
|
|
205
209
|
enable :oauth_jwt, :oauth_jwt_jwks
|
206
210
|
```
|
207
211
|
|
212
|
+
## OIDC RP-initiated logout segregated in its plugin
|
213
|
+
|
214
|
+
It was previously being loaded in the `:oidc` plugin by default. If you require this funtionality, enable the plugin:
|
215
|
+
|
216
|
+
```ruby
|
217
|
+
enable :oidc_rp_initiated_logout
|
218
|
+
```
|
219
|
+
|
208
220
|
## routing functions renamed
|
209
221
|
|
210
222
|
Previously, loading well-known routes, the oauth server metadata, or oauth application/tokens (now grants) management dashboard implied calling a function on roda to load those routes. These have been renamed:
|
data/README.md
CHANGED
@@ -1,11 +1,25 @@
|
|
1
1
|
# Rodauth::Oauth
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/rodauth-oauth.svg)](http://rubygems.org/gems/rodauth-oauth)
|
4
|
-
[![pipeline status](https://gitlab.com/
|
5
|
-
[![coverage report](https://gitlab.com/
|
4
|
+
[![pipeline status](https://gitlab.com/os85/rodauth-oauth/badges/master/pipeline.svg)](https://gitlab.com/os85/rodauth-oauth/pipelines?page=1&scope=all&ref=master)
|
5
|
+
[![coverage report](https://gitlab.com/os85/rodauth-oauth/badges/master/coverage.svg?job=coverage)](https://os85.gitlab.io/rodauth-oauth/coverage/#_AllFiles)
|
6
6
|
|
7
7
|
This is an extension to the `rodauth` gem which implements the [OAuth 2.0 framework](https://tools.ietf.org/html/rfc6749) for an authorization server.
|
8
8
|
|
9
|
+
## Certification
|
10
|
+
[<img width="184" height="96" align="right" src="/openid-certified.jpg" alt="OpenID Certification">](https://openid.net/certification/)
|
11
|
+
|
12
|
+
`rodauth-oauth` is [certified](https://openid.net/certification/) for the following profiles of the OpenID Connect™ protocol:
|
13
|
+
|
14
|
+
* Basic OP
|
15
|
+
* Implicit OP
|
16
|
+
* Hybrid OP
|
17
|
+
* Config OP
|
18
|
+
* Dynamic OP
|
19
|
+
* Form Post OP
|
20
|
+
|
21
|
+
(it also passes the conformance tests for the RP-Initiated Logout OP).
|
22
|
+
|
9
23
|
## Features
|
10
24
|
|
11
25
|
This gem implements the following RFCs and features of OAuth:
|
@@ -35,11 +49,12 @@ This gem implements the following RFCs and features of OAuth:
|
|
35
49
|
|
36
50
|
It also implements the [OpenID Connect layer](https://openid.net/connect/) (via the `openid` feature) on top of the OAuth features it provides, including:
|
37
51
|
|
38
|
-
*
|
39
|
-
* [OpenID Connect
|
40
|
-
* [OpenID
|
41
|
-
* [OpenID
|
42
|
-
* [
|
52
|
+
* `oidc`
|
53
|
+
* [OpenID Connect Core](https://openid.net/specs/openid-connect-core-1_0.html);
|
54
|
+
* [OpenID Connect Discovery](https://openid.net/specs/openid-connect-discovery-1_0-29.html);
|
55
|
+
* [OpenID Multiple Response Types](https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html);
|
56
|
+
* `oidc_dynamic_client_registration` - [OpenID Connect Dynamic Client Registration](https://openid.net/specs/openid-connect-registration-1_0.html);
|
57
|
+
* `oidc_rp_initiated_logout` - [RP Initiated Logout](https://openid.net/specs/openid-connect-rpinitiated-1_0.html);
|
43
58
|
|
44
59
|
This gem supports also rails (through [rodauth-rails]((https://github.com/janko/rodauth-rails))).
|
45
60
|
|
@@ -64,10 +79,10 @@ Or install it yourself as:
|
|
64
79
|
## Resources
|
65
80
|
| | |
|
66
81
|
| ------------- | ----------------------------------------------------------- |
|
67
|
-
| Website | https://
|
68
|
-
| Documentation | https://
|
69
|
-
| Wiki | https://gitlab.com/
|
70
|
-
| CI | https://gitlab.com/
|
82
|
+
| Website | https://os85.gitlab.io/rodauth-oauth/ |
|
83
|
+
| Documentation | https://os85.gitlab.io/rodauth-oauth/rdoc/ |
|
84
|
+
| Wiki | https://gitlab.com/os85/rodauth-oauth/wikis/home |
|
85
|
+
| CI | https://gitlab.com/os85/rodauth-oauth/pipelines |
|
71
86
|
|
72
87
|
## Articles
|
73
88
|
|
@@ -131,12 +146,12 @@ end
|
|
131
146
|
|
132
147
|
### Example (TL;DR)
|
133
148
|
|
134
|
-
Just [check our example applications](https://gitlab.com/
|
149
|
+
Just [check our example applications](https://gitlab.com/os85/rodauth-oauth/-/tree/master/examples/).
|
135
150
|
|
136
151
|
|
137
152
|
### Database migrations
|
138
153
|
|
139
|
-
You have to generate database tables for accounts, oauth applications, grants and tokens. In order for you to hit the ground running, [here's a set of migrations (using `sequel`) to generate the needed tables](https://gitlab.com/
|
154
|
+
You have to generate database tables for accounts, oauth applications, grants and tokens. In order for you to hit the ground running, [here's a set of migrations (using `sequel`) to generate the needed tables](https://gitlab.com/os85/rodauth-oauth/-/tree/master/test/migrate) (omit the first 2 if you already have account tables, and [follow recommendations from rodauth accordingly](https://github.com/jeremyevans/rodauth)).
|
140
155
|
|
141
156
|
You can change column names or even use existing tables, however, be aware that you'll have to define new column accessors at the `rodauth` plugin declaration level. Let's say, for instance, you'd like to change the `oauth_grants` table name to `access_grants`, and it's `code` column to `authorization_code`; then, you'd have to do the following:
|
142
157
|
|
@@ -269,7 +284,7 @@ end
|
|
269
284
|
|
270
285
|
`rodauth-oauth` supports translating all user-facing text found in all pages and forms, by integrating with [rodauth-i18n](https://github.com/janko/rodauth-i18n). Just set it up in your application and `rodauth` configuration.
|
271
286
|
|
272
|
-
Default translations shipping with `rodauth-oauth` can be found [in this directory](https://gitlab.com/
|
287
|
+
Default translations shipping with `rodauth-oauth` can be found [in this directory](https://gitlab.com/os85/rodauth-oauth/-/tree/master/locales). If they're not available for the languages you'd like to support, consider getting them translated from the english text, and contributing them to this repository via a Merge Request.
|
273
288
|
|
274
289
|
(This feature is available since `v0.7`.)
|
275
290
|
|
@@ -288,4 +303,4 @@ After checking out the repo, run `bundle install` to install dependencies. Then,
|
|
288
303
|
|
289
304
|
## Contributing
|
290
305
|
|
291
|
-
Bug reports and pull requests are welcome on Gitlab at https://gitlab.com/
|
306
|
+
Bug reports and pull requests are welcome on Gitlab at https://gitlab.com/os85/rodauth-oauth.
|
data/doc/release_notes/0_1_0.md
CHANGED
@@ -12,9 +12,9 @@ plugin :rodauth do
|
|
12
12
|
end
|
13
13
|
```
|
14
14
|
|
15
|
-
For more info about integrating it, [check the wiki](https://gitlab.com/
|
15
|
+
For more info about integrating it, [check the wiki](https://gitlab.com/os85/rodauth-oauth/-/wikis/home#openid-connect-since-v01).
|
16
16
|
|
17
|
-
It supports omniauth openID integrations out-of-the-box, [check the OpenID example, which integrates with omniauth_openid_connect](https://gitlab.com/
|
17
|
+
It supports omniauth openID integrations out-of-the-box, [check the OpenID example, which integrates with omniauth_openid_connect](https://gitlab.com/os85/rodauth-oauth/-/tree/master/examples).
|
18
18
|
|
19
19
|
#### Improvements
|
20
20
|
|
data/doc/release_notes/0_2_0.md
CHANGED
@@ -12,7 +12,7 @@ plugin :rodauth do
|
|
12
12
|
end
|
13
13
|
```
|
14
14
|
|
15
|
-
For more info about integrating it, [check the wiki](https://gitlab.com/
|
15
|
+
For more info about integrating it, [check the wiki](https://gitlab.com/os85/rodauth-oauth/-/wikis/SAML-Assertion-Access-Tokens).
|
16
16
|
|
17
17
|
##### Supporting rotating keys
|
18
18
|
|
data/doc/release_notes/0_3_0.md
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
#### Improvements
|
8
8
|
|
9
9
|
|
10
|
-
* Support for the OIDC authorize [`prompt` parameter](https://openid.net/specs/openid-connect-core-1_0.html) (sectionn 3.1.2.1). It supports the `none`, `login` and `consent` out-of-the-box, while providing support for `select-account` when paired with [rodauth-select-account, a rodauth feature to handle multiple accounts in the same session](https://gitlab.com/
|
10
|
+
* Support for the OIDC authorize [`prompt` parameter](https://openid.net/specs/openid-connect-core-1_0.html) (sectionn 3.1.2.1). It supports the `none`, `login` and `consent` out-of-the-box, while providing support for `select-account` when paired with [rodauth-select-account, a rodauth feature to handle multiple accounts in the same session](https://gitlab.com/os85/rodauth-select-account).
|
11
11
|
|
12
12
|
* Refresh Tokens are now expirable. The refresh token expiration period is governed by the `oauth_refresh_token_expires_in` option (default: 1 year), and is the period for which a refresh token can be used after its respective access token expired.
|
13
13
|
|
data/doc/release_notes/0_5_0.md
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
#### RP-Initiated Logout
|
4
4
|
|
5
|
-
The `:oidc` plugin can now do [RP-Initiated Logout](https://gitlab.com/
|
5
|
+
The `:oidc` plugin can now do [RP-Initiated Logout](https://gitlab.com/os85/rodauth-oauth/-/wikis/RP-Initiated-Logout). It's disabled by default, so read the docs to learn how to enable it.
|
6
6
|
|
7
7
|
#### Security
|
8
8
|
|
9
9
|
The `:oauth_jwt` (and by association, `:oidc`) plugin(s) verifies the claims of used JWT tokens. This is a **very important security fix**, as without it, there is no protection against replay attacks and other types of misuse of the JWT token.
|
10
10
|
|
11
|
-
A new auth method, `generate_jti(claims)`, was [added to the list of oauth_jwt plugin options](https://gitlab.com/
|
11
|
+
A new auth method, `generate_jti(claims)`, was [added to the list of oauth_jwt plugin options](https://gitlab.com/os85/rodauth-oauth/-/wikis/JWT-Access-Tokens#rodauth-options). By default, it'll hash the `aud` and `iat` claims together, but you can overwrite how this is done.
|
data/doc/release_notes/0_8_0.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
* Device code grant
|
6
6
|
|
7
|
-
`rodauth-oauth` now supports the [Device code grant RFC](https://gitlab.com/
|
7
|
+
`rodauth-oauth` now supports the [Device code grant RFC](https://gitlab.com/os85/rodauth-oauth/-/wikis/Device-Grant), via the `oauth_device_grant` feature.
|
8
8
|
|
9
9
|
* OAuth Tokens Management
|
10
10
|
|
@@ -12,7 +12,7 @@ An OAuth Tokens Management Dashboard is now provided (via `r.oauth_tokens` call
|
|
12
12
|
|
13
13
|
* Assertion Framework (+ SAML and JWT Bearer Grant)
|
14
14
|
|
15
|
-
A new plugin, `oauth_assertion_base`, was introduced to provide a baseline for implementing custom Bearer Assertion as per the [OAuth Client Assertion Framework RFC](https://gitlab.com/
|
15
|
+
A new plugin, `oauth_assertion_base`, was introduced to provide a baseline for implementing custom Bearer Assertion as per the [OAuth Client Assertion Framework RFC](https://gitlab.com/os85/rodauth-oauth/-/wikis/Client-Assertion-Framework). This in turn was used to refactor and reintroduce the [oauth_saml_bearer_grant](https://gitlab.com/os85/rodauth-oauth/-/wikis/SAML-Bearer-Assertions) and the [oauth_jwt_bearer_grant](https://gitlab.com/os85/rodauth-oauth/-/wikis/JWT-Bearer-Assertions) features, which implement the respective and most recent version of the assertion RFCs.
|
16
16
|
|
17
17
|
(as a result, `oauth_saml` was removed, which implemented a very old draft version of the SAML Bearer spec).
|
18
18
|
|
@@ -0,0 +1,79 @@
|
|
1
|
+
## 1.0.0 (15/12/2022)
|
2
|
+
|
3
|
+
## Highlights
|
4
|
+
|
5
|
+
rodauth-oauth is now [OpenID certified](https://openid.net/certification/) for the following certification profiles:
|
6
|
+
|
7
|
+
* Basic OP
|
8
|
+
* Implicit OP
|
9
|
+
* Hybrid OP
|
10
|
+
* Config OP
|
11
|
+
* Dynamic OP
|
12
|
+
* Form Post OP
|
13
|
+
|
14
|
+
and passes the conformance tests for RP-Initiated Logout OP.
|
15
|
+
|
16
|
+
The OIDC server used to run the test can be found [here](https://gitlab.com/os85/rodauth-oauth/-/blob/master/examples/oidc/authentication_server.rb) and deployed [here](https://rodauth-oauth-oidc.onrender.com).
|
17
|
+
|
18
|
+
### Breaking changes
|
19
|
+
|
20
|
+
The full description of breaking changes, and suggestions on how to make the migration smoother, can be found in the [migration guide](https://gitlab.com/os85/rodauth-oauth/-/blob/6465b8522a78cf0037a55d3d4b81f68f7811be68/MIGRATION-GUIDE-v1.md).
|
21
|
+
|
22
|
+
A short list of the main highlights:
|
23
|
+
|
24
|
+
|
25
|
+
* Ruby 2.5 or higher is required.
|
26
|
+
* `oauth_http_mac` feature removed.
|
27
|
+
* `oauth_tokens` table (and resource) were removed (only `oauth_applications` and `oauth_grants`, access and refresh tokens are now properties of the latter).
|
28
|
+
* access and refresh tokens hashed by default when stored in the database.
|
29
|
+
* default oauth response mode is `"form_post"`.
|
30
|
+
* oauth specific features require explicit enablement of respective features (no more `enable :oauth`)
|
31
|
+
* refresh token policy is "rotation" by default
|
32
|
+
* homepage url is no longer a client application required property.
|
33
|
+
* OIDC RP-initiated logout extracted into `oidc_rp_initiated_logout` feature.
|
34
|
+
|
35
|
+
### Features
|
36
|
+
|
37
|
+
The following helpers are exposed in the `rodauth` object:
|
38
|
+
|
39
|
+
* `current_oauth_account` - returns the dataset row for the `rodauth` account associated to an oauth access token in the "authorization" header.
|
40
|
+
* `current_oauth_application` - returns the dataset row for the oauth application associated to an oauth access token in the "authorization" header.
|
41
|
+
|
42
|
+
When used in `rails` via `rodauth-rails`, both are exposed directly as controller helpers.
|
43
|
+
|
44
|
+
#### `oauth_resource_server` plugin
|
45
|
+
|
46
|
+
This plugin can be used as a convenience when configuring resource servers.
|
47
|
+
|
48
|
+
#### JAR support for request_uri query param
|
49
|
+
|
50
|
+
The `oauth_jwt_secured_authorization_request` plugin now supports a `request_uri` query param as well.
|
51
|
+
|
52
|
+
#### OIDC features
|
53
|
+
|
54
|
+
* The `oidc` plugin supports [essential claims](https://openid.net/specs/openid-connect-core-1_0.html#ClaimsParameter), via the `claims` authorization request query parameter.
|
55
|
+
* id token built with `"c_hash"` and `"at_hash"` claims when they should.
|
56
|
+
|
57
|
+
### Improvements
|
58
|
+
|
59
|
+
* `:oauth_introspect` plugin: OAuth introspection endpoint exposes the token's `"username"` claim.
|
60
|
+
* endpoint client authentication supports "client credentials grant" access tokens.
|
61
|
+
* `acr_values_supported` exposed in the openid configuration.
|
62
|
+
* `oauth_request_object_signing_alg_allow_none` enables `"none"` as an accepted request object signing alg when `true` (`false` by default).
|
63
|
+
* OIDC `offline_access` supported.
|
64
|
+
|
65
|
+
### Bugfixes
|
66
|
+
|
67
|
+
* fixed `oidc` calculation of `"auth_time"` claim.
|
68
|
+
* JWT: "sub" is now always a string.
|
69
|
+
* `response_type` is now an authorization request required parameter (as per the RFC).
|
70
|
+
* `state` is now passed along when redirecting from authorization requests with `error`;
|
71
|
+
* access token can now be read from POST body or GET query params (as per the RFC).
|
72
|
+
* id token no longer shipping with claims with `null` value;
|
73
|
+
* id token no longer encoding claims by default (only when `response_type=id_token`, as per the RFC).
|
74
|
+
* support "JWT without kid" when doing jwt decoding for JWT tokens not generated in the provider (such as request objects).
|
75
|
+
* Set `iss` and `aud` claims in the Userinfo JWT response.
|
76
|
+
* Make sure errors are also delivered via form POST, when `response_mode=form_post`.
|
77
|
+
* Authorization request now shows an error page when `response_type` or `client_id` are missing, or `redirect_uri` is missing or invalid; a new `"authorize_error"` template is invoked in such cases.
|
78
|
+
* oidc: nonce present in id token when using the "id_token token" response type.
|
79
|
+
* error parameter delivered in URL fragment when failing an implicit grant autorization request.
|
@@ -2,7 +2,9 @@
|
|
2
2
|
<% if rodauth.oauth_application[rodauth.oauth_applications_logo_uri_column] %>
|
3
3
|
<%= image_tag rodauth.oauth_application[rodauth.oauth_applications_logo_uri_column] %>
|
4
4
|
<% end %>
|
5
|
-
|
5
|
+
<% application_uri = rodauth.oauth_application[rodauth.oauth_applications_homepage_url_column] %>
|
6
|
+
<% application_name = application_uri ? link_to(rodauth.oauth_application[rodauth.oauth_applications_name_column], application_uri) : rodauth.oauth_application[rodauth.oauth_applications_name_column] %>
|
7
|
+
<p class="lead"><%= rodauth.authorize_page_lead(name: application_name).html_safe %></p>
|
6
8
|
|
7
9
|
<div class="list-group">
|
8
10
|
<% if rodauth.oauth_application[rodauth.oauth_applications_tos_uri_column] %>
|
@@ -26,10 +28,14 @@
|
|
26
28
|
<h1 class="display-6"><%= rodauth.oauth_grants_scopes_label %></h1>
|
27
29
|
|
28
30
|
<% rodauth.authorize_scopes.each do |scope| %>
|
29
|
-
|
30
|
-
<%=
|
31
|
-
|
32
|
-
|
31
|
+
<% if rodauth.features.include?(:oidc) && scope == "offline_access" %>
|
32
|
+
<%= hidden_field_tag "scope[]", scope %>
|
33
|
+
<% else %>
|
34
|
+
<div class="form-check">
|
35
|
+
<%= check_box_tag "scope[]", scope, id: scope, class: "form-check-input" %>
|
36
|
+
<%= label_tag scope, scope, class: "form-check-label" %>
|
37
|
+
</div>
|
38
|
+
<% end %>
|
33
39
|
<% end %>
|
34
40
|
<%= hidden_field_tag :client_id, params[:client_id] %>
|
35
41
|
<% %i[access_type response_type response_mode state redirect_uri].each do |oauth_param| %>
|
@@ -51,6 +57,9 @@
|
|
51
57
|
<% end %>
|
52
58
|
<% end %>
|
53
59
|
<% if rodauth.features.include?(:oidc) %>
|
60
|
+
<% if params[:prompt] %>
|
61
|
+
<%= hidden_field_tag :prompt, params[:prompt] %>
|
62
|
+
<% end %>
|
54
63
|
<% if params[:nonce] %>
|
55
64
|
<%= hidden_field_tag :nonce, params[:nonce] %>
|
56
65
|
<% end %>
|
@@ -60,13 +69,16 @@
|
|
60
69
|
<% if params[:claims_locales] %>
|
61
70
|
<%= hidden_field_tag :claims_locales, params[:claims_locales] %>
|
62
71
|
<% end %>
|
72
|
+
<% if params[:claims] %>
|
73
|
+
<%= hidden_field_tag :claims, sanitize(params[:claims]) %>
|
74
|
+
<% end %>
|
63
75
|
<% if params[:acr_values] %>
|
64
|
-
<%= hidden_field_tag :
|
76
|
+
<%= hidden_field_tag :acr_values, params[:acr_values] %>
|
65
77
|
<% end %>
|
66
78
|
<% end %>
|
67
79
|
</div>
|
68
80
|
<p class="text-center">
|
69
81
|
<%= submit_tag rodauth.oauth_authorize_button, class: "btn btn-outline-primary" %>
|
70
|
-
<%= link_to rodauth.oauth_cancel_button, "#{rodauth.redirect_uri}?error=access_denied&error_description=The+resource+owner+or+authorization+server+denied+the+request#{"&state=\#{rodauth.state}" if params[:state] }", class: "btn btn-outline-danger" %>
|
82
|
+
<%= link_to rodauth.oauth_cancel_button, "#{rodauth.redirect_uri}?error=access_denied&error_description=The+resource+owner+or+authorization+server+denied+the+request#{"&state=\#{CGI.escape(rodauth.state)}" if params[:state] }", class: "btn btn-outline-danger" %>
|
71
83
|
</p>
|
72
84
|
<% end %>
|
@@ -5,42 +5,48 @@ class CreateRodauthOauth < ActiveRecord::Migration<%= migration_version %>
|
|
5
5
|
t.foreign_key :accounts, column: :account_id
|
6
6
|
t.string :name, null: false
|
7
7
|
t.string :description, null: true
|
8
|
-
t.string :homepage_url, null:
|
8
|
+
t.string :homepage_url, null: true
|
9
9
|
t.string :redirect_uri, null: false
|
10
10
|
t.string :client_id, null: false, index: { unique: true }
|
11
11
|
t.string :client_secret, null: false, index: { unique: true }
|
12
12
|
t.string :scopes, null: false
|
13
13
|
t.datetime :created_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
14
|
-
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
#
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
#
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
#
|
43
|
-
|
14
|
+
|
15
|
+
# :oauth_dynamic_client_configuration enabled, extra optional params
|
16
|
+
t.string :token_endpoint_auth_method, null: true
|
17
|
+
t.string :grant_types, null: true
|
18
|
+
t.string :response_types, null: true
|
19
|
+
t.string :client_uri, null: true
|
20
|
+
t.string :logo_uri, null: true
|
21
|
+
t.string :tos_uri, null: true
|
22
|
+
t.string :policy_uri, null: true
|
23
|
+
t.string :jwks_uri, null: true
|
24
|
+
t.string :jwks, null: true
|
25
|
+
t.string :contacts, null: true
|
26
|
+
t.string :software_id, null: true
|
27
|
+
t.string :software_version, null: true
|
28
|
+
|
29
|
+
# :oidc_dynamic_client_configuration enabled, extra optional params
|
30
|
+
t.string :sector_identifier_uri, null: true
|
31
|
+
t.string :application_type, null: true
|
32
|
+
|
33
|
+
# :oidc enabled
|
34
|
+
t.string :subject_type, null: true
|
35
|
+
t.string :id_token_signed_response_alg, null: true
|
36
|
+
t.string :id_token_encrypted_response_alg, null: true
|
37
|
+
t.string :id_token_encrypted_response_enc, null: true
|
38
|
+
t.string :userinfo_signed_response_alg, null: true
|
39
|
+
t.string :userinfo_encrypted_response_alg, null: true
|
40
|
+
t.string :userinfo_encrypted_response_enc, null: true
|
41
|
+
|
42
|
+
# :oauth_jwt_secured_authorization_request
|
43
|
+
t.string :request_object_signing_alg, null: true
|
44
|
+
t.string :request_object_encryption_alg, null: true
|
45
|
+
t.string :request_object_encryption_enc, null: true
|
46
|
+
t.string :request_uris, null: true
|
47
|
+
|
48
|
+
# :oidc_rp_initiated_logout enabled
|
49
|
+
t.string :post_logout_redirect_uris, null: false
|
44
50
|
end
|
45
51
|
|
46
52
|
create_table :oauth_grants do |t|
|
@@ -58,19 +64,24 @@ class CreateRodauthOauth < ActiveRecord::Migration<%= migration_version %>
|
|
58
64
|
t.datetime :revoked_at
|
59
65
|
t.string :scopes, null: false
|
60
66
|
t.datetime :created_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
|
61
|
-
# for using access_types
|
62
67
|
t.string :access_type, null: false, default: "offline"
|
63
|
-
|
64
|
-
#
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
#
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
#
|
73
|
-
|
68
|
+
|
69
|
+
# :oauth_pkce enabled
|
70
|
+
t.string :code_challenge
|
71
|
+
t.string :code_challenge_method
|
72
|
+
|
73
|
+
# :oauth_device_code_grant enabled
|
74
|
+
t.string :user_code, null: true, unique: true
|
75
|
+
t.datetime :last_polled_at, null: true
|
76
|
+
|
77
|
+
# :resource_indicators enabled
|
78
|
+
t.string :resource
|
79
|
+
|
80
|
+
# :oidc enabled
|
81
|
+
t.string :nonce
|
82
|
+
t.string :acr
|
83
|
+
t.string :claims_locales
|
84
|
+
t.string :claims
|
74
85
|
end
|
75
86
|
end
|
76
87
|
end
|
@@ -165,10 +165,10 @@ module Rodauth
|
|
165
165
|
value.each do |uri|
|
166
166
|
next if uri.empty?
|
167
167
|
|
168
|
-
set_field_error(key, invalid_url_message) unless
|
168
|
+
set_field_error(key, invalid_url_message) unless check_valid_no_fragment_uri?(uri)
|
169
169
|
end
|
170
170
|
else
|
171
|
-
set_field_error(key, invalid_url_message) unless
|
171
|
+
set_field_error(key, invalid_url_message) unless check_valid_no_fragment_uri?(value)
|
172
172
|
end
|
173
173
|
elsif key == oauth_application_scopes_param
|
174
174
|
|
@@ -25,9 +25,9 @@ module Rodauth
|
|
25
25
|
def validate_authorize_params
|
26
26
|
super
|
27
27
|
|
28
|
-
|
28
|
+
response_mode = param_or_nil("response_mode")
|
29
29
|
|
30
|
-
redirect_response_error("invalid_request")
|
30
|
+
redirect_response_error("invalid_request") if response_mode && !oauth_response_modes_supported.include?(response_mode)
|
31
31
|
end
|
32
32
|
|
33
33
|
def validate_token_params
|
@@ -46,7 +46,6 @@ module Rodauth
|
|
46
46
|
|
47
47
|
case response_type
|
48
48
|
when "code", nil
|
49
|
-
response_mode ||= oauth_response_mode
|
50
49
|
response_params.replace(_do_authorize_code)
|
51
50
|
end
|
52
51
|
|
@@ -68,7 +67,7 @@ module Rodauth
|
|
68
67
|
redirect_url = URI.parse(redirect_uri)
|
69
68
|
case mode
|
70
69
|
when "query"
|
71
|
-
params = params.map { |k, v| "#{k}=#{v}" }
|
70
|
+
params = params.map { |k, v| "#{CGI.escape(k)}=#{CGI.escape(v)}" }
|
72
71
|
params << redirect_url.query if redirect_url.query
|
73
72
|
redirect_url.query = params.join("&")
|
74
73
|
redirect(redirect_url.to_s)
|
@@ -80,7 +79,7 @@ module Rodauth
|
|
80
79
|
<form method="post" action="#{redirect_uri}">
|
81
80
|
#{
|
82
81
|
params.map do |name, value|
|
83
|
-
"<input type=\"hidden\" name=\"#{name}\" value=\"#{scope.h(value)}\" />"
|
82
|
+
"<input type=\"hidden\" name=\"#{scope.h(name)}\" value=\"#{scope.h(value)}\" />"
|
84
83
|
end.join
|
85
84
|
}
|
86
85
|
<input type="submit" class="btn btn-outline-primary" value="#{scope.h(oauth_authorize_post_button)}"/>
|
@@ -91,11 +90,36 @@ module Rodauth
|
|
91
90
|
end
|
92
91
|
end
|
93
92
|
|
93
|
+
def _redirect_response_error(redirect_url, query_params)
|
94
|
+
response_mode = param_or_nil("response_mode") || oauth_response_mode
|
95
|
+
|
96
|
+
case response_mode
|
97
|
+
when "form_post"
|
98
|
+
response["Content-Type"] = "text/html"
|
99
|
+
response.write <<-FORM
|
100
|
+
<html>
|
101
|
+
<head><title></title></head>
|
102
|
+
<body onload="javascript:document.forms[0].submit()">
|
103
|
+
<form method="post" action="#{redirect_uri}">
|
104
|
+
#{
|
105
|
+
query_params.map do |name, value|
|
106
|
+
"<input type=\"hidden\" name=\"#{name}\" value=\"#{scope.h(value)}\" />"
|
107
|
+
end.join
|
108
|
+
}
|
109
|
+
</form>
|
110
|
+
</body>
|
111
|
+
</html>
|
112
|
+
FORM
|
113
|
+
request.halt
|
114
|
+
else
|
115
|
+
super
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
94
119
|
def create_token(grant_type)
|
95
120
|
return super unless supported_grant_type?(grant_type, "authorization_code")
|
96
121
|
|
97
122
|
grant_params = {
|
98
|
-
oauth_grants_type_column => grant_type,
|
99
123
|
oauth_grants_code_column => param("code"),
|
100
124
|
oauth_grants_redirect_uri_column => param("redirect_uri"),
|
101
125
|
oauth_grants_oauth_application_id_column => oauth_application[oauth_applications_id_column]
|
@@ -107,7 +131,7 @@ module Rodauth
|
|
107
131
|
def check_valid_response_type?
|
108
132
|
response_type = param_or_nil("response_type")
|
109
133
|
|
110
|
-
response_type
|
134
|
+
response_type == "code" || response_type == "none" || super
|
111
135
|
end
|
112
136
|
|
113
137
|
def oauth_server_metadata_body(*)
|