doorkeeper-openid_connect 1.10.5 → 2.0.0.beta1
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 +49 -1
- data/README.md +47 -20
- data/app/controllers/concerns/doorkeeper/openid_connect/metadata_extension.rb +72 -0
- data/app/controllers/doorkeeper/openid_connect/discovery_controller.rb +20 -42
- data/app/controllers/doorkeeper/openid_connect/dynamic_client_registration_controller.rb +35 -4
- data/app/controllers/doorkeeper/openid_connect/userinfo_controller.rb +21 -1
- data/config/locales/en.yml +18 -0
- data/lib/doorkeeper/oauth/id_token_request.rb +3 -6
- data/lib/doorkeeper/oauth/id_token_response.rb +25 -1
- data/lib/doorkeeper/oauth/id_token_token_request.rb +6 -1
- data/lib/doorkeeper/oauth/id_token_token_response.rb +5 -1
- data/lib/doorkeeper/openid_connect/claims/claim.rb +5 -1
- data/lib/doorkeeper/openid_connect/claims_builder.rb +11 -2
- data/lib/doorkeeper/openid_connect/config.rb +102 -0
- data/lib/doorkeeper/openid_connect/discovery_helpers_mixin.rb +69 -0
- data/lib/doorkeeper/openid_connect/engine.rb +7 -0
- data/lib/doorkeeper/openid_connect/errors.rb +11 -5
- data/lib/doorkeeper/openid_connect/grant_types_supported_mixin.rb +24 -2
- data/lib/doorkeeper/openid_connect/helpers/controller/error_response.rb +7 -0
- data/lib/doorkeeper/openid_connect/helpers/controller/max_age.rb +20 -2
- data/lib/doorkeeper/openid_connect/helpers/controller/prompt.rb +27 -5
- data/lib/doorkeeper/openid_connect/helpers/controller.rb +8 -9
- data/lib/doorkeeper/openid_connect/{id_token_token.rb → hybrid_id_token_concern.rb} +10 -2
- data/lib/doorkeeper/openid_connect/id_token.rb +17 -5
- data/lib/doorkeeper/openid_connect/oauth/authorization/code.rb +5 -14
- data/lib/doorkeeper/openid_connect/oauth/authorization_code_request.rb +10 -5
- data/lib/doorkeeper/openid_connect/oauth/dynamic_registration_request.rb +7 -2
- data/lib/doorkeeper/openid_connect/oauth/metadata_response.rb +33 -0
- data/lib/doorkeeper/openid_connect/oauth/password_access_token_request.rb +7 -11
- data/lib/doorkeeper/openid_connect/oauth/token_response.rb +53 -13
- data/lib/doorkeeper/openid_connect/orm/active_record/mixins/application.rb +93 -0
- data/lib/doorkeeper/openid_connect/orm/active_record.rb +36 -3
- data/lib/doorkeeper/openid_connect/rails/routes.rb +15 -1
- data/lib/doorkeeper/openid_connect/token_endpoint_auth_methods_supported_mixin.rb +49 -3
- data/lib/doorkeeper/openid_connect/user_info.rb +11 -6
- data/lib/doorkeeper/openid_connect/version.rb +4 -4
- data/lib/doorkeeper/openid_connect.rb +192 -39
- data/lib/generators/doorkeeper/openid_connect/add_post_logout_redirect_uris_generator.rb +38 -0
- data/lib/generators/doorkeeper/openid_connect/templates/add_post_logout_redirect_uris.rb.erb +5 -0
- data/lib/generators/doorkeeper/openid_connect/templates/initializer.rb +30 -0
- data/lib/generators/doorkeeper/openid_connect/templates/migration.rb.erb +2 -0
- metadata +13 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 960d2cf9c359d5bae10fc7be2eff5fba0eb5309b359422d81ea0e0a3c451f192
|
|
4
|
+
data.tar.gz: e2efc3c51af4c54d599dd884264b9ce41cf136fa94f291d4222186dac3e266bd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f349f5d093f30c5ed07a77349cc63d0651047185587c149172ec5d38eb29bd4644a74f3b10fd54674f43beda2885f58b7b400094e19afda4d24daadd56dc1e8d
|
|
7
|
+
data.tar.gz: 73e1e48f7fa439a9f7df513db74ba0a5df969a19a32abdf9c1b8bda34db08356abde81b3b3fdf425a0bbc46c8f258b669d1368cf25d067f187405e2f7cc8efd0
|
data/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,57 @@
|
|
|
1
|
+
Upgrading? [Migration from Old Versions](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/wiki/Migration-from-Old-Versions) walks through every breaking change and the steps it asks for, and the rest of the [wiki](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/wiki) documents the configuration and behavior the entries below refer to.
|
|
2
|
+
|
|
1
3
|
## Unreleased
|
|
2
4
|
|
|
5
|
+
- Add entry here
|
|
6
|
+
|
|
7
|
+
## v2.0.0.beta1 (2026-08-20)
|
|
8
|
+
|
|
9
|
+
>[!IMPORTANT]
|
|
10
|
+
>
|
|
11
|
+
>- **This is a prerelease.** RubyGems does not resolve prereleases from an unqualified requirement, so it must be requested explicitly: `gem "doorkeeper-openid_connect", "2.0.0.beta1"`
|
|
12
|
+
>- **Migration required:** existing installations must add the `post_logout_redirect_uris` column — `rails generate doorkeeper:openid_connect:add_post_logout_redirect_uris` followed by `rails db:migrate` ([#243])
|
|
13
|
+
>- **Breaking (hybrid response type):** the `id_token token` response object is now the configured `id_token_class` extended with `HybridIdTokenConcern`, and a custom `id_token_class` must expose an `#access_token` reader ([#337])
|
|
14
|
+
>- **Breaking (constant removed):** `Doorkeeper::OpenidConnect::IdTokenToken` is gone — custom subclasses must subclass `IdToken` and include `HybridIdTokenConcern` ([#338])
|
|
15
|
+
>- **Breaking (Dynamic Client Registration):** a registration request that omits `response_types` / `grant_types` now defaults to `["code"]` / `["authorization_code"]` per RFC 7591 §2, instead of inheriting the server's global configuration ([#350])
|
|
16
|
+
>
|
|
17
|
+
>[Migration from Old Versions](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/wiki/Migration-from-Old-Versions) walks through each one.
|
|
18
|
+
|
|
19
|
+
- [#243] Add per-client `post_logout_redirect_uris` for RP-Initiated Logout, exposed via `Doorkeeper::Application#post_logout_redirect_uris` and `#valid_post_logout_redirect_uri?(uri)`. URIs are validated with the same rules as `redirect_uri`; Dynamic Client Registration accepts and echoes them back
|
|
20
|
+
- [#320] Support mounting the engine under multiple named scopes — `use_doorkeeper_openid_connect as: :users` makes each mount's discovery document advertise its own endpoints ([#192])
|
|
21
|
+
- [#322] Fall back to Doorkeeper's `issuer` configuration when the OpenID Connect `issuer` is not set. The OpenID Connect value still takes precedence ([#321])
|
|
22
|
+
- [#323] Resolve `token_endpoint_auth_methods_supported` from Doorkeeper's client authentication methods registry when available, falling back to legacy `client_credentials_methods` on older versions
|
|
23
|
+
- [#332] Fix `grant_types_supported` listing `refresh_token` twice when enabled via both `grant_flows` and `use_refresh_token`
|
|
24
|
+
- [#333] Emit the RFC 9207 `iss` parameter on `id_token` / `id_token token` authorization responses and on OIDC error redirects, and advertise `authorization_response_iss_parameter_supported` in the discovery document. No behavior change until Doorkeeper is configured with an `issuer`
|
|
25
|
+
- [#334] Allow Doorkeeper 6.0 (`>= 5.5, < 7.0`). Note: Doorkeeper 6.0's `force_pkce` applies to confidential clients too — `id_token` / `id_token token` authorization requests are rejected unless they carry a `code_challenge`
|
|
26
|
+
- [#335] Add `id_token_class` and `user_info_class` config options for custom ID Token / UserInfo response objects
|
|
27
|
+
- [#337] Rework `id_token_class` / `user_info_class` internals — lazy-resolve and validate configured classes at first use (fixes zeitwerk on Rails 7+) — and deprecate `Doorkeeper::OpenidConnect::IdTokenToken`. A custom `id_token_class` must now expose an `#access_token` reader. **Breaking (type change):** the hybrid response token is now the configured `id_token_class` extended with `HybridIdTokenConcern` — see the [migration guide](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/wiki/Migration-from-Old-Versions)
|
|
28
|
+
- [#338] **Breaking:** Remove the deprecated `IdTokenToken` class. Custom subclasses must subclass `IdToken` and include `HybridIdTokenConcern` instead
|
|
29
|
+
- [#341] Fix dynamic client registration to respect the `application_class` configuration
|
|
30
|
+
- [#347] Omit symmetric (`oct`) keys from the JWKS endpoint when signing with an HMAC algorithm (RFC 7517)
|
|
31
|
+
- [#348] Authorization endpoint hardening:
|
|
32
|
+
- Treat a malformed `max_age` parameter (e.g. `max_age[]=1`) as absent instead of a 500
|
|
33
|
+
- Build `prompt=login` / `prompt=select_account` return URLs without mutating the shared `request.query_parameters` hash
|
|
34
|
+
- Route internal errors (e.g. `InvalidConfiguration`) to a 500 instead of leaking them as authorization error redirects
|
|
35
|
+
- [#349] Fix several 500 errors in the claims pipeline: gracefully omit `id_token` when the access token has no resource owner, no application, or an owner that no longer resolves; return `401 invalid_token` at userinfo for the same cases. Also dispatch claims whose `response:` option is configured with strings (e.g. `response: ["id_token"]`), which were previously dropped from every response
|
|
36
|
+
- [#350] Discovery / Dynamic Client Registration spec compliance:
|
|
37
|
+
- Advertise the standard `implicit` grant type instead of the internal `implicit_oidc` name (RFC 7591 §2)
|
|
38
|
+
- **Breaking:** omitted `response_types` / `grant_types` in a registration request now default to `["code"]` / `["authorization_code"]` per RFC 7591 §2
|
|
39
|
+
- Use RFC 7591 §3.2.2 error codes (`invalid_redirect_uri` / `invalid_client_metadata`) instead of the invented `invalid_client_params`
|
|
40
|
+
- Serve WebFinger as `application/jrd+json` with `Access-Control-Allow-Origin: *` (RFC 7033)
|
|
41
|
+
- Create dynamically registered clients through `application_model` so custom models work with DCR
|
|
42
|
+
- [#351] Align OpenID Connect token/authorization responses with Doorkeeper's response contract: return the plaintext access token from the `id_token token` implicit response (fixes `hash_token_secrets`), define `#issued_token` on OIDC responses, and attach the ID token before `after_successful_strategy_response` fires
|
|
43
|
+
- [#353] Enrich Doorkeeper 6.0's RFC 8414 metadata document (`/.well-known/oauth-authorization-server`) with the OpenID Connect fields (`jwks_uri`, `userinfo_endpoint`, signing algs, claims) via the `custom_metadata` seam; app-configured `custom_metadata` keeps precedence. No behavior change on Doorkeeper < 6.0
|
|
44
|
+
- [#355] Compute `at_hash` from the plaintext access token instead of the stored value, fixing ID Token validation when `hash_token_secrets` is enabled
|
|
45
|
+
- [#360] Load the OpenID Connect constants with `autoload` instead of `require`, including the requests and responses this gem contributes to Doorkeeper's own namespace. No public constant changes name or moves ([#362])
|
|
46
|
+
- [#363] Extend [#349]'s `id_token` guard to the password grant with `skip_client_authentication_for_password_grant` — previously returned an unhandled 500
|
|
47
|
+
- [#370] Correct the stale `rake db:migrate` command to `rails db:migrate` in the README, the [#243] migration note, and the `post_logout_redirect_uris` missing-column error message
|
|
48
|
+
- [#372] Fix duplicate entries in the discovery document's `claims_supported` when a custom claim shadows a base claim (`iss`/`sub`/`aud`/`exp`/`iat`)
|
|
49
|
+
- [#373] Fix `prompt=consent` under Doorkeeper's `api_only` mode — the consent step now returns the pre-authorization as JSON instead of attempting to render a template that `ActionController::API` cannot serve
|
|
50
|
+
- [#381] Echo the registered `client_name` in the Dynamic Client Registration response, as RFC 7591 §3.2.1 requires the response to include all registered client metadata
|
|
51
|
+
|
|
3
52
|
## v1.10.5 (2026-07-09)
|
|
4
53
|
|
|
5
54
|
- [#329] Restore compatibility with the full `doorkeeper >= 5.5` range declared in the gemspec ([#328](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/issues/328)). Doorkeeper 5.5.x raised `NameError: uninitialized constant Doorkeeper::Orm::ActiveRecord::Mixins` at load time (the mixin file ships since 5.5.0 but is only autoloadable since 5.6.0 — it is now required explicitly when absent), and Doorkeeper 5.6/5.7 broke the discovery endpoint because `pkce_code_challenge_methods` only exists since 5.8.0 (the discovery response now falls back to `plain S256`, which is what those versions accept). CI now exercises the oldest supported Doorkeeper series via `gemfiles/doorkeeper_5.{5,6,7}.gemfile`
|
|
6
|
-
- Please add here
|
|
7
55
|
- [#325] Remove the dead `Claims::AggregatedClaim` and `Claims::DistributedClaim` classes. They have never been required, instantiated, or reachable through the claims DSL (`ClaimsBuilder` only builds `NormalClaim`), and the discovery document only advertises `claim_types_supported: ["normal"]` — the files just shipped in the gem unused since 2016
|
|
8
56
|
- [#324] Split `Helpers::Controller` (294 lines, one module) into focused submodules — `Prompt`, `MaxAge`, `ErrorResponse`, `TokenMatching` — and decompose the two most complex methods (`handle_oidc_prompt_param!`, `handle_oidc_max_age_param!`). This is a behavior-preserving refactor that allows dropping the `Metrics/ModuleLength`, `Metrics/CyclomaticComplexity` and `Metrics/PerceivedComplexity` overrides from `.rubocop_todo.yml`; the codebase now passes those cops at RuboCop's default thresholds
|
|
9
57
|
- [#326] Make the dynamic client registration spec robust against pre-existing `Doorkeeper::Application` rows: replace absolute `Application.count` assertions and `Application.first` lookups with relative `change` matchers and `Application.find_by(uid:)` lookups keyed on the `client_id` returned by each request. With a polluted `test.sqlite3` (e.g. left behind by a `rake server` session against the same dummy app) 12 of the 20 examples failed spuriously; they now pass regardless of prior DB state
|
data/README.md
CHANGED
|
@@ -3,25 +3,28 @@
|
|
|
3
3
|
[](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/actions/workflows/ci.yml)
|
|
4
4
|
[](https://qlty.sh/gh/doorkeeper-gem/projects/doorkeeper-openid_connect)
|
|
5
5
|
[](https://rubygems.org/gems/doorkeeper-openid_connect)
|
|
6
|
+
[](https://rubygems.org/gems/doorkeeper-openid_connect)
|
|
6
7
|
|
|
7
8
|
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.
|
|
8
9
|
|
|
9
10
|
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/).
|
|
10
11
|
|
|
12
|
+
Full documentation lives in the [wiki](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/wiki).
|
|
13
|
+
|
|
11
14
|
## Table of Contents
|
|
12
15
|
|
|
13
16
|
- [Status](#status)
|
|
14
|
-
- [Known Issues](#known-issues)
|
|
15
17
|
- [Example Applications](#example-applications)
|
|
18
|
+
- [Requirements](#requirements)
|
|
16
19
|
- [Installation](#installation)
|
|
17
|
-
- [
|
|
20
|
+
- [Documentation](#documentation)
|
|
18
21
|
- [Development](#development)
|
|
19
22
|
- [License](#license)
|
|
20
23
|
- [Sponsors](#sponsors)
|
|
21
24
|
|
|
22
25
|
## Status
|
|
23
26
|
|
|
24
|
-
The following parts of [OpenID Connect Core 1.0](http://openid.net/specs/openid-connect-core-1_0.html) are currently supported:
|
|
27
|
+
The following parts of [OpenID Connect Core 1.0](http://openid.net/specs/openid-connect-core-1_0.html) and related specifications are currently supported:
|
|
25
28
|
- [Authentication using the Authorization Code Flow](http://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth)
|
|
26
29
|
- [Authentication using the Implicit Flow](http://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth)
|
|
27
30
|
- [Requesting Claims using Scope Values](http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims)
|
|
@@ -29,20 +32,30 @@ The following parts of [OpenID Connect Core 1.0](http://openid.net/specs/openid-
|
|
|
29
32
|
- [Normal Claims](http://openid.net/specs/openid-connect-core-1_0.html#NormalClaims)
|
|
30
33
|
- [OAuth 2.0 Form Post Response Mode](https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html)
|
|
31
34
|
- [OAuth 2.0 Dynamic Client Registration Protocol](https://datatracker.ietf.org/doc/html/rfc7591)
|
|
35
|
+
- [RP-Initiated Logout 1.0](https://openid.net/specs/openid-connect-rpinitiated-1_0.html) client metadata — per-client `post_logout_redirect_uris` registration and validation; see [RP-Initiated Logout](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/wiki/RP-Initiated-Logout) for the host application's part
|
|
36
|
+
- [RFC 9207](https://www.rfc-editor.org/rfc/rfc9207) `iss` authorization response parameter, emitted when Doorkeeper itself is configured with an `issuer`
|
|
37
|
+
- [RFC 8414 Authorization Server Metadata](https://www.rfc-editor.org/rfc/rfc8414) — see [Routes](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/wiki/Routes) for how this interacts with the metadata endpoint Doorkeeper 6.0 serves itself
|
|
32
38
|
|
|
33
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.
|
|
34
40
|
|
|
35
|
-
Take a look at the [DiscoveryController](app/controllers/doorkeeper/openid_connect/discovery_controller.rb) for more details on supported features.
|
|
36
|
-
|
|
37
|
-
### Known Issues
|
|
38
|
-
|
|
39
|
-
- Doorkeeper's API mode (`Doorkeeper.configuration.api_only`) is not properly supported yet
|
|
41
|
+
Take a look at the [DiscoveryController](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/blob/master/app/controllers/doorkeeper/openid_connect/discovery_controller.rb) for more details on supported features.
|
|
40
42
|
|
|
41
43
|
### Example Applications
|
|
42
44
|
|
|
43
|
-
- [GitLab](https://gitlab.com/gitlab-org/gitlab
|
|
45
|
+
- [GitLab](https://gitlab.com/gitlab-org/gitlab) ([original MR](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8018))
|
|
44
46
|
- [Testing app for this gem](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/tree/master/spec/dummy)
|
|
45
47
|
|
|
48
|
+
## Requirements
|
|
49
|
+
|
|
50
|
+
| Dependency | Supported versions |
|
|
51
|
+
| --- | --- |
|
|
52
|
+
| Ruby | 3.2 or newer |
|
|
53
|
+
| Rails | 7.0 to 8.1 |
|
|
54
|
+
| Doorkeeper | 5.5 or newer, below 7.0 |
|
|
55
|
+
| ORM | Active Record only |
|
|
56
|
+
|
|
57
|
+
The [CI matrix](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/blob/master/.github/workflows/ci.yml) is the authoritative statement of what is tested: each Rails series above against Ruby 3.2 through 4.0 and — except for Rails 7.0 — against `ruby-head`, plus one build per supported Doorkeeper series and one against Doorkeeper's `main` branch.
|
|
58
|
+
|
|
46
59
|
## Installation
|
|
47
60
|
|
|
48
61
|
Make sure your application is already set up with [Doorkeeper](https://github.com/doorkeeper-gem/doorkeeper#installation).
|
|
@@ -63,22 +76,22 @@ Generate a migration for Active Record (other ORMs are currently not supported):
|
|
|
63
76
|
|
|
64
77
|
```sh
|
|
65
78
|
rails generate doorkeeper:openid_connect:migration
|
|
66
|
-
|
|
79
|
+
rails db:migrate
|
|
67
80
|
```
|
|
68
81
|
|
|
69
82
|
If you're upgrading from an earlier version, check [Migration from Old Versions](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/wiki/Migration-from-Old-Versions)
|
|
70
|
-
wiki and [CHANGELOG.md](CHANGELOG.md) for upgrade instructions
|
|
83
|
+
wiki and [CHANGELOG.md](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/blob/master/CHANGELOG.md) for upgrade instructions, including the
|
|
84
|
+
migrations that newer versions add to existing installations.
|
|
71
85
|
|
|
72
|
-
##
|
|
86
|
+
## Documentation
|
|
73
87
|
|
|
74
|
-
|
|
88
|
+
Configuration and usage are documented in the [wiki](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/wiki), whose home page indexes every topic. The pages to start from:
|
|
75
89
|
|
|
76
|
-
- [
|
|
77
|
-
- [
|
|
78
|
-
- [
|
|
79
|
-
|
|
80
|
-
-
|
|
81
|
-
- [Dynamic Client Registration](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/wiki/Dynamic-Client-Registration)
|
|
90
|
+
- [Configuration](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/wiki/Configuration) — the issuer, subject, signing keys, and every other initializer option
|
|
91
|
+
- [Migration from Old Versions](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/wiki/Migration-from-Old-Versions) — upgrade instructions for breaking changes
|
|
92
|
+
- [Troubleshooting](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/wiki/Troubleshooting) — symptoms, causes, and fixes for common integration pitfalls
|
|
93
|
+
|
|
94
|
+
The remaining pages cover scopes and claims, `prompt` and `max_age`, routes and multiple mounts, nonces, RP-Initiated Logout, Dynamic Client Registration, and I18n.
|
|
82
95
|
|
|
83
96
|
## Development
|
|
84
97
|
|
|
@@ -102,9 +115,23 @@ To run the local engine server:
|
|
|
102
115
|
bundle exec rake server
|
|
103
116
|
```
|
|
104
117
|
|
|
105
|
-
|
|
118
|
+
To run the browser end-to-end tests, which boot the dummy app with
|
|
119
|
+
[Capybara](https://github.com/teamcapybara/capybara) and drive its dashboard
|
|
120
|
+
through [Cuprite](https://github.com/rubycdp/cuprite):
|
|
106
121
|
|
|
122
|
+
```sh
|
|
123
|
+
bundle exec rake e2e
|
|
107
124
|
```
|
|
125
|
+
|
|
126
|
+
They need an installed Chrome or Chromium and nothing else. Run them with
|
|
127
|
+
`HEADLESS=false` to watch a flow in a visible browser. The suite boots the app
|
|
128
|
+
in the development environment against its own `spec/dummy/db/e2e.sqlite3`
|
|
129
|
+
database, so it leaves the one behind `bundle exec rake server` alone, and it
|
|
130
|
+
saves the page of a failing example to `spec/dummy/tmp/e2e`.
|
|
131
|
+
|
|
132
|
+
By default, Rails 8.0 is used. To use a specific version run:
|
|
133
|
+
|
|
134
|
+
```sh
|
|
108
135
|
rails=7.2 bundle update
|
|
109
136
|
```
|
|
110
137
|
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Doorkeeper
|
|
4
|
+
module OpenidConnect
|
|
5
|
+
# Prepended to Doorkeeper::MetadataController (Doorkeeper >= 6.0) so the
|
|
6
|
+
# RFC 8414 document at `/.well-known/oauth-authorization-server` also
|
|
7
|
+
# carries the OpenID Connect metadata this gem serves from its discovery
|
|
8
|
+
# document — otherwise the two documents describe the same server with a
|
|
9
|
+
# different issuer and without the OIDC endpoints and capabilities.
|
|
10
|
+
#
|
|
11
|
+
# When mounted under a named scope, Doorkeeper's metadata route carries no
|
|
12
|
+
# `route_helper_prefix`, so the enriched endpoints resolve to the default
|
|
13
|
+
# mount — matching how the core document advertises its own endpoints
|
|
14
|
+
# there. Scoped mounts are fully served by the gem's namespaced
|
|
15
|
+
# `/.well-known/openid-configuration` document.
|
|
16
|
+
module MetadataExtension
|
|
17
|
+
include DiscoveryHelpersMixin
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def metadata_response
|
|
22
|
+
return super unless Doorkeeper::OpenidConnect.configured? && oidc_routes_mounted?
|
|
23
|
+
|
|
24
|
+
@metadata_response ||= Doorkeeper::OpenidConnect::OAuth::MetadataResponse.new(
|
|
25
|
+
request.base_url,
|
|
26
|
+
->(**args) { url_for(**args) },
|
|
27
|
+
issuer: issuer,
|
|
28
|
+
oidc_metadata: oidc_metadata,
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# This controller is reachable through Doorkeeper's own routes, so it
|
|
33
|
+
# also serves apps that configure this gem without mounting
|
|
34
|
+
# `use_doorkeeper_openid_connect` (or that skip routes through its
|
|
35
|
+
# mapping) — where the gem's URL helpers are not defined. Rather than
|
|
36
|
+
# raise, or advertise an OIDC document missing its core endpoints, fall
|
|
37
|
+
# back to the plain Doorkeeper document.
|
|
38
|
+
def oidc_routes_mounted?
|
|
39
|
+
endpoint_defined?(:oauth_userinfo_url) &&
|
|
40
|
+
endpoint_defined?(:oauth_discovery_keys_url)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def oidc_metadata
|
|
44
|
+
openid_connect = Doorkeeper::OpenidConnect.configuration
|
|
45
|
+
|
|
46
|
+
{
|
|
47
|
+
userinfo_endpoint: endpoint_url(:oauth_userinfo_url, userinfo_url_options),
|
|
48
|
+
jwks_uri: endpoint_url(:oauth_discovery_keys_url, jwks_url_options),
|
|
49
|
+
end_session_endpoint: instance_exec(&openid_connect.end_session_endpoint),
|
|
50
|
+
registration_endpoint: registration_endpoint_url(openid_connect),
|
|
51
|
+
subject_types_supported: openid_connect.subject_types_supported,
|
|
52
|
+
id_token_signing_alg_values_supported: [::Doorkeeper::OpenidConnect.signing_algorithm],
|
|
53
|
+
claim_types_supported: ["normal"],
|
|
54
|
+
claims_supported: claims_supported(openid_connect),
|
|
55
|
+
}.compact
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def registration_endpoint_url(openid_connect)
|
|
59
|
+
return unless openid_connect.dynamic_client_registration
|
|
60
|
+
# The registration route is drawn conditionally on the configuration
|
|
61
|
+
# at the time the app's routes were loaded, so it can be absent even
|
|
62
|
+
# while `dynamic_client_registration` is enabled.
|
|
63
|
+
return unless endpoint_defined?(:oauth_dynamic_client_registration_url)
|
|
64
|
+
|
|
65
|
+
endpoint_url(
|
|
66
|
+
:oauth_dynamic_client_registration_url,
|
|
67
|
+
dynamic_client_registration_url_options,
|
|
68
|
+
)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -6,6 +6,7 @@ module Doorkeeper
|
|
|
6
6
|
include Doorkeeper::Helpers::Controller
|
|
7
7
|
include GrantTypesSupportedMixin
|
|
8
8
|
include TokenEndpointAuthMethodsSupportedMixin
|
|
9
|
+
include DiscoveryHelpersMixin
|
|
9
10
|
|
|
10
11
|
WEBFINGER_RELATION = "http://openid.net/specs/connect/1.0/issuer"
|
|
11
12
|
|
|
@@ -14,7 +15,11 @@ module Doorkeeper
|
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def webfinger
|
|
17
|
-
|
|
18
|
+
# RFC 7033 §5: the WebFinger resource must be queryable from browser
|
|
19
|
+
# scripts on other origins, §10.2: JRD responses use the dedicated
|
|
20
|
+
# `application/jrd+json` media type.
|
|
21
|
+
response.headers["Access-Control-Allow-Origin"] = "*"
|
|
22
|
+
render json: webfinger_response, content_type: "application/jrd+json"
|
|
18
23
|
end
|
|
19
24
|
|
|
20
25
|
def keys
|
|
@@ -29,18 +34,17 @@ module Doorkeeper
|
|
|
29
34
|
|
|
30
35
|
{
|
|
31
36
|
issuer: issuer,
|
|
32
|
-
authorization_endpoint: oauth_authorization_url
|
|
33
|
-
token_endpoint: oauth_token_url
|
|
34
|
-
revocation_endpoint: oauth_revoke_url
|
|
35
|
-
introspection_endpoint:
|
|
36
|
-
userinfo_endpoint: oauth_userinfo_url
|
|
37
|
-
jwks_uri: oauth_discovery_keys_url
|
|
37
|
+
authorization_endpoint: endpoint_url(:oauth_authorization_url, authorization_url_options),
|
|
38
|
+
token_endpoint: endpoint_url(:oauth_token_url, token_url_options),
|
|
39
|
+
revocation_endpoint: endpoint_url(:oauth_revoke_url, revocation_url_options),
|
|
40
|
+
introspection_endpoint: endpoint_defined?(:oauth_introspect_url) ? endpoint_url(:oauth_introspect_url, introspection_url_options) : nil,
|
|
41
|
+
userinfo_endpoint: endpoint_url(:oauth_userinfo_url, userinfo_url_options),
|
|
42
|
+
jwks_uri: endpoint_url(:oauth_discovery_keys_url, jwks_url_options),
|
|
38
43
|
end_session_endpoint: instance_exec(&openid_connect.end_session_endpoint),
|
|
39
|
-
registration_endpoint: openid_connect.dynamic_client_registration ? oauth_dynamic_client_registration_url
|
|
44
|
+
registration_endpoint: openid_connect.dynamic_client_registration ? endpoint_url(:oauth_dynamic_client_registration_url, dynamic_client_registration_url_options) : nil,
|
|
40
45
|
|
|
41
46
|
scopes_supported: doorkeeper.scopes,
|
|
42
47
|
|
|
43
|
-
# TODO: support id_token response type
|
|
44
48
|
response_types_supported: doorkeeper.authorization_response_types,
|
|
45
49
|
response_modes_supported: response_modes_supported(doorkeeper),
|
|
46
50
|
grant_types_supported: grant_types_supported(doorkeeper),
|
|
@@ -50,6 +54,12 @@ module Doorkeeper
|
|
|
50
54
|
# 'private_key_jwt'
|
|
51
55
|
token_endpoint_auth_methods_supported: token_endpoint_auth_methods_supported,
|
|
52
56
|
|
|
57
|
+
# RFC 9207: mirrors Doorkeeper's own RFC 8414 document — true exactly
|
|
58
|
+
# when Doorkeeper is configured with an issuer and therefore emits the
|
|
59
|
+
# `iss` authorization response parameter. `false` survives the
|
|
60
|
+
# `.compact` below, so it is advertised explicitly.
|
|
61
|
+
authorization_response_iss_parameter_supported: Doorkeeper::OpenidConnect.doorkeeper_issuer.present?,
|
|
62
|
+
|
|
53
63
|
subject_types_supported: openid_connect.subject_types_supported,
|
|
54
64
|
|
|
55
65
|
id_token_signing_alg_values_supported: [
|
|
@@ -64,13 +74,7 @@ module Doorkeeper
|
|
|
64
74
|
# 'distributed',
|
|
65
75
|
],
|
|
66
76
|
|
|
67
|
-
claims_supported:
|
|
68
|
-
iss
|
|
69
|
-
sub
|
|
70
|
-
aud
|
|
71
|
-
exp
|
|
72
|
-
iat
|
|
73
|
-
] | openid_connect.claims.to_h.keys,
|
|
77
|
+
claims_supported: claims_supported(openid_connect),
|
|
74
78
|
|
|
75
79
|
code_challenge_methods_supported: code_challenge_methods_supported(doorkeeper),
|
|
76
80
|
}.compact
|
|
@@ -105,32 +109,6 @@ module Doorkeeper
|
|
|
105
109
|
def keys_response
|
|
106
110
|
{ keys: Doorkeeper::OpenidConnect.signing_keys_normalized }
|
|
107
111
|
end
|
|
108
|
-
|
|
109
|
-
def protocol
|
|
110
|
-
configured = Doorkeeper::OpenidConnect.configuration.protocol
|
|
111
|
-
configured.respond_to?(:call) ? configured.call : configured
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def discovery_url_options
|
|
115
|
-
Doorkeeper::OpenidConnect.configuration.discovery_url_options.call(request)
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def discovery_url_default_options
|
|
119
|
-
{
|
|
120
|
-
protocol: protocol,
|
|
121
|
-
}
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
def issuer
|
|
125
|
-
Doorkeeper::OpenidConnect.resolve_issuer(request: request)
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
%i[authorization token revocation introspection userinfo jwks
|
|
129
|
-
dynamic_client_registration].each do |endpoint|
|
|
130
|
-
define_method :"#{endpoint}_url_options" do
|
|
131
|
-
discovery_url_default_options.merge(discovery_url_options[endpoint.to_sym] || {})
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
112
|
end
|
|
135
113
|
end
|
|
136
114
|
end
|
|
@@ -13,11 +13,13 @@ module Doorkeeper
|
|
|
13
13
|
return
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
client = Doorkeeper
|
|
16
|
+
client = Doorkeeper.configuration.application_model.create!(application_params(registration))
|
|
17
17
|
render json: registration_response(client, registration), status: :created
|
|
18
18
|
rescue ActiveRecord::RecordInvalid => e
|
|
19
|
-
render json: {
|
|
20
|
-
|
|
19
|
+
render json: {
|
|
20
|
+
error: registration_error_code(e.record),
|
|
21
|
+
error_description: e.record.errors.full_messages.join(", "),
|
|
22
|
+
}, status: :bad_request
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
private
|
|
@@ -47,19 +49,43 @@ module Doorkeeper
|
|
|
47
49
|
end
|
|
48
50
|
end
|
|
49
51
|
|
|
52
|
+
# RFC 7591 §3.2.2 registration error codes: `invalid_redirect_uri` for
|
|
53
|
+
# redirect URI problems, `invalid_client_metadata` for everything else.
|
|
54
|
+
def registration_error_code(record)
|
|
55
|
+
record.errors.include?(:redirect_uri) ? "invalid_redirect_uri" : "invalid_client_metadata"
|
|
56
|
+
end
|
|
57
|
+
|
|
50
58
|
def application_params(registration)
|
|
51
|
-
{
|
|
59
|
+
application_params = {
|
|
52
60
|
name: params[:client_name],
|
|
53
61
|
redirect_uri: params[:redirect_uris] || [],
|
|
54
62
|
scopes: registration.permitted_scopes,
|
|
55
63
|
confidential: registration.confidential_client?,
|
|
56
64
|
}
|
|
65
|
+
|
|
66
|
+
# Existing installations may not have run the migration that adds the
|
|
67
|
+
# `post_logout_redirect_uris` column yet. RFC 7591 §2 allows the server
|
|
68
|
+
# to ignore client metadata it does not understand, so the parameter is
|
|
69
|
+
# simply dropped in that case instead of failing the registration.
|
|
70
|
+
if post_logout_redirect_uris_supported?
|
|
71
|
+
application_params[:post_logout_redirect_uris] = params[:post_logout_redirect_uris] || []
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
application_params
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def post_logout_redirect_uris_supported?
|
|
78
|
+
Doorkeeper.config.application_model.column_names.include?("post_logout_redirect_uris")
|
|
57
79
|
end
|
|
58
80
|
|
|
59
81
|
def registration_response(doorkeeper_application, registration)
|
|
60
82
|
response = {
|
|
61
83
|
client_id: doorkeeper_application.uid,
|
|
62
84
|
client_id_issued_at: doorkeeper_application.created_at.to_i,
|
|
85
|
+
# RFC 7591 §3.2.1: the response must include all registered client
|
|
86
|
+
# metadata. The name is always present on a successfully created
|
|
87
|
+
# application (the model validates its presence).
|
|
88
|
+
client_name: doorkeeper_application.name,
|
|
63
89
|
redirect_uris: doorkeeper_application.redirect_uri.split,
|
|
64
90
|
token_endpoint_auth_method: registration.token_endpoint_auth_method,
|
|
65
91
|
token_endpoint_auth_methods_supported: registration.token_endpoint_auth_methods_supported,
|
|
@@ -69,6 +95,11 @@ module Doorkeeper
|
|
|
69
95
|
application_type: registration.requested_application_type,
|
|
70
96
|
}
|
|
71
97
|
|
|
98
|
+
# Registration is optional (RP-Initiated Logout §2), so the metadata
|
|
99
|
+
# field is only echoed when post-logout redirect URIs were registered.
|
|
100
|
+
post_logout_uris = doorkeeper_application.post_logout_redirect_uris
|
|
101
|
+
response[:post_logout_redirect_uris] = post_logout_uris if post_logout_uris.present?
|
|
102
|
+
|
|
72
103
|
if registration.confidential_client?
|
|
73
104
|
response[:client_secret] =
|
|
74
105
|
doorkeeper_application.plaintext_secret || doorkeeper_application.secret
|
|
@@ -6,7 +6,27 @@ module Doorkeeper
|
|
|
6
6
|
before_action -> { doorkeeper_authorize! :openid }
|
|
7
7
|
|
|
8
8
|
def show
|
|
9
|
-
|
|
9
|
+
user_info = Doorkeeper::OpenidConnect.configuration.user_info_model.new(doorkeeper_token)
|
|
10
|
+
|
|
11
|
+
# A token can carry the openid scope yet resolve to no end user — a
|
|
12
|
+
# client_credentials token, or an owner deleted after issuance. The
|
|
13
|
+
# UserInfo response is a statement about the End-User, so such a token
|
|
14
|
+
# is not valid at this endpoint: answer with RFC 6750's 401
|
|
15
|
+
# invalid_token instead of letting the claim generators dereference a
|
|
16
|
+
# nil owner (500).
|
|
17
|
+
if user_info.respond_to?(:resource_owner) && user_info.resource_owner.nil?
|
|
18
|
+
render_resource_owner_missing_error
|
|
19
|
+
else
|
|
20
|
+
render json: user_info, status: :ok
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def render_resource_owner_missing_error
|
|
27
|
+
error = Doorkeeper::OAuth::InvalidTokenResponse.from_access_token(doorkeeper_token)
|
|
28
|
+
response.headers.merge!(error.headers)
|
|
29
|
+
render json: error.body, status: error.status
|
|
10
30
|
end
|
|
11
31
|
end
|
|
12
32
|
end
|
data/config/locales/en.yml
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
en:
|
|
2
|
+
activerecord:
|
|
3
|
+
attributes:
|
|
4
|
+
doorkeeper/application:
|
|
5
|
+
post_logout_redirect_uris: 'Post Logout Redirect URIs'
|
|
6
|
+
errors:
|
|
7
|
+
models:
|
|
8
|
+
doorkeeper/application:
|
|
9
|
+
attributes:
|
|
10
|
+
# Mirror Doorkeeper's own redirect_uri error messages so that an
|
|
11
|
+
# invalid post_logout_redirect_uris value (validated through
|
|
12
|
+
# Doorkeeper::RedirectUriValidator) produces a readable message.
|
|
13
|
+
post_logout_redirect_uris:
|
|
14
|
+
fragment_present: 'cannot contain a fragment.'
|
|
15
|
+
invalid_uri: 'must be a valid URI.'
|
|
16
|
+
unspecified_scheme: 'must specify a scheme.'
|
|
17
|
+
relative_uri: 'must be an absolute URI.'
|
|
18
|
+
secured_uri: 'must be an HTTPS/SSL URI.'
|
|
19
|
+
forbidden_uri: 'is forbidden by the server.'
|
|
2
20
|
doorkeeper:
|
|
3
21
|
scopes:
|
|
4
22
|
openid: 'Authenticate your account'
|
|
@@ -12,11 +12,7 @@ module Doorkeeper
|
|
|
12
12
|
|
|
13
13
|
def authorize
|
|
14
14
|
@auth = Authorization::Token.new(pre_auth, resource_owner)
|
|
15
|
-
|
|
16
|
-
@auth.issue_token!
|
|
17
|
-
else
|
|
18
|
-
@auth.issue_token
|
|
19
|
-
end
|
|
15
|
+
@auth.issue_token!
|
|
20
16
|
response
|
|
21
17
|
end
|
|
22
18
|
|
|
@@ -28,7 +24,8 @@ module Doorkeeper
|
|
|
28
24
|
private
|
|
29
25
|
|
|
30
26
|
def response
|
|
31
|
-
id_token = Doorkeeper::OpenidConnect
|
|
27
|
+
id_token = Doorkeeper::OpenidConnect.configuration.id_token_model
|
|
28
|
+
.new(auth.token, pre_auth.nonce)
|
|
32
29
|
|
|
33
30
|
IdTokenResponse.new(pre_auth, auth, id_token)
|
|
34
31
|
end
|
|
@@ -18,16 +18,40 @@ module Doorkeeper
|
|
|
18
18
|
true
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
+
# Expose the issued access token, mirroring core `CodeResponse` /
|
|
22
|
+
# `TokenResponse`. `after_successful_authorization` hooks read
|
|
23
|
+
# `context.issued_token` (via `Hooks::Context#issued_token`), which
|
|
24
|
+
# would otherwise raise `NoMethodError` for the `id_token` and
|
|
25
|
+
# `id_token token` response types.
|
|
26
|
+
def issued_token
|
|
27
|
+
auth.token
|
|
28
|
+
end
|
|
29
|
+
|
|
21
30
|
def body
|
|
22
31
|
{
|
|
23
32
|
state: pre_auth.state,
|
|
24
33
|
id_token: id_token.as_jws_token,
|
|
25
|
-
}
|
|
34
|
+
}.merge(iss_parameter)
|
|
26
35
|
end
|
|
27
36
|
|
|
28
37
|
def redirect_uri
|
|
29
38
|
Authorization::URIBuilder.uri_with_fragment(pre_auth.redirect_uri, body)
|
|
30
39
|
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
# RFC 9207 Authorization Server Issuer Identification. Emitted only when
|
|
44
|
+
# Doorkeeper itself is configured with an issuer, mirroring the gating of
|
|
45
|
+
# Doorkeeper's CodeResponse and its advertised
|
|
46
|
+
# `authorization_response_iss_parameter_supported` metadata flag. The
|
|
47
|
+
# value is this response's ID Token `iss` claim: RFC 9207 §2 requires the
|
|
48
|
+
# `iss` parameter to be identical to the `iss` claim of an ID Token
|
|
49
|
+
# returned from the authorization endpoint.
|
|
50
|
+
def iss_parameter
|
|
51
|
+
return {} if Doorkeeper::OpenidConnect.doorkeeper_issuer.blank?
|
|
52
|
+
|
|
53
|
+
{ iss: id_token.issuer }
|
|
54
|
+
end
|
|
31
55
|
end
|
|
32
56
|
end
|
|
33
57
|
end
|
|
@@ -6,7 +6,12 @@ module Doorkeeper
|
|
|
6
6
|
private
|
|
7
7
|
|
|
8
8
|
def response
|
|
9
|
-
|
|
9
|
+
# `extend` is a no-op when the concern is already in the ancestry
|
|
10
|
+
# (e.g. a custom id_token_class that includes it), so the same path
|
|
11
|
+
# serves the default and any custom id_token_class alike.
|
|
12
|
+
id_token_token = Doorkeeper::OpenidConnect.configuration.id_token_model
|
|
13
|
+
.new(auth.token, pre_auth.nonce)
|
|
14
|
+
.extend(Doorkeeper::OpenidConnect::HybridIdTokenConcern)
|
|
10
15
|
|
|
11
16
|
IdTokenTokenResponse.new(pre_auth, auth, id_token_token)
|
|
12
17
|
end
|
|
@@ -5,7 +5,11 @@ module Doorkeeper
|
|
|
5
5
|
class IdTokenTokenResponse < IdTokenResponse
|
|
6
6
|
def body
|
|
7
7
|
super.merge({
|
|
8
|
-
|
|
8
|
+
# `plaintext_token`, not `token`: with a hashing token-secret
|
|
9
|
+
# strategy the stored `token` attribute is the hash, so returning it
|
|
10
|
+
# would hand the client an unusable access token (mirrors core
|
|
11
|
+
# `CodeResponse` / `TokenResponse`, which return `plaintext_token`).
|
|
12
|
+
access_token: auth.token.plaintext_token,
|
|
9
13
|
token_type: auth.token.token_type,
|
|
10
14
|
expires_in: auth.token.expires_in_seconds,
|
|
11
15
|
})
|
|
@@ -21,7 +21,11 @@ module Doorkeeper
|
|
|
21
21
|
|
|
22
22
|
def initialize(options = {})
|
|
23
23
|
@name = options[:name].to_sym
|
|
24
|
-
|
|
24
|
+
# Symbolize so a claim configured with string responses
|
|
25
|
+
# (`response: ["id_token"]`) matches the symbol tokens the builder
|
|
26
|
+
# dispatches with (`:id_token` / `:user_info`); otherwise such a
|
|
27
|
+
# claim would be silently dropped from every response.
|
|
28
|
+
@response = Array.wrap(options[:response]).compact.map(&:to_sym).freeze
|
|
25
29
|
@scopes = normalize_scopes(options[:scope])
|
|
26
30
|
|
|
27
31
|
# use default scope for Standard Claims, fallback to profile
|
|
@@ -5,8 +5,17 @@ require "ostruct"
|
|
|
5
5
|
module Doorkeeper
|
|
6
6
|
module OpenidConnect
|
|
7
7
|
class ClaimsBuilder
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
# Sentinel distinct from any real resource owner (including `nil`) so a
|
|
9
|
+
# caller that already resolved the owner can pass it in — even a nil one —
|
|
10
|
+
# and skip the second `resource_owner_from_access_token` lookup.
|
|
11
|
+
NO_RESOURCE_OWNER = Object.new
|
|
12
|
+
private_constant :NO_RESOURCE_OWNER
|
|
13
|
+
|
|
14
|
+
def self.generate(access_token, response, resource_owner = NO_RESOURCE_OWNER)
|
|
15
|
+
if resource_owner.equal?(NO_RESOURCE_OWNER)
|
|
16
|
+
resource_owner =
|
|
17
|
+
Doorkeeper::OpenidConnect.configuration.resource_owner_from_access_token.call(access_token)
|
|
18
|
+
end
|
|
10
19
|
|
|
11
20
|
Doorkeeper::OpenidConnect.configuration.claims.to_h.map do |name, claim|
|
|
12
21
|
if claim.scopes.any? { |scope| access_token.scopes.exists?(scope) } &&
|