doorkeeper-openid_connect 1.8.11 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +52 -1
- data/README.md +226 -12
- data/app/controllers/concerns/doorkeeper/openid_connect/authorizations_extension.rb +2 -1
- data/app/controllers/doorkeeper/openid_connect/discovery_controller.rb +14 -28
- data/app/controllers/doorkeeper/openid_connect/dynamic_client_registration_controller.rb +81 -0
- data/config/locales/en.yml +2 -0
- data/lib/doorkeeper/oauth/id_token_response.rb +1 -1
- data/lib/doorkeeper/oauth/id_token_token_response.rb +2 -1
- data/lib/doorkeeper/openid_connect/claims/claim.rb +21 -9
- data/lib/doorkeeper/openid_connect/claims_builder.rb +3 -2
- data/lib/doorkeeper/openid_connect/config.rb +31 -8
- data/lib/doorkeeper/openid_connect/engine.rb +1 -1
- data/lib/doorkeeper/openid_connect/errors.rb +3 -1
- data/lib/doorkeeper/openid_connect/grant_types_supported_mixin.rb +13 -0
- data/lib/doorkeeper/openid_connect/helpers/controller.rb +171 -32
- data/lib/doorkeeper/openid_connect/id_token.rb +24 -12
- data/lib/doorkeeper/openid_connect/id_token_token.rb +11 -4
- data/lib/doorkeeper/openid_connect/oauth/authorization/code.rb +1 -1
- data/lib/doorkeeper/openid_connect/oauth/authorization_code_request.rb +5 -5
- data/lib/doorkeeper/openid_connect/oauth/dynamic_registration_request.rb +108 -0
- data/lib/doorkeeper/openid_connect/oauth/password_access_token_request.rb +5 -3
- data/lib/doorkeeper/openid_connect/oauth/pre_authorization.rb +2 -2
- data/lib/doorkeeper/openid_connect/oauth/token_response.rb +1 -1
- data/lib/doorkeeper/openid_connect/orm/active_record/access_grant.rb +2 -2
- data/lib/doorkeeper/openid_connect/orm/active_record/mixins/openid_request.rb +31 -0
- data/lib/doorkeeper/openid_connect/orm/active_record/request.rb +3 -13
- data/lib/doorkeeper/openid_connect/orm/active_record.rb +26 -14
- data/lib/doorkeeper/openid_connect/rails/routes/mapping.rb +5 -3
- data/lib/doorkeeper/openid_connect/rails/routes.rb +20 -10
- data/lib/doorkeeper/openid_connect/token_endpoint_auth_methods_supported_mixin.rb +18 -0
- data/lib/doorkeeper/openid_connect/user_info.rb +6 -3
- data/lib/doorkeeper/openid_connect/version.rb +7 -1
- data/lib/doorkeeper/openid_connect.rb +134 -43
- data/lib/doorkeeper/request/id_token.rb +1 -1
- data/lib/doorkeeper/request/id_token_token.rb +1 -1
- data/lib/generators/doorkeeper/openid_connect/install_generator.rb +6 -5
- data/lib/generators/doorkeeper/openid_connect/migration_generator.rb +8 -8
- data/lib/generators/doorkeeper/openid_connect/templates/initializer.rb +58 -8
- metadata +21 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1b09f0d036559583b3db8dd63e6e35452e5f9c42c90ce098ab263c1817016994
|
|
4
|
+
data.tar.gz: f9c9584568d90c9d351a347d435ba471d8e798aa42c9ac28edebefcd59d33c1a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a5a7f986bd19adcc2f3b4a03467d6052e32722f06162446b5ba944a8b905a111aa27528ccfc827e493382e95ab9dc89834a4ee483895951883291bda1387db81
|
|
7
|
+
data.tar.gz: c9fc3444e391e9b971bd193b18f388dafa47c5f5d6188d055fad2f524f9c8d6ceb67929a6b2ab5179ab50ff3c854e8d4883c9f6a43b9cd650cceba97a2e4dee2
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,57 @@
|
|
|
1
1
|
## Unreleased
|
|
2
2
|
|
|
3
|
-
-
|
|
3
|
+
- Please add here
|
|
4
|
+
|
|
5
|
+
## v1.10.0 (2026-06-01)
|
|
6
|
+
|
|
7
|
+
- [#241] Fix NameError on doorkeeper master by deferring AR model loading in run_hooks (see [Doorkeeper PR](https://github.com/doorkeeper-gem/doorkeeper/pull/1804))
|
|
8
|
+
- [#242] Fix `NoMethodError` for openid_request in testing environments.
|
|
9
|
+
- [#246] Fix `at_hash` to use correct hash algorithm based on `signing_algorithm`
|
|
10
|
+
- [#250] Return configured `issuer` instead of `root_url` in WebFinger response (thanks to @sato11 for the original work in #172)
|
|
11
|
+
- [#248] Fix `max_age` always triggering reauthentication when `auth_time_from_resource_owner` returns Integer
|
|
12
|
+
- [#254] **Breaking:** Omit `expires_in` from the `response_type=id_token` response (OIDC Core §3.2.2.5 — `expires_in` represents the Access Token lifetime; it is still returned for `response_type=id_token token`)
|
|
13
|
+
- [#252] Treat `auth_time_from_resource_owner` as optional in `IdToken` — omit `auth_time` claim when unconfigured instead of raising `InvalidConfiguration`
|
|
14
|
+
- [#256] Accept non-callable values (symbol / string) for the `protocol` config option, matching the pattern used by `issuer` / `signing_algorithm` / `signing_key` / `expiration`
|
|
15
|
+
- [#258] Skip `IdToken` construction on password grants without the `openid` scope
|
|
16
|
+
- [#259] Skip `IdToken` construction on authorization code grants without the `openid` scope
|
|
17
|
+
- [#261] Fix obsolete RuboCop configuration (`require:` → `plugins:`, `RSpec/FilePath` split, remove `Capybara/FeatureMethods`)
|
|
18
|
+
- [#263] **Security/Breaking:** Determine dynamically registered client's `confidential` flag from `token_endpoint_auth_method` per RFC 7591 — previously every dynamically registered client was created as public (`confidential: false`), which let callers authenticate with only `client_id` (`by_uid_and_secret(uid, nil)` bypass). Default is now `client_secret_basic` (confidential); `none` produces a public client; unsupported values (e.g. `private_key_jwt`) are rejected with `invalid_client_metadata`. Also derive `token_endpoint_auth_methods_supported` in the response from `Doorkeeper.configuration.client_credentials_methods` instead of a hardcoded list, matching #236
|
|
19
|
+
- [#264] Apply safe RuboCop autocorrections and fix resulting artifacts
|
|
20
|
+
- [#265] Add Dynamic Client Registration section to README
|
|
21
|
+
- [#266] Validate `application_type`, `response_types`, and `grant_types` parameters in dynamic client registration per RFC 7591 — reject unsupported values with `invalid_client_metadata` and echo the requested values back in the registration response, instead of silently ignoring them and returning the server's global configuration
|
|
22
|
+
- [#267] Add `authorize_dynamic_client_registration` config option to gate the dynamic client registration endpoint per RFC 7591 §3.1 — when set to a callable, the block is evaluated in the controller scope (with access to `request`, `params`, `request.headers`, etc.) and falsy return values reject the request with `401 invalid_token`. Default is `nil` so the endpoint remains open for backward compatibility; consumers should configure this to validate an Initial Access Token (or any other authorization scheme) before allowing client registration
|
|
23
|
+
- [#268] Update Dynamic Client Registration README for validated metadata parameters
|
|
24
|
+
- [#269] Document `authorize_dynamic_client_registration` in README
|
|
25
|
+
- [#270] Document the unified issuer block signature in README
|
|
26
|
+
- [#278] Test against Ruby 4.0.
|
|
27
|
+
- [#271] **Security:** Add `auth_time_from_session` config for per-session `max_age` enforcement. The legacy `auth_time_from_resource_owner` cannot distinguish between concurrent sessions and is now deprecated for `max_age` use (see [#150](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/issues/150))
|
|
28
|
+
- [#272] Document `auth_time_from_session` in README (follow-up to [#271](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/pull/271))
|
|
29
|
+
- [#273] **Security/Hardening:** Merge framework-controlled registered claims last — `iss`/`sub`/`aud`/`exp`/`iat`/`nonce`/`auth_time` for the ID Token and `sub` for UserInfo — so a custom claim block can no longer override security-critical values. No legitimate configuration relied on this; custom claims that intentionally shadowed a registered claim name will now be ignored for that key (OIDC Core §2 / §3.1.3.7 / §5.3.2).
|
|
30
|
+
- [#276] Get RuboCop to zero offenses: fix `Lint/MissingSuper` in `IdTokenResponse`, replace `puts` with `warn` for deprecation notices, and modernise spec style
|
|
31
|
+
- [#277] Fix README inaccuracies (`signing_algorithm` description and link, `discovery_url_options` endpoint list, `oauth-authorization-server` route) and use constant-time comparison in the DCR authorization example to prevent timing attacks on the Initial Access Token
|
|
32
|
+
- [#279] Return `account_selection_required` when a `prompt=select_account` handler does not generate a response, per [OIDC Core 1.0 §3.1.2.6](https://openid.net/specs/openid-connect-core-1_0.html#AuthError) — previously the authorization silently continued without account selection. Adds the missing `Errors::AccountSelectionRequired` class, mirroring the existing `login_required` backstop for `reauthenticate_resource_owner`
|
|
33
|
+
- [#275] Return `login_required` for `max_age` reauthentication when `prompt=none`, instead of triggering the interactive `reauthenticate_resource_owner` flow (OIDC Core §3.1.2.1)
|
|
34
|
+
- [#284] Document `acr` / `amr` claims in README — show how to expose Authentication Context Class Reference and Authentication Methods References via the `claim` DSL, with callouts for the `response:` and `scope:` defaults that silently bite
|
|
35
|
+
- [#288] Document `offline_access` scope recipe in README — show how to wire `use_refresh_token` with scope-based filtering for OIDC offline access
|
|
36
|
+
- [#281] Fix `NoMethodError` / `DoubleRenderError` when `resource_owner_authenticator` redirects with a truthy non-model value (e.g. `current_user || redirect_to(login_url)`). Normalize the leaked value to `nil` when `performed?` and add missing `if owner` guard on `select_account`.
|
|
37
|
+
- [#285] Document custom `jwks_uri` path pattern in README — show how to advertise a non-default path in the discovery document using Rails' `direct` URL helper
|
|
38
|
+
- [#283] Support multiple signing keys in the JWKS response — `signing_key` now also accepts an array (and callables returning an array). The first entry is the active key used to sign new ID tokens; the remaining entries are published in the JWKS so clients can still validate tokens signed with a retired key during a rotation window. Single-value and callable forms continue to work unchanged
|
|
39
|
+
- [#286] Allow claims to be assigned to multiple scopes via `scope: [:profile, :all_data]` — the claim is returned whenever the access token grants any of the listed scopes. **Note:** the previously implicit `Claim#scope=` writer (from `attr_accessor :scope`) is no longer provided; rebuild the claim instead of mutating it
|
|
40
|
+
- [#287] Add `apply_prompt_to_non_oidc_requests` option to honor the `prompt` parameter on plain OAuth requests that do not include the `openid` scope
|
|
41
|
+
- [#282] Allow `prompt=none` reauthorization with a narrower subset of previously-granted scopes (issue #63). Per RFC 6749 §1.5, narrower-or-equal scopes do not require fresh user consent; previously these requests returned `consent_required`.
|
|
42
|
+
- [#290] Freeze `Claim#scopes` and `Claim#response` arrays at construction so callers can't accidentally mutate the claim's internal state from outside
|
|
43
|
+
- [#297] Fix the generated initializer's `issuer` example referencing an undefined `request` local (the block parameter is `_request`), which raised `NameError` when copied verbatim
|
|
44
|
+
|
|
45
|
+
## v1.9.0 (2026-03-16)
|
|
46
|
+
|
|
47
|
+
- [#229] Allow to application manage signing key and algorithm
|
|
48
|
+
- [#230] Add dynamic client registration
|
|
49
|
+
- [#233] fix: handle `DoubleRenderError` in library instead of requiring consumer workaround
|
|
50
|
+
- [#232] Implements customizable OpenID request class
|
|
51
|
+
- [#236] Derive `token_endpoint_auth_methods_supported` from Doorkeeper's client_credentials config
|
|
52
|
+
- [#225] Allow configuration of id_token expiration using a block.
|
|
53
|
+
- [#237] Fix dynamic client registration returning hashed secret when `hash_application_secrets` is enabled
|
|
54
|
+
- [#226] Respect Doorkeeper's configured `pkce_code_challenge_methods`
|
|
4
55
|
|
|
5
56
|
## v1.8.11 (2025-02-10)
|
|
6
57
|
|
data/README.md
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
# Doorkeeper::OpenidConnect
|
|
2
2
|
|
|
3
|
-
[](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/actions/workflows/ci.yml)
|
|
4
|
+
[](https://qlty.sh/gh/doorkeeper-gem/projects/doorkeeper-openid_connect)
|
|
5
5
|
[](https://rubygems.org/gems/doorkeeper-openid_connect)
|
|
6
6
|
|
|
7
|
-
#### :warning: **This project is looking for maintainers, see [this issue](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/issues/89).**
|
|
8
|
-
|
|
9
7
|
This library implements an [OpenID Connect](http://openid.net/connect/) authentication provider for Rails applications on top of the [Doorkeeper](https://github.com/doorkeeper-gem/doorkeeper) OAuth 2.0 framework.
|
|
10
8
|
|
|
11
9
|
OpenID Connect is a single-sign-on and identity layer with a [growing list of server and client implementations](http://openid.net/developers/libraries/). If you're looking for a client in Ruby check out [omniauth_openid_connect](https://github.com/m0n9oose/omniauth_openid_connect/).
|
|
@@ -22,6 +20,7 @@ OpenID Connect is a single-sign-on and identity layer with a [growing list of se
|
|
|
22
20
|
- [Routes](#routes)
|
|
23
21
|
- [Nonces](#nonces)
|
|
24
22
|
- [Internationalization (I18n)](#internationalization-i18n)
|
|
23
|
+
- [Dynamic Client Registration](#dynamic-client-registration)
|
|
25
24
|
- [Development](#development)
|
|
26
25
|
- [License](#license)
|
|
27
26
|
- [Sponsors](#sponsors)
|
|
@@ -35,8 +34,9 @@ The following parts of [OpenID Connect Core 1.0](http://openid.net/specs/openid-
|
|
|
35
34
|
- [UserInfo Endpoint](http://openid.net/specs/openid-connect-core-1_0.html#UserInfo)
|
|
36
35
|
- [Normal Claims](http://openid.net/specs/openid-connect-core-1_0.html#NormalClaims)
|
|
37
36
|
- [OAuth 2.0 Form Post Response Mode](https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html)
|
|
37
|
+
- [OAuth 2.0 Dynamic Client Registration Protocol](https://datatracker.ietf.org/doc/html/rfc7591)
|
|
38
38
|
|
|
39
|
-
In addition we also support most of [OpenID Connect Discovery 1.0](http://openid.net/specs/openid-connect-discovery-1_0.html) for automatic configuration discovery.
|
|
39
|
+
In addition, we also support most of [OpenID Connect Discovery 1.0](http://openid.net/specs/openid-connect-discovery-1_0.html) for automatic configuration discovery.
|
|
40
40
|
|
|
41
41
|
Take a look at the [DiscoveryController](app/controllers/doorkeeper/openid_connect/discovery_controller.rb) for more details on supported features.
|
|
42
42
|
|
|
@@ -72,7 +72,8 @@ rails generate doorkeeper:openid_connect:migration
|
|
|
72
72
|
rake db:migrate
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
If you're upgrading from an earlier version, check [
|
|
75
|
+
If you're upgrading from an earlier version, check [Migration from old versions](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/wiki/Migration%E2%80%90from%E2%80%90old%E2%80%90versions)
|
|
76
|
+
wiki and [CHANGELOG.md](CHANGELOG.md) for upgrade instructions.
|
|
76
77
|
|
|
77
78
|
## Configuration
|
|
78
79
|
|
|
@@ -104,7 +105,19 @@ The following settings are required in `config/initializers/doorkeeper_openid_co
|
|
|
104
105
|
|
|
105
106
|
- `issuer`
|
|
106
107
|
- Identifier for the issuer of the response (i.e. your application URL). The value is a case sensitive URL using the `https` scheme that contains scheme, host, and optionally, port number and path components and no query or fragment components.
|
|
107
|
-
- You can either pass a string value, or a block to generate the issuer dynamically
|
|
108
|
+
- You can either pass a string value, or a block to generate the issuer dynamically. The block receives `resource_owner`, `application`, and `request` so that the same configuration can serve both ID token issuance (where `resource_owner` and `application` are available) and the discovery endpoint (where only `request` is available):
|
|
109
|
+
|
|
110
|
+
```ruby
|
|
111
|
+
# config/initializers/doorkeeper_openid_connect.rb
|
|
112
|
+
Doorkeeper::OpenidConnect.configure do
|
|
113
|
+
# ...
|
|
114
|
+
issuer do |resource_owner, application, request|
|
|
115
|
+
request&.base_url || "https://default.example.com"
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
- For backward compatibility, blocks with arity 0, 1, or 2 are also accepted. An arity-1 block receives `request` from the discovery endpoint and `resource_owner` from the ID token context, while an arity-2 block always receives `resource_owner` and `application`.
|
|
108
121
|
- `subject`
|
|
109
122
|
- Identifier for the resource owner (i.e. the authenticated user). A locally unique and never reassigned identifier within the issuer for the end-user, which is intended to be consumed by the client. The value is a case-sensitive string and must not exceed 255 ASCII characters in length.
|
|
110
123
|
- The database ID of the user is an acceptable choice if you don't mind leaking that information.
|
|
@@ -128,15 +141,45 @@ The following settings are required in `config/initializers/doorkeeper_openid_co
|
|
|
128
141
|
- You can generate a private key with the `openssl` command, see e.g. [Generate an RSA keypair using OpenSSL](https://en.wikibooks.org/wiki/Cryptography/Generate_a_keypair_using_OpenSSL).
|
|
129
142
|
- You should not commit the key to your repository, but use an external file (in combination with `File.read`) and/or the [dotenv-rails](https://github.com/bkeepers/dotenv) gem (in combination with `ENV[...]`).
|
|
130
143
|
- `signing_algorithm`
|
|
131
|
-
- The
|
|
144
|
+
- The signing algorithm used for the ID token, which defaults to `:rs256`. The list of supported algorithms can be found [here](https://github.com/jwt/ruby-jwt#algorithms-and-usage)
|
|
132
145
|
- `resource_owner_from_access_token`
|
|
133
146
|
- Defines how to translate the Doorkeeper access token to a resource owner model.
|
|
134
147
|
|
|
148
|
+
> [!Note]
|
|
149
|
+
> Both `signing_key` and `signing_algorithm` also accept callable objects (e.g. a lambda), which are evaluated on each call — useful for multi-tenant setups where the key or algorithm varies per request:
|
|
150
|
+
>
|
|
151
|
+
> ```ruby
|
|
152
|
+
> signing_key -> { current_tenant.private_key }
|
|
153
|
+
> signing_algorithm -> { current_tenant.algorithm }
|
|
154
|
+
> ```
|
|
155
|
+
|
|
156
|
+
> [!Note]
|
|
157
|
+
> `signing_key` also accepts an array for key rotation. The first entry is the active key used to sign newly issued ID tokens; the remaining entries are still published in the JWKS so clients can validate tokens signed with a retired key during a rotation window. Callable forms returning an array are also supported.
|
|
158
|
+
>
|
|
159
|
+
> ```ruby
|
|
160
|
+
> signing_key [
|
|
161
|
+
> File.read("config/keys/current.pem"), # active, signs new tokens
|
|
162
|
+
> File.read("config/keys/previous.pem"), # retired, exposed in JWKS only
|
|
163
|
+
> ]
|
|
164
|
+
> ```
|
|
165
|
+
|
|
135
166
|
The following settings are optional, but recommended for better client compatibility:
|
|
136
167
|
|
|
137
168
|
- `auth_time_from_resource_owner`
|
|
138
169
|
- Returns the time of the user's last login, this can be a `Time`, `DateTime`, or any other class that responds to `to_i`
|
|
139
|
-
-
|
|
170
|
+
- Used to populate the `auth_time` claim on the ID Token.
|
|
171
|
+
- Used as a fallback for `max_age` enforcement when `auth_time_from_session` is not configured. **Note:** for multi-session deployments this is insecure (it returns the most recent login on _any_ device), and emits a deprecation warning — prefer `auth_time_from_session` below.
|
|
172
|
+
- `auth_time_from_session`
|
|
173
|
+
- Returns the time the user authenticated for the *current* session. Required for correct `max_age` enforcement when the same user can hold multiple concurrent sessions (e.g. PC + smartphone) — `auth_time_from_resource_owner` cannot distinguish between sessions and would let a stale session inherit a fresh login from another device.
|
|
174
|
+
- The block is executed in the controller's scope and receives `(session, request)`. Return value can be a `Time`, `DateTime`, or anything responding to `to_i`. Return `nil` to force reauthentication.
|
|
175
|
+
|
|
176
|
+
```ruby
|
|
177
|
+
# Example: capture auth_time on the session at login,
|
|
178
|
+
# and surface it here for the OIDC max_age check.
|
|
179
|
+
auth_time_from_session do |session, _request|
|
|
180
|
+
session[:auth_time]
|
|
181
|
+
end
|
|
182
|
+
```
|
|
140
183
|
- `reauthenticate_resource_owner`
|
|
141
184
|
- Defines how to trigger reauthentication for the current user (e.g. display a password prompt, or sign-out the user and redirect to the login form).
|
|
142
185
|
- Required to support the `max_age` and `prompt=login` parameters.
|
|
@@ -150,7 +193,18 @@ The following settings are optional:
|
|
|
150
193
|
|
|
151
194
|
- `expiration`
|
|
152
195
|
- Expiration time after which the ID Token must not be accepted for processing by clients.
|
|
153
|
-
- The default is 120 seconds
|
|
196
|
+
- The default is 120 seconds, it can be configured using a value or block.
|
|
197
|
+
```ruby
|
|
198
|
+
# config/initializers/doorkeeper_openid_connect.rb
|
|
199
|
+
Doorkeeper::OpenidConnect.configure do
|
|
200
|
+
# ...
|
|
201
|
+
expiration do |resource_owner, application|
|
|
202
|
+
# You will have to ensure the application model implements an expiration method
|
|
203
|
+
application.expiration
|
|
204
|
+
end
|
|
205
|
+
# ...
|
|
206
|
+
end
|
|
207
|
+
```
|
|
154
208
|
|
|
155
209
|
- `protocol`
|
|
156
210
|
- The protocol to use when generating URIs for the discovery endpoints.
|
|
@@ -166,7 +220,7 @@ The following settings are optional:
|
|
|
166
220
|
- `discovery_url_options`
|
|
167
221
|
- The URL options for every available endpoint to use when generating the endpoint URL in the
|
|
168
222
|
discovery response. Available endpoints: `authorization`, `token`, `revocation`,
|
|
169
|
-
`introspection`, `userinfo`, `jwks`, `
|
|
223
|
+
`introspection`, `userinfo`, `jwks`, `dynamic_client_registration`.
|
|
170
224
|
- This option requires option keys with an available endpoint and
|
|
171
225
|
[URL options](https://api.rubyonrails.org/v6.0.3.3/classes/ActionDispatch/Routing/UrlFor.html#method-i-url_for)
|
|
172
226
|
as value.
|
|
@@ -192,6 +246,20 @@ The following settings are optional:
|
|
|
192
246
|
end
|
|
193
247
|
```
|
|
194
248
|
|
|
249
|
+
- `apply_prompt_to_non_oidc_requests`
|
|
250
|
+
- Whether to honor the `prompt` authorization parameter (`none`, `login`, `consent`, `select_account`) on plain OAuth requests that do not include the `openid` scope.
|
|
251
|
+
- Defaults to `false`, which preserves the historical behavior of silently ignoring `prompt` outside of OIDC requests.
|
|
252
|
+
- `max_age` enforcement remains OIDC-only regardless of this option, since it is defined by OIDC Core.
|
|
253
|
+
|
|
254
|
+
```ruby
|
|
255
|
+
# config/initializers/doorkeeper_openid_connect.rb
|
|
256
|
+
Doorkeeper::OpenidConnect.configure do
|
|
257
|
+
# ...
|
|
258
|
+
apply_prompt_to_non_oidc_requests true
|
|
259
|
+
# ...
|
|
260
|
+
end
|
|
261
|
+
```
|
|
262
|
+
|
|
195
263
|
### Scopes
|
|
196
264
|
|
|
197
265
|
To perform authentication over OpenID Connect, an OAuth client needs to request the `openid` scope. This scope needs to be enabled using either `optional_scopes` in the global Doorkeeper configuration in `config/initializers/doorkeeper.rb`, or by adding it to any OAuth application's `scope` attribute.
|
|
@@ -200,6 +268,24 @@ To perform authentication over OpenID Connect, an OAuth client needs to request
|
|
|
200
268
|
>
|
|
201
269
|
> See [Using Scopes](https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes) in the Doorkeeper wiki for more information.
|
|
202
270
|
|
|
271
|
+
#### `offline_access`
|
|
272
|
+
|
|
273
|
+
Per [OIDC Core §11](https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess), the `offline_access` scope signals that the client wants a refresh token so it can access the user's resources while the user is offline. Doorkeeper's existing `use_refresh_token` block already covers the basic flow — issue a refresh token only when the client actually asked for `offline_access`:
|
|
274
|
+
|
|
275
|
+
```ruby
|
|
276
|
+
# config/initializers/doorkeeper.rb
|
|
277
|
+
Doorkeeper.configure do
|
|
278
|
+
optional_scopes :openid, :offline_access
|
|
279
|
+
|
|
280
|
+
# Issue a refresh token only when the client requests offline_access
|
|
281
|
+
use_refresh_token do |context|
|
|
282
|
+
context.scopes.exists?("offline_access")
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
> **Note:** This does not automatically enforce [OIDC Core §11](https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess)'s strict requirements — for example, the OP MUST ignore `offline_access` unless `prompt=consent` is present and `response_type` returns an Authorization Code. If you need that level of enforcement, filter the scope in your `use_refresh_token` block or authorization controller override.
|
|
288
|
+
|
|
203
289
|
### Claims
|
|
204
290
|
|
|
205
291
|
Claims can be defined in a `claims` block inside `config/initializers/doorkeeper_openid_connect.rb`:
|
|
@@ -238,6 +324,48 @@ By default all custom claims are only returned from the `UserInfo` endpoint and
|
|
|
238
324
|
|
|
239
325
|
You can also pass a `scope:` keyword argument on each claim to specify which OAuth scope should be required to access the claim. If you define any of the defined [Standard Claims](http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) they will by default use their [corresponding scopes](http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims) (`profile`, `email`, `address` and `phone`), and any other claims will by default use the `profile` scope. Again, to use any of these scopes you need to enable them as described above.
|
|
240
326
|
|
|
327
|
+
You can also pass an array of scopes, in which case the claim is returned whenever the access token grants any of the listed scopes. This is useful when you want to expose the same claim under both a standard scope and an aggregate scope:
|
|
328
|
+
|
|
329
|
+
``` ruby
|
|
330
|
+
claim :given_name, scope: [:profile, :all_data] do |user|
|
|
331
|
+
user.first_name
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
claim :email, scope: [:email, :all_data] do |user|
|
|
335
|
+
user.email
|
|
336
|
+
end
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
#### Authentication Context (`acr`) and Methods (`amr`)
|
|
340
|
+
|
|
341
|
+
The `claim` DSL also handles standard top-level ID Token claims such as [`acr`](http://openid.net/specs/openid-connect-core-1_0.html#IDToken) (Authentication Context Class Reference) and [`amr`](https://www.rfc-editor.org/rfc/rfc8176) (Authentication Methods References) — commonly used to expose MFA status to clients:
|
|
342
|
+
|
|
343
|
+
```ruby
|
|
344
|
+
claims do
|
|
345
|
+
claim :acr, response: [:id_token, :user_info], scope: :openid do |resource_owner|
|
|
346
|
+
# Single string — e.g. a URI like "urn:mace:incommon:iap:silver",
|
|
347
|
+
# or a numeric Level of Assurance "1".."4" per ISO/IEC 29115.
|
|
348
|
+
resource_owner.mfa_enabled? ? "2" : "1"
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
claim :amr, response: [:id_token, :user_info], scope: :openid do |resource_owner|
|
|
352
|
+
# Array of strings, per RFC 8176.
|
|
353
|
+
methods = ["pwd"]
|
|
354
|
+
methods << "mfa" if resource_owner.mfa_enabled?
|
|
355
|
+
methods << "otp" if resource_owner.last_login_used_totp?
|
|
356
|
+
methods
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
Two defaults are worth calling out because they bite silently:
|
|
362
|
+
|
|
363
|
+
- **`response: [:id_token, :user_info]`** — custom claims default to UserInfo only, but relying parties usually expect `acr` / `amr` on the ID Token.
|
|
364
|
+
- **`scope: :openid`** — without it, non-standard claims fall back to the `profile` scope and disappear for clients that only requested `openid`.
|
|
365
|
+
|
|
366
|
+
Claim names you declare here are automatically advertised under `claims_supported` in the discovery document. The list of advertised `acr` values (`acr_values_supported`) is not currently generated.
|
|
367
|
+
|
|
368
|
+
|
|
241
369
|
### Routes
|
|
242
370
|
|
|
243
371
|
The installation generator will update your `config/routes.rb` to define all required routes:
|
|
@@ -256,11 +384,36 @@ GET /oauth/userinfo
|
|
|
256
384
|
POST /oauth/userinfo
|
|
257
385
|
GET /oauth/discovery/keys
|
|
258
386
|
GET /.well-known/openid-configuration
|
|
387
|
+
GET /.well-known/oauth-authorization-server
|
|
259
388
|
GET /.well-known/webfinger
|
|
260
389
|
```
|
|
261
390
|
|
|
262
391
|
With the exception of the hard-coded `/.well-known` paths (see [RFC 5785](https://tools.ietf.org/html/rfc5785)) you can customize routes in the same way as with Doorkeeper, please refer to [this page on their wiki](https://github.com/doorkeeper-gem/doorkeeper/wiki/Customizing-routes#version--05-1).
|
|
263
392
|
|
|
393
|
+
#### Customizing the `jwks_uri` path in the discovery document
|
|
394
|
+
|
|
395
|
+
[`discovery_url_options`](#configuration) lets you tweak the host, protocol, or port of the published `jwks_uri`, but not the path itself. To advertise a custom path — while keeping `/oauth/discovery/keys` working for existing clients during a rollover — mount the discovery controller at the new path and re-point the `oauth_discovery_keys_url` helper at it via [`direct`](https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/CustomUrlHelpers.html#method-i-direct):
|
|
396
|
+
|
|
397
|
+
```ruby
|
|
398
|
+
# config/routes.rb
|
|
399
|
+
Rails.application.routes.draw do
|
|
400
|
+
use_doorkeeper_openid_connect
|
|
401
|
+
|
|
402
|
+
# 1. Mount the custom path under a non-conflicting helper name
|
|
403
|
+
get "/-/jwks",
|
|
404
|
+
to: "doorkeeper/openid_connect/discovery#keys",
|
|
405
|
+
as: :custom_jwks
|
|
406
|
+
|
|
407
|
+
# 2. Re-point oauth_discovery_keys_url at the new path
|
|
408
|
+
direct(:oauth_discovery_keys) { |opts| custom_jwks_url(opts) }
|
|
409
|
+
end
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
After this, `.well-known/openid-configuration` returns `"jwks_uri": "https://example.com/-/jwks"`, and the original `/oauth/discovery/keys` route still responds (handy during a rollover).
|
|
413
|
+
|
|
414
|
+
> [!Note]
|
|
415
|
+
> A naive `match "/-/jwks", ..., as: :oauth_discovery_keys` won't work — Rails has refused to reuse a route name [since 4.0](https://github.com/rails/rails/commit/a2b7c0e69d) and raises `ArgumentError: Invalid route name, already in use: 'oauth_discovery_keys'`. The `direct` helper sidesteps this by overriding the URL helper itself rather than re-declaring the route name.
|
|
416
|
+
|
|
264
417
|
### Nonces
|
|
265
418
|
|
|
266
419
|
To support clients who send nonces you have to tweak Doorkeeper's authorization view so the parameter is passed on.
|
|
@@ -298,6 +451,67 @@ Then tweak the template as follows:
|
|
|
298
451
|
|
|
299
452
|
We use Rails locale files for error messages and scope descriptions, see [config/locales/en.yml](config/locales/en.yml). You can override these by adding them to your own translations in `config/locale`.
|
|
300
453
|
|
|
454
|
+
### Dynamic Client Registration
|
|
455
|
+
|
|
456
|
+
This gem supports [OpenID Connect Dynamic Client Registration 1.0](https://openid.net/specs/openid-connect-registration-1_0.html) based on [RFC 7591](https://www.rfc-editor.org/rfc/rfc7591).
|
|
457
|
+
|
|
458
|
+
To enable dynamic client registration, add the following to `config/initializers/doorkeeper_openid_connect.rb`:
|
|
459
|
+
|
|
460
|
+
```ruby
|
|
461
|
+
Doorkeeper::OpenidConnect.configure do
|
|
462
|
+
# ...
|
|
463
|
+
dynamic_client_registration true
|
|
464
|
+
# ...
|
|
465
|
+
end
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
This exposes a `POST /oauth/registration` endpoint where OAuth clients can register themselves.
|
|
469
|
+
|
|
470
|
+
#### Supported parameters
|
|
471
|
+
|
|
472
|
+
The registration endpoint currently accepts the following [RFC 7591 §2](https://www.rfc-editor.org/rfc/rfc7591#section-2) parameters:
|
|
473
|
+
|
|
474
|
+
| Parameter | Description |
|
|
475
|
+
| --- | --- |
|
|
476
|
+
| `client_name` | Human-readable name of the client |
|
|
477
|
+
| `redirect_uris` | Array of redirection URIs |
|
|
478
|
+
| `scope` | Space-delimited list of requested scopes |
|
|
479
|
+
| `token_endpoint_auth_method` | Requested authentication method. Defaults to `client_secret_basic`. `none` is always allowed (and registers a public client); other allowed values depend on the host application's Doorkeeper `client_credentials_methods` configuration. Unsupported values are rejected with `invalid_client_metadata`. |
|
|
480
|
+
| `application_type` | Client type: `web` (default) or `native`, per [OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0.html). Unsupported values are rejected with `invalid_client_metadata`. |
|
|
481
|
+
| `response_types` | Array of OAuth 2.0 response types the client will use (e.g. `["code"]`). Must be a subset of the server's supported response types. Defaults to the server's full set when omitted. |
|
|
482
|
+
| `grant_types` | Array of OAuth 2.0 grant types the client will use (e.g. `["authorization_code"]`). Must be a subset of the server's supported grant types. Defaults to the server's full set when omitted. |
|
|
483
|
+
|
|
484
|
+
When `token_endpoint_auth_method` is set to `none`, the client is registered as **public** (i.e. `confidential: false`). For all other values — or when the parameter is omitted — the client is registered as **confidential**, matching the RFC 7591 default of `client_secret_basic`.
|
|
485
|
+
|
|
486
|
+
Other RFC 7591 parameters (e.g. `client_uri`, `logo_uri`, `contacts`) require schema additions to `oauth_applications` and are not yet supported.
|
|
487
|
+
|
|
488
|
+
#### Authorization
|
|
489
|
+
|
|
490
|
+
By default, the registration endpoint is open to any request. To require authorization (e.g. an Initial Access Token per [RFC 7591 §3.1](https://www.rfc-editor.org/rfc/rfc7591#section-3.1)), configure `authorize_dynamic_client_registration`:
|
|
491
|
+
|
|
492
|
+
```ruby
|
|
493
|
+
Doorkeeper::OpenidConnect.configure do
|
|
494
|
+
# ...
|
|
495
|
+
dynamic_client_registration true
|
|
496
|
+
authorize_dynamic_client_registration do
|
|
497
|
+
provided = request.headers["Authorization"].to_s
|
|
498
|
+
expected = "Bearer #{ENV['DCR_INITIAL_ACCESS_TOKEN']}"
|
|
499
|
+
# Use a constant-time comparison to avoid leaking the token via timing.
|
|
500
|
+
# Digesting first keeps the comparison fixed-length so the token's length
|
|
501
|
+
# isn't leaked either.
|
|
502
|
+
ActiveSupport::SecurityUtils.secure_compare(
|
|
503
|
+
Digest::SHA256.hexdigest(provided),
|
|
504
|
+
Digest::SHA256.hexdigest(expected),
|
|
505
|
+
)
|
|
506
|
+
end
|
|
507
|
+
# ...
|
|
508
|
+
end
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
The block is evaluated in the controller scope (with access to `request`, `params`, `request.headers`, etc.). Return a truthy value to allow the request, or a falsy value to reject it with `401 invalid_token`.
|
|
512
|
+
|
|
513
|
+
When not configured (default), the endpoint remains open for backward compatibility.
|
|
514
|
+
|
|
301
515
|
## Development
|
|
302
516
|
|
|
303
517
|
Run `bundle install` to setup all development dependencies.
|
|
@@ -323,7 +537,7 @@ bundle exec rake server
|
|
|
323
537
|
By default, the latest Rails version is used. To use a specific version run:
|
|
324
538
|
|
|
325
539
|
```
|
|
326
|
-
rails=
|
|
540
|
+
rails=7.2 bundle update
|
|
327
541
|
```
|
|
328
542
|
|
|
329
543
|
## License
|
|
@@ -4,8 +4,10 @@ module Doorkeeper
|
|
|
4
4
|
module OpenidConnect
|
|
5
5
|
class DiscoveryController < ::Doorkeeper::ApplicationMetalController
|
|
6
6
|
include Doorkeeper::Helpers::Controller
|
|
7
|
+
include GrantTypesSupportedMixin
|
|
8
|
+
include TokenEndpointAuthMethodsSupportedMixin
|
|
7
9
|
|
|
8
|
-
WEBFINGER_RELATION =
|
|
10
|
+
WEBFINGER_RELATION = "http://openid.net/specs/connect/1.0/issuer"
|
|
9
11
|
|
|
10
12
|
def provider
|
|
11
13
|
render json: provider_response
|
|
@@ -34,6 +36,7 @@ module Doorkeeper
|
|
|
34
36
|
userinfo_endpoint: oauth_userinfo_url(userinfo_url_options),
|
|
35
37
|
jwks_uri: oauth_discovery_keys_url(jwks_url_options),
|
|
36
38
|
end_session_endpoint: instance_exec(&openid_connect.end_session_endpoint),
|
|
39
|
+
registration_endpoint: openid_connect.dynamic_client_registration ? oauth_dynamic_client_registration_url(dynamic_client_registration_url_options) : nil,
|
|
37
40
|
|
|
38
41
|
scopes_supported: doorkeeper.scopes,
|
|
39
42
|
|
|
@@ -45,7 +48,7 @@ module Doorkeeper
|
|
|
45
48
|
# TODO: look into doorkeeper-jwt_assertion for these
|
|
46
49
|
# 'client_secret_jwt',
|
|
47
50
|
# 'private_key_jwt'
|
|
48
|
-
token_endpoint_auth_methods_supported:
|
|
51
|
+
token_endpoint_auth_methods_supported: token_endpoint_auth_methods_supported,
|
|
49
52
|
|
|
50
53
|
subject_types_supported: openid_connect.subject_types_supported,
|
|
51
54
|
|
|
@@ -54,7 +57,7 @@ module Doorkeeper
|
|
|
54
57
|
],
|
|
55
58
|
|
|
56
59
|
claim_types_supported: [
|
|
57
|
-
|
|
60
|
+
"normal",
|
|
58
61
|
|
|
59
62
|
# TODO: support these
|
|
60
63
|
# 'aggregated',
|
|
@@ -73,12 +76,6 @@ module Doorkeeper
|
|
|
73
76
|
}.compact
|
|
74
77
|
end
|
|
75
78
|
|
|
76
|
-
def grant_types_supported(doorkeeper)
|
|
77
|
-
grant_types_supported = doorkeeper.grant_flows.dup
|
|
78
|
-
grant_types_supported << 'refresh_token' if doorkeeper.refresh_token_enabled?
|
|
79
|
-
grant_types_supported
|
|
80
|
-
end
|
|
81
|
-
|
|
82
79
|
def response_modes_supported(doorkeeper)
|
|
83
80
|
doorkeeper.authorization_response_flows.flat_map(&:response_mode_matches).uniq
|
|
84
81
|
end
|
|
@@ -86,7 +83,7 @@ module Doorkeeper
|
|
|
86
83
|
def code_challenge_methods_supported(doorkeeper)
|
|
87
84
|
return unless doorkeeper.access_grant_model.pkce_supported?
|
|
88
85
|
|
|
89
|
-
|
|
86
|
+
doorkeeper.pkce_code_challenge_methods
|
|
90
87
|
end
|
|
91
88
|
|
|
92
89
|
def webfinger_response
|
|
@@ -95,27 +92,19 @@ module Doorkeeper
|
|
|
95
92
|
links: [
|
|
96
93
|
{
|
|
97
94
|
rel: WEBFINGER_RELATION,
|
|
98
|
-
href:
|
|
95
|
+
href: issuer,
|
|
99
96
|
}
|
|
100
97
|
]
|
|
101
98
|
}
|
|
102
99
|
end
|
|
103
100
|
|
|
104
101
|
def keys_response
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
{
|
|
108
|
-
keys: [
|
|
109
|
-
signing_key.merge(
|
|
110
|
-
use: 'sig',
|
|
111
|
-
alg: Doorkeeper::OpenidConnect.signing_algorithm
|
|
112
|
-
)
|
|
113
|
-
]
|
|
114
|
-
}
|
|
102
|
+
{ keys: Doorkeeper::OpenidConnect.signing_keys_normalized }
|
|
115
103
|
end
|
|
116
104
|
|
|
117
105
|
def protocol
|
|
118
|
-
Doorkeeper::OpenidConnect.configuration.protocol
|
|
106
|
+
configured = Doorkeeper::OpenidConnect.configuration.protocol
|
|
107
|
+
configured.respond_to?(:call) ? configured.call : configured
|
|
119
108
|
end
|
|
120
109
|
|
|
121
110
|
def discovery_url_options
|
|
@@ -129,14 +118,11 @@ module Doorkeeper
|
|
|
129
118
|
end
|
|
130
119
|
|
|
131
120
|
def issuer
|
|
132
|
-
|
|
133
|
-
Doorkeeper::OpenidConnect.configuration.issuer.call(request).to_s
|
|
134
|
-
else
|
|
135
|
-
Doorkeeper::OpenidConnect.configuration.issuer
|
|
136
|
-
end
|
|
121
|
+
Doorkeeper::OpenidConnect.resolve_issuer(request: request)
|
|
137
122
|
end
|
|
138
123
|
|
|
139
|
-
%i[authorization token revocation introspection userinfo jwks
|
|
124
|
+
%i[authorization token revocation introspection userinfo jwks
|
|
125
|
+
dynamic_client_registration].each do |endpoint|
|
|
140
126
|
define_method :"#{endpoint}_url_options" do
|
|
141
127
|
discovery_url_default_options.merge(discovery_url_options[endpoint.to_sym] || {})
|
|
142
128
|
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Doorkeeper
|
|
4
|
+
module OpenidConnect
|
|
5
|
+
class DynamicClientRegistrationController < ::Doorkeeper::ApplicationMetalController
|
|
6
|
+
before_action :authorize_dynamic_client_registration!
|
|
7
|
+
|
|
8
|
+
def register
|
|
9
|
+
registration = OAuth::DynamicRegistrationRequest.new(::Doorkeeper.configuration, params)
|
|
10
|
+
|
|
11
|
+
unless registration.valid?
|
|
12
|
+
render json: registration.error_response, status: :bad_request
|
|
13
|
+
return
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
client = Doorkeeper::Application.create!(application_params(registration))
|
|
17
|
+
render json: registration_response(client, registration), status: :created
|
|
18
|
+
rescue ActiveRecord::RecordInvalid => e
|
|
19
|
+
render json: { error: "invalid_client_params", error_description: e.record.errors.full_messages.join(", ") },
|
|
20
|
+
status: :bad_request
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def authorize_dynamic_client_registration!
|
|
26
|
+
authorizer = ::Doorkeeper::OpenidConnect.configuration.authorize_dynamic_client_registration
|
|
27
|
+
return if authorizer.nil?
|
|
28
|
+
|
|
29
|
+
return if authorized?(authorizer)
|
|
30
|
+
|
|
31
|
+
response.headers["WWW-Authenticate"] = "Bearer error=\"invalid_token\""
|
|
32
|
+
render json: {
|
|
33
|
+
error: "invalid_token",
|
|
34
|
+
error_description: I18n.t(
|
|
35
|
+
"doorkeeper.openid_connect.errors.messages.dynamic_client_registration_unauthorized",
|
|
36
|
+
),
|
|
37
|
+
}, status: :unauthorized
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def authorized?(authorizer)
|
|
41
|
+
if authorizer.respond_to?(:to_proc)
|
|
42
|
+
instance_exec(&authorizer.to_proc)
|
|
43
|
+
elsif authorizer.respond_to?(:call)
|
|
44
|
+
authorizer.call(self)
|
|
45
|
+
else
|
|
46
|
+
authorizer
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def application_params(registration)
|
|
51
|
+
{
|
|
52
|
+
name: params[:client_name],
|
|
53
|
+
redirect_uri: params[:redirect_uris] || [],
|
|
54
|
+
scopes: params[:scope],
|
|
55
|
+
confidential: registration.confidential_client?,
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def registration_response(doorkeeper_application, registration)
|
|
60
|
+
response = {
|
|
61
|
+
client_id: doorkeeper_application.uid,
|
|
62
|
+
client_id_issued_at: doorkeeper_application.created_at.to_i,
|
|
63
|
+
redirect_uris: doorkeeper_application.redirect_uri.split,
|
|
64
|
+
token_endpoint_auth_method: registration.token_endpoint_auth_method,
|
|
65
|
+
token_endpoint_auth_methods_supported: registration.token_endpoint_auth_methods_supported,
|
|
66
|
+
response_types: registration.requested_response_types,
|
|
67
|
+
grant_types: registration.requested_grant_types,
|
|
68
|
+
scope: doorkeeper_application.scopes.to_s,
|
|
69
|
+
application_type: registration.requested_application_type,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if registration.confidential_client?
|
|
73
|
+
response[:client_secret] =
|
|
74
|
+
doorkeeper_application.plaintext_secret || doorkeeper_application.secret
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
response
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
data/config/locales/en.yml
CHANGED
|
@@ -21,3 +21,5 @@ en:
|
|
|
21
21
|
reauthenticate_resource_owner_not_configured: 'Failure due to Doorkeeper::OpenidConnect.configure.reauthenticate_resource_owner missing configuration.'
|
|
22
22
|
select_account_for_resource_owner_not_configured: 'Failure due to Doorkeeper::OpenidConnect.configure.select_account_for_resource_owner missing configuration.'
|
|
23
23
|
subject_not_configured: 'ID Token generation failed due to Doorkeeper::OpenidConnect.configure.subject missing configuration.'
|
|
24
|
+
signing_key_not_configured: 'Doorkeeper::OpenidConnect.configure.signing_key must resolve to at least one key.'
|
|
25
|
+
dynamic_client_registration_unauthorized: 'Authorization required for client registration'
|
|
@@ -8,6 +8,7 @@ module Doorkeeper
|
|
|
8
8
|
attr_accessor :pre_auth, :auth, :id_token
|
|
9
9
|
|
|
10
10
|
def initialize(pre_auth, auth, id_token)
|
|
11
|
+
super()
|
|
11
12
|
@pre_auth = pre_auth
|
|
12
13
|
@auth = auth
|
|
13
14
|
@id_token = id_token
|
|
@@ -19,7 +20,6 @@ module Doorkeeper
|
|
|
19
20
|
|
|
20
21
|
def body
|
|
21
22
|
{
|
|
22
|
-
expires_in: auth.token.expires_in_seconds,
|
|
23
23
|
state: pre_auth.state,
|
|
24
24
|
id_token: id_token.as_jws_token
|
|
25
25
|
}
|