OpenID4VP icon indicating copy to clipboard operation
OpenID4VP copied to clipboard

Client Identifier Prefix and URL ambiguity

Open erincandescent opened this issue 7 months ago • 4 comments

I realise there has historically been a flurry of Client Identifier Prefix/Scheme related issues (#505, #376, #351, #554, #466, ...) but I think there is one issue remaining

There is a longstanding understanding of the necessity within an OAuth 2/OpenID Connect environment of preventing confusion between client IDs and User/Subject IDs. For example, RFC 9068 says

Authorization servers should prevent scenarios where clients can affect the value of the "sub" claim in ways that could confuse resource servers. For example, if the authorization server elects to use the client_id as the "sub" value for access tokens issued using the client credentials grant, the authorization server should prevent clients from registering an arbitrary client_id value, as this would allow malicious clients to select the sub of a high-privilege resource owner and confuse any authorization logic on the resource server relying on the "sub" value. For more details, please refer to Section 4.14 of [OAuth2.Security.BestPractices].

To prevent cross-JWT confusion, authorization servers MUST use a distinct identifier as an "aud" claim value to uniquely identify access tokens issued by the same issuer for distinct resources. For more details on cross-JWT confusion, please refer to Section 2.8 of [RFC8725].

Authorization server implementations may put client IDs in the sub (client credentials grant), client_id (RFC 9068 style access tokens), and aud (OIDC ID tokens) claims. In addition they may put relying party identifiers, typically URLs, in the aud cliam of both access tokens and ID tokens.

To put it simply: an OAuth 2.0/OIDC implementation may already be using URLs as identifiers in ways that could cause confusion with the client identifier schemes introduced in this specification. As defined at present, there is no way of identifying whether the prefix is a Client Identifier Prefix or a URL scheme.

Except, for all but one of the prefixes defined by this document, it is in fact possible to distinguish these two. RFC 3968 defines a URI scheme as:

      scheme      = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )

All of the Client Identifier Prefixes defined in OpenID4VP other than origin contain an underscore, rendering them an invalid URI scheme. If the origin prefix were changed to e.g. web_origin, then the Client ID prefix syntax could be defined as e.g. the regex [a-z][a-z0-9]*(_[a-z0-9]+)+ making the two mutually exclusive.

JWT defines the syntax of the identifier claims as StringOrURI:

StringOrURI
      A JSON string value, with the additional requirement that while
      arbitrary string values MAY be used, any value containing a ":"
      character MUST be a URI [[RFC3986](https://www.rfc-editor.org/rfc/rfc3986)].  StringOrURI values are
      compared as case-sensitive strings with no transformations or
      canonicalizations applied.

This implies that no existing valid user can have subject identifiers in conflict with client identifiers defined with a client identifier prefix. Technically OpenID4VP JWTs are invalid per the JWT spec; but OpenID4VP can be said to be extending the specification here.

When @aaronpk brings his client-id-scheme draft back to the oauthwg, presumbaly it would establish a registry of such schemes and note the restriction that they must contain an underscore to render them illegal as URI schemes.

erincandescent avatar Apr 28 '25 22:04 erincandescent

I'm not sure I'm following this part:

an OAuth 2.0/OIDC implementation may already be using URLs as identifiers in ways that could cause confusion with the client identifier schemes introduced in this specification

I find it highly unlikely that any implementation would already be using (say) x509_san_dns:client.example.org in any of these fields so I'm not sure what that could be confused with? Could you expand on what value could be confusing and in what case please?

jogu avatar May 01 '25 17:05 jogu

As the author of StringOrURI, I'll say that our current Client ID syntax is a legal String. No need for changes.

I suggest that we close this issue on this basis.

selfissued avatar May 12 '25 12:05 selfissued

As the author of StringOrURI, I'll say that our current Client ID syntax is a legal String.

I am genuinely perplexed by this statement. The current Client ID syntax in unambiguously not conformant to the StringOrURI datatype definition (as @erincandescent alludes in the issue description with "Technically OpenID4VP JWTs are invalid per the JWT spec"). Thus, when used in a claim like aud that's defined as containing a StringOrURI value, something is definitely being violated (though the implications of the violation are unclear). Are you suggesting, as the author of StringOrURI, that the intent was something different than the text in RFC7519? That would suggest an erratum or update to RFC7519. Being the author of something, however, doesn't bestow authority to declare an alternate meaning to something.

I've argued elsewhere (a slack or signal or similar group somewhere) that not conforming to RFC7519's StringOrURI definition in aud/iss/sub is probably not really a problem in practice because most implementations (those that I'm aware of anyway) do not seem to do anything to actively enforce it on either the sending or receiving side. A hidden assumption like that is probably somewhat irresponsible too. But feels to me like a different and lesser level. It'd maybe be worthwhile for OpenID4VP to at least mention the contradiction/violation and justification/explanation for it.

I suggest that we close this issue on this basis.

I believe the StringOrURI thing is only a part of @erincandescent's issue here though so, even if correct, that basis would not be sufficient.

bc-pi avatar May 13 '25 16:05 bc-pi

All of the Client Identifier Prefixes defined in OpenID4VP other than origin contain an underscore, rendering them an invalid URI scheme. If the origin prefix were changed to e.g. web_origin, then the Client ID prefix syntax could be defined as e.g. the regex [a-z][a-z0-9]*(_[a-z0-9]+)+ making the two mutually exclusive.

That was the name before we tried to broaden it a bit since that mechanism now also allows for platform calls (e.g., other apps), not only calls from the browser.

I don't think we have a problem with origin though, since it cannot be present in a request, only a response - it is sort of a virtual scheme, just reserved to avoid collision. In the context of a browser-based flow, a response with origin would arrive via the Digital Credentials API, which would allow for easy/separate handling.

c2bo avatar May 13 '25 17:05 c2bo