Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds mandatory support for the OAuth 2.0 Client Credentials Grant to the Solid-OIDC specification to enable non-interactive authentication for scripts, automated agents, and server-to-server communication. Both major implementations (Community Solid Server and Enterprise Solid Server) already support this feature.
Changes:
- Added Client Credentials Grant as a MUST requirement for OpenID Providers
- Updated Core Concepts section to clarify support for both interactive (Authorization Code + PKCE) and non-interactive (Client Credentials) authentication flows
- Updated discovery requirements to mandate advertising
client_credentialsingrant_types_supportedmetadata - Updated Token Instantiation section to explicitly cover both Authorization Code Grant and Client Credentials Grant
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| with `grant_type=client_credentials` and the `webid` scope. | ||
|
|
||
| The OP MUST validate the `client_id` and `client_secret`, and if valid, MUST return | ||
| a DPoP-bound Access Token. The Client MUST include a valid DPoP proof [[!DPOP]] |
There was a problem hiding this comment.
There's an inconsistency between this statement and line 319 in the Token Instantiation section. This line states the OP must return "a DPoP-bound Access Token" for the Client Credentials Grant, but line 319 (which explicitly covers both Authorization Code Grant and Client Credentials Grant per line 316) states "the OP MUST return a DPoP-bound OIDC ID Token". These two statements need to be aligned. Based on the structure of the specification and line 319's scope covering both grant types, this should likely say "a DPoP-bound OIDC ID Token" instead of "Access Token".
| a DPoP-bound Access Token. The Client MUST include a valid DPoP proof [[!DPOP]] | |
| a DPoP-bound OIDC ID Token. The Client MUST include a valid DPoP proof [[!DPOP]] |
There was a problem hiding this comment.
ID Tokens are only meaningful terms in the context of OIDC, in the context of the client credentials grant of OAuth2 one should use "Access Tokens" as the proper terminology.
There was a problem hiding this comment.
This also hints at some long-standing challenges with Solid-OIDC. In Solid-OIDC, an OpenID provider generates ID tokens for use with Solid Clients and Servers, but these ID tokens are used as Access Tokens. Arguably, this is incorrect.
Furthermore, DPoP is defined as a mechanism to protect Access Tokens. Using DPoP with ID Tokens is not defined. Insofar as Solid-OIDC is about defining ID Tokens, it is incorrect to use DPoP, and insofar as Solid-OIDC is a about defining Access Tokens, it is correct to use DPoP but incorrect to use OpenID Connect.
| When using the Client Credentials Grant, the Client authenticates with the OP using a | ||
| `client_id` and `client_secret` pair previously obtained through client registration | ||
| (either static or dynamic). The Client sends a token request to the OP's token endpoint | ||
| with `grant_type=client_credentials` and the `webid` scope. |
There was a problem hiding this comment.
There's a potential contradiction with the statement at lines 121-122 which says "client registration, whether dynamic, or static, is entirely optional." The Client Credentials Grant inherently requires client registration to obtain the client_id and client_secret pair. Consider either: (1) clarifying at lines 121-122 that client registration is optional for some flows but required for Client Credentials Grant, or (2) adding a note in the Client Credentials section that explicitly acknowledges this requirement represents an exception to the general optional nature of client registration mentioned in the Core Concepts section.
| When using the Client Credentials Grant, the Client authenticates with the OP using a | |
| `client_id` and `client_secret` pair previously obtained through client registration | |
| (either static or dynamic). The Client sends a token request to the OP's token endpoint | |
| with `grant_type=client_credentials` and the `webid` scope. | |
| When using the Client Credentials Grant, the Client MUST be registered with the OP and | |
| authenticate using a `client_id` and `client_secret` pair previously obtained through | |
| client registration (either static or dynamic). This requirement is an exception to the | |
| general statement in the Core Concepts section that client registration is optional. The | |
| Client sends a token request to the OP's token endpoint with `grant_type=client_credentials` | |
| and the `webid` scope. |
There was a problem hiding this comment.
@acoburn @joachimvh can you confirm this is accurate with your implementations?
| Additionally, the OP MUST include `client_credentials` in its `grant_types_supported` | ||
| metadata property to indicate support for non-interactive authentication | ||
| via the Client Credentials Grant (see [[#client-credentials]]). |
There was a problem hiding this comment.
This requirement duplicates the one already stated in the Client Credentials Grant section (lines 310-311). The same requirement appears twice: once in the Client Credentials Grant section and once here in the Conformance Discovery section. Consider removing the duplication by keeping only one of these statements, or if both are intentional, clarify why the requirement is repeated. Typically, the discovery/conformance section would be the natural place for such metadata requirements, making lines 310-311 potentially redundant.
| Additionally, the OP MUST include `client_credentials` in its `grant_types_supported` | |
| metadata property to indicate support for non-interactive authentication | |
| via the Client Credentials Grant (see [[#client-credentials]]). | |
| Additionally, an OP that supports non-interactive authentication | |
| via the Client Credentials Grant (see [[#client-credentials]]) indicates this support by including | |
| `client_credentials` in its `grant_types_supported` metadata property. |
There was a problem hiding this comment.
Only to implement this change if we go with MAY wording over MUST.
|
@laurensdeb could you please also review it? I think we should add a note about limitation around Client IDs that are URLs, I have PR to CSS that allows it Still only one user can use client with given Client ID URL. Since it is often used for scripts that aren't multi tenant it migth be fine. In case of multi tenant clients, I also made an early draft that uses another flow/grant @acoburn does ESS support client credentials with Client ID URL? |
|
|
||
| # Client Credentials Grant # {#client-credentials} | ||
|
|
||
| OpenID Providers MUST support the OAuth 2.0 Client Credentials Grant [[!RFC6749]] (Section 4.4) |
There was a problem hiding this comment.
Generally OpenID Connect does not define a client credentials grant mechanism for OPs. It would be more correct to refer to Authorization Servers rather than OpenID Providers.
| communication. | ||
|
|
||
| When using the Client Credentials Grant, the Client authenticates with the OP using a | ||
| `client_id` and `client_secret` pair previously obtained through client registration |
| (either static or dynamic). The Client sends a token request to the OP's token endpoint | ||
| with `grant_type=client_credentials` and the `webid` scope. | ||
|
|
||
| The OP MUST validate the `client_id` and `client_secret`, and if valid, MUST return |
There was a problem hiding this comment.
See comment above, I would not normatively require the use of a client_secret.
| with the token request. | ||
|
|
||
| The OP MUST advertise `client_credentials` in its `grant_types_supported` | ||
| metadata property in its OpenID Connect Discovery 1.0 [[!OIDC-DISCOVERY]] document. |
There was a problem hiding this comment.
Note that the grant_types_supported metadata field of OpenID connect is optional. I don't think it makes sense to introduce a MUST therefore, in particular given that this is an OAuth grant type.
laurensdeb
left a comment
There was a problem hiding this comment.
I generally don't think it makes a lot of sense to introduce client_credentials grant as part of the Solid-OIDC specification. The general remarks I made previously on supporting additional grant types are still quite relevant here.
The main issue I see is that OIDC builds on top of the OAuth2 protocol, therefore it would make more sense to do a thorough refactoring here and extract aspects specific to OAuth in a Solid-OAuth specification, and have the Solid-OIDC specification extend that for the authorization_code grant.
The introduction of a Solid-OAuth specification would have the benefit of being able to e.g. drop the requirement of DPoP for client_credentials grant, as it makes very little sense for a confidential client (which would typically be the case for a client_credentials based flow).
@laurensdeb could you please clarify? Even with confidential clients, when |
acoburn
left a comment
There was a problem hiding this comment.
Rather than focus on particular line changes in this PR, there are some high level issues that would be good to clarify.
- Use cases: this change seems to be motivated by a desire to support scripts and bots. As such, there are several different ways to address this, and
client_credentialsis just one approach. There is also the use of refresh tokens (already compatible with Solid-OIDC) and other mechanisms such as thejwt-bearergrant type from RFC 7523. Client Credentials (as typically implemented with a client_id/client_secret pair) has some notable security concerns (e.g. relying on a shared secret rather than on public key cryptography). Adding a hard requirement on this for Solid-OIDC may be misguided. - OAuth vs OpenID Connect: Solid-OIDC is clearly a mechanism to integrate Solid with OpenID Connect. As such, Solid-OIDC supports browser-based authentication flows (
authorization_codeflow), since that is the motivating use case for OpenID Connect. Adding a grant type from OAuth 2 is not the best fit for an OpenID Connect profile. Here, an authentication mechanism defined in a different specification (e.g., Solid-OAuth) may be a better approach - Identity binding: While the Inrupt ESS platform currently supports client credential flows via its OpenID Connect broker, one challenge is that any client_credential grant needs a pre-existing identity binding. Typically, a
client_idvalue is an opaque UUID and scoped to a particular OP. The only way to ensure that this client_id value is bound to a WebID identity is to do so at registration time. Note that, functionally, this is nearly identical to using a refresh token. And specifically, this does not address the case of authenticating autonomous bots. - Alternatives: I would highly recommend considering alternatives, such as the use of Client Id Metadata documents, which largely derives from Solid-OIDC and adds features that are needed for autonomous bots, such as authentication.
If there were some |
|
In this sketch https://elf-pavlik.github.io/lws-auth/view/oidc/?dynamic=sequence |
|
@elf-pavlik As Aaron mentioned, in a more general Solid-OAuth scenario an audience constrained access token would make more sense than a sender constrained access token using DPoP. I agree that there still is a risk of a malicious RS or AS intercepting a token, so a mechanism still needs to be in place to constrain the token to a target. |
This PR makes client credentials a MUST as part of the solid-oidc specification. The CSS and ESS both currently implement client credentials. There respective documentation can be found as follows:
Questions:
cc @acoburn @joachimvh @elf-pavlik @thhck @uvdsl @dmitrizagidulin