[Openid-specs-ab] OpenID Connect Key Binding vs OpenID Connect UserInfo Verifiable Credentials
Jacob Ideskog
jacob.ideskog at curity.io
Mon Sep 8 20:02:49 UTC 2025
Just one more comment ( two points ).
1.
> > zero OP interest
We are interested in this, it does make sense in several use cases.
2.
Let's never forget SAML :) . The SAML model is a bit more comprehensive but
essentially similar. The Holder of Key spec defines more or less this
scheme IINM. The difference is that in SAML the asserting party and the
identity provider may or may not be the same. In the HoK pattern the
asserting party is thought to be an RP (which itself could be an IdP).
Translated to OIDC, an OP may also be an RP. So if an OP receives an ID
token from an upstream IDP (OP), having that key bound could be useful when
proving authentication events further on. But even if it's not an OP it
could be the asserting party.
/Jacob
On Mon, 8 Sept 2025 at 13:28, Dick Hardt via Openid-specs-ab <
openid-specs-ab at lists.openid.net> wrote:
> > Finally, to Dick’s points about RP1 (really the OAuth client) sending it
> to RP2, I believe that creates a mutually exclusive decision for the OP. If
> the client requests claims that MUST NOT be sent to RP2, then what is the
> OP supposed to do? Reject the request? Send back an id_token that is
> insufficient for the client (RP1) but good for RP2? Send back an id_token
> that works for both the client and RP2 which has leaked privacy claims?
>
> RP1 is not an OAuth client -- it is an RP. It does not want authorization,
> it wants authentication. The OP cannot prevent RP1 from sending any
> information it wants to RP2 independent of it being in an id_token or in
> another part of the communication -- what RP1 shares with RP2 is going to
> be based on business decisions, not a technical barrier of it not being in
> an id_token.
>
> On Mon, Sep 8, 2025 at 12:17 PM <george at practicalidentity.com> wrote:
>
>> I’m going to respond to a couple points from different emails here as
>> it’s easier to do it in one post :)
>>
>> Dick asked why I didn’t object to ID-JAG as the ‘aud’ rule isn’t applied
>> by the OP in that draft.
>>
>> For me, the reason is that back when we did OpenID Connect Core, there
>> was the issue of the id_token_hint parameter which meant sending the
>> id_token back to the issuer that issued it. We had the discussion at that
>> time and the way I remember it, we all agreed that it was ok for the
>> id_token to be sent back to its issuing OP. I believe Karl makes the same
>> point. I don’t see any privacy risks here either as the OP put all the
>> claims into the id_token.
>>
>> Now regarding the comment about the Native SSO spec, in that spec also,
>> the id_token is ONLY sent to the OP that issued it. Sending the id_token to
>> a different OP would be outside the intent of that spec. As for clients
>> written by the same company sharing the id_token, you could say that is an
>> abuse of the ’aud’ rules and in fact there has been push back against the
>> Native SSO spec for it’s use of the id_token.
>>
>> Regarding the Kubctl use of the id_token, I worked with my colleague at
>> Capital One to get this changed to using a JWT based access token as the
>> purpose of the token in the K8 use case was for authorization NOT
>> authentication context.
>>
>> Finally, to Dick’s points about RP1 (really the OAuth client) sending it
>> to RP2, I believe that creates a mutually exclusive decision for the OP. If
>> the client requests claims that MUST NOT be sent to RP2, then what is the
>> OP supposed to do? Reject the request? Send back an id_token that is
>> insufficient for the client (RP1) but good for RP2? Send back an id_token
>> that works for both the client and RP2 which has leaked privacy claims?
>>
>> I still believe the best path forward is a dedicated token for this
>> purpose. The ID-JAG model is fine, send the id_token back to the OP to
>> request an authentication assertion for RP2 and get back the token to
>> share. If there is concern that the OP then knows who the client is
>> communicating with, then make the authentication assertion usable for
>> everyone (though I daresay many enterprise IDPs would not want this
>> feature).
>>
>> Future responses today will be limited. I’ll check back this evening or
>> tomorrow morning :)
>>
>> George Fletcher
>> Identity Standards Architect
>> Practical Identity LLC
>>
>>
>>
>> On Sep 7, 2025, at 5:07 PM, Karl McGuinness <me at karlmcguinness.com>
>> wrote:
>>
>> There are several widely deployed infrastructure use cases that already
>> take an id_token as a bootstrap credential
>>
>> -
>> https://kubernetes.io/docs/reference/access-authn-authz/authentication/#openid-connect-tokens
>> -
>> https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html
>> -
>> https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers
>>
>> It's common for a CLI tool for example to to use something like device
>> authorization grant to obtain an id_token from an enterprise IdP end
>> exchange the the id_token for a backend session with a control plane. In
>> fact Okta uses OpenID Native SSO
>> https://openid.net/specs/openid-connect-native-sso-1_0.html for its AWS
>> CLI implementation to SSO to different AWS Accounts. These use cases are
>> attempting to use the ID Token similar to a X.509 as would benefit from a
>> key binding for an ID Token IMHO. From a deployment perspective it's so
>> much easier to get an ID Token from an Enterprise IdP than an X.509 for
>> these scenarios. The security benefits of supporting dynamic issued
>> credentials from an IdP that can implement zero-trust security controls
>> including MFA outweighs the privacy risks.
>>
>> There are also cross-client identity scenarios
>> https://developers.google.com/identity/protocols/oauth2/cross-client-identity
>> where a native app for example may have its own identity and the backend a
>> different client identity but to the end-user they are the same client.
>> These deployments are a single trust domain and don't have the same
>> privacy risks as cross-domain deployments
>>
>> With ID-JAG the id_token issuer is the processor of the token exchange
>> request. The assertion is something it issued so there wasn't a concern
>> for the same party to also validate it. We didn't want the IdP to have to
>> maintain the state with a refresh token so decided to use the serialized
>> authentication context in the id_token for the request as the goal was a
>> chained authentication. There is also interest to flow these claims also
>> in the ID-JAG to downstream AS. I could see ID-JAG also supporting a key
>> binding for the id_token if supported by the IdP.
>>
>> -Karl
>>
>>
>>
>> On Sun, Sep 7, 2025 at 10:19 AM Dick Hardt via Openid-specs-ab <
>> openid-specs-ab at lists.openid.net> wrote:
>>
>>> Hey George
>>>
>>> I see you (and many others) were supportive for adoption of the Identity
>>> Assertion Authorization Grant
>>>
>>>
>>> https://datatracker.ietf.org/doc/draft-parecki-oauth-identity-assertion-authz-grant/
>>>
>>> Where a client presents the id_token back to the OP/AS to get an ID-JAG
>>> token. Clearly the "aud" in the id_token is not the OP / AS. If presenting
>>> a token to a party that is not the "aud" is problematic, why did you not
>>> push back on that proposal? The AS could return a special token that the
>>> client could present back later to the OP to get an ID-JAG according to
>>> your logic below.
>>>
>>> I think some of the difference of opinion here is evident in how you are
>>> describing what is happening. You are using the terms client and AS for the
>>> parties, which are OAuth / authorization terms -- and suggesting the
>>> id_token is being presented to an RS.
>>>
>>> I would agree that using the id_token for authorization is problematic
>>> -- but that is not what we are proposing.
>>>
>>> The RP1 gets an id_token that has a bound key from the OP.
>>>
>>> RP1 then presents the id_token to RP2, with some proof of possession
>>> mechanism specific to the RP1 -> RP2 protocol.
>>>
>>> All the claims in the id_token are expected to be relevant in the
>>> presentation to RP2.
>>>
>>> As Jacob notes -- the "auth_time", "acr", and "amr" claims could be
>>> very useful to RP2.
>>>
>>> In other words, RP1 -> RP2 is a chained authentication event.
>>>
>>> /Dick
>>>
>>>
>>> On Sat, Sep 6, 2025 at 4:02 PM <george at practicalidentity.com> wrote:
>>>
>>>> So I think there are a couple of things I’d like to add to this
>>>> conversation.
>>>>
>>>> 1. The original intent/purpose of the id_token is to communicate an
>>>> identity assertion to the requesting client about the logged in user. Hence
>>>> the ‘aud’ claim in the id_token being the client_id of the requesting
>>>> client. General JWT based ‘aud’ claim processing rules require another
>>>> party receiving the id_token to reject it because the ‘aud’ claim doesn’t
>>>> match the receiver (see section 4.1.3 of RFC 7519). I have significant
>>>> concerns around trying to re-purpose the id_token for something different
>>>> (communicating status of the authentication to another party than the
>>>> requesting client).
>>>>
>>>> 2. The need for a secure way for the client to communicate to another
>>>> party (e.g. resource server) status about the authenticated user is valid.
>>>> However, I don’t believe that using the id_token is the best way to do
>>>> this. That is because, in addition to the ‘aud’ claim issues highlighted
>>>> previously, there are significant privacy risks in doing so. I’ve seen many
>>>> deployments that put user claims into the id_token that are NOT appropriate
>>>> for a subsequent resource server. Asking the AS to limit the user claims in
>>>> the id_token because it will be used to communicate authentication status
>>>> to a resource server could hamper the requesting client as it now needs a
>>>> different way to get those user claims that are appropriate just for
>>>> itself. I would much prefer that a new token be defined for the explicit
>>>> purpose of communicating authentication status. That frees up the AS to
>>>> limit PII related claims in that token while providing them in the id_token
>>>> to the requesting client. This also allows the AS to identify the list of
>>>> ‘aud’ values matching the receiving servers or potentially removing it
>>>> completely.
>>>>
>>>> 3. A new ’scope’, as currently proposed, can instruct the AS to return
>>>> this new token. There is much precedent for scopes to trigger this type of
>>>> behavior including the ‘openid’ scope itself.
>>>>
>>>> In my career I have rarely seen overloading intent to work out well.
>>>> Maybe others have a different experience.
>>>>
>>>> Thanks,
>>>> George
>>>>
>>>> George Fletcher
>>>> Identity Standards Architect
>>>> Practical Identity LLC
>>>>
>>>>
>>>>
>>>> On Sep 5, 2025, at 5:18 AM, Jacob Ideskog via Openid-specs-ab <
>>>> openid-specs-ab at lists.openid.net> wrote:
>>>>
>>>> Hi all,
>>>>
>>>> I'd like to chip in on the semantics of the two approaches.
>>>>
>>>> The way I've always interpreted the id_token vs the user info is the
>>>> following:
>>>>
>>>> The *id_token* represents the authentication transaction that just
>>>> took place. For that reason it contains important non-profile information
>>>> such as auth_time, acr, amr etc which are useful for the RP when deciding
>>>> if the authentication that took place is strong enough, fresh enough etc.
>>>> It *can* also contain a number of useful claims about the account or
>>>> the user but at a minimum it needs the subject in some form.
>>>>
>>>> The *user info *on the other hand is mainly governed by the profile
>>>> scope and sibling scopes. It does not contain authentication specific
>>>> information but rather only account specific details.
>>>>
>>>> In our implementation we tend to recommend adding account/user claims
>>>> in the ID token if you think the RP needs them to save them the round trip
>>>> for user info, but it's optional and up to the particular use-case. For
>>>> instance if you intend to share the ID token as this spec proposes, then
>>>> adding account claims should be weighed against the privacy posture
>>>> required.
>>>>
>>>> That said, to me, issuing a proof based on user info is less valuable
>>>> to a 3rd party as it would not contain the authentication specific details
>>>> that may matter to that party as well. If nothing else, the auth_time is
>>>> generally valuable. It could also convey details about how long the OP
>>>> considers the session to be valid for if you chose to interpret the exp as
>>>> such.
>>>> Issuing a bound ID token seems more to the point if that's the main
>>>> use-case we're after. If all we want to do is share user info details to
>>>> another party then a credential would do.
>>>>
>>>> It sounds like they solve different problems and should not be mixed.
>>>>
>>>> Just my 2¢
>>>>
>>>> /Jacob Ideskog
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Thu, 21 Aug 2025 at 19:39, Dick Hardt via Openid-specs-ab <
>>>> openid-specs-ab at lists.openid.net> wrote:
>>>>
>>>>> Here is my homework as assigned by the working group chair. :)
>>>>>
>>>>> KB = OpenID Connect Key Binding
>>>>> UVC = OpenID Connect UserInfo Verifiable Credentials
>>>>> Links to specs at bottom
>>>>>
>>>>>
>>>>> *Tl;dr:*KB adds the key to an ID Token
>>>>> UVC creates a verifiable credential with same info, but VC syntax
>>>>> KB does it in one call to OP
>>>>> UVC requires two calls to OP
>>>>>
>>>>> *Key Bound Token*
>>>>> KB outputs an id_token that includes a `cnf` claim of the public key
>>>>> UVC outputs a verifiable credential with a `did:jwk:ey...` claim
>>>>> Both include all the same user claims
>>>>>
>>>>>
>>>>> *Authentication Request*
>>>>> - KB uses `dpop` scope as well as `dpop_jkt` parameter
>>>>> - UVC uses `userinfo_credential`
>>>>>
>>>>> KB has extra layer of security as `dpop_jkt` provides additional
>>>>> assurance between authentication request and token request
>>>>>
>>>>> *Token Request*
>>>>> - KB - RP passes DPoP JWT as header
>>>>> - UVC has no changes
>>>>>
>>>>> *Token Response*
>>>>> - KB - OP passes back id_token that includes `cnf` claim
>>>>> - UVC - OP passes back an access_token as well as c_nonce and
>>>>> c_nonce_expires_in
>>>>>
>>>>> At this point, KB has completed the key binding ...
>>>>>
>>>>> *Credential Request and Response *
>>>>> UVC continues on
>>>>> - RP generates a verifiable credential request and passes it with the
>>>>> access_token as a bearer token to the OP's credential endpoint
>>>>> - OP returns a verifiable credential
>>>>>
>>>>>
>>>>> https://dickhardt.github.io/openid-key-binding/main.html
>>>>> https://github.com/dickhardt/openid-key-binding
>>>>>
>>>>> https://openid.net/specs/openid-connect-userinfo-vc-1_0.html
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> Openid-specs-ab mailing list
>>>>> Openid-specs-ab at lists.openid.net
>>>>> https://lists.openid.net/mailman/listinfo/openid-specs-ab
>>>>>
>>>>
>>>>
>>>> --
>>>> Jacob Ideskog
>>>> CTO
>>>> Curity
>>>> -------------------------------------------------------------------
>>>> Sankt Göransgatan 66, Stockholm, Sweden
>>>> M: +46 70-2233664
>>>> j <jacob at twobo.com>acob at curity.io
>>>> curity.io
>>>> -------------------------------------------------------------------
>>>> _______________________________________________
>>>> Openid-specs-ab mailing list
>>>> Openid-specs-ab at lists.openid.net
>>>> https://lists.openid.net/mailman/listinfo/openid-specs-ab
>>>>
>>>>
>>>> _______________________________________________
>>> Openid-specs-ab mailing list
>>> Openid-specs-ab at lists.openid.net
>>> https://lists.openid.net/mailman/listinfo/openid-specs-ab
>>>
>>
>> _______________________________________________
> Openid-specs-ab mailing list
> Openid-specs-ab at lists.openid.net
> https://lists.openid.net/mailman/listinfo/openid-specs-ab
>
--
Jacob Ideskog
CTO
Curity
-------------------------------------------------------------------
Sankt Göransgatan 66, Stockholm, Sweden
M: +46 70-2233664
j <jacob at twobo.com>acob at curity.io
curity.io
-------------------------------------------------------------------
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openid.net/pipermail/openid-specs-ab/attachments/20250908/c073f73c/attachment-0001.htm>
More information about the Openid-specs-ab
mailing list