You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Signed JWT - Issuer should not be required to match Subject #15688
1. The JWT MUST contain an "iss" (issuer) claim that contains a
unique identifier for the entity that issued the JWT. In the
absence of an application profile specifying otherwise,
compliant applications MUST compare issuer values [...]
Using the client ID at (sub) itself as expected issuer seems to be one option, where the client needs to forge tokens on its own.
If the client ID isn't used, some other issuer would need to be configured as expected for the client. right?
It's not very clear from the spec, but if not why does it talk about comparing issuer values?
On Tue, Nov 29, 2022 at 12:58 PM Johannes Bergmann ***@***.***> wrote:
section 3. <https://datatracker.ietf.org/doc/html/rfc7523#section-3>
states
1. The JWT MUST contain an "iss" (issuer) claim that contains a
unique identifier for the entity that issued the JWT. In the
absence of an application profile specifying otherwise,
compliant applications MUST compare issuer values [...]
Using the client ID at (sub) itself as expected issuer seems to be one
option, where the client needs to forge tokens on its own.
If the client ID isn't used, some other issuer would need to be configured
as expected for the client. right?
It's not very clear from the spec, but if not why does it talk about
comparing issuer values?
—
Reply to this email directly, view it on GitHub
<#15688 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AABVP2M45YJHFOTDBMV5C5LWKY74JANCNFSM6AAAAAASKUH74U>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
If you don't require issuer and subject to be identical, you need a mechanism to configure which issuers to trust when it comes to making statements about clients. As such, I would say this is a feature request or an enhancement - not a bug.
I think what you’re describing is a feature request which is peripherally
related but the current implementation does not match the spec and is
enforcing an incorrect constraint.
On Wed, Nov 30, 2022 at 11:21 AM Sebastian Schuster < ***@***.***> wrote:
If you don't require issuer and subject to be identical, you need a
mechanism to configure which issuers to trust when it comes to making
statements about clients. As such, I would say this is a feature request or
an enhancement - not a bug.
—
Reply to this email directly, view it on GitHub
<#15688 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AABVP2KPMK74XJCHYNFS7CTWK55IZANCNFSM6AAAAAASKUH74U>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
Ok. But it also doesn’t say that they MUST be the same. So the
implementation is enforcing a constraint that is beyond what the spec
requires.
I’m raising this because we have a real-world case where a JWT from a 3rd
party STS is being rejected by keycloak because of this constraint.
Thanks for the report, but unfortunately due the amount of other reported issues and other priorities, Keycloak team does not have time to properly triage this bug. So preliminary added to Backlog for now.
It will be helpful if:
You can verify if still applicable in latest Keycloak released version. If not, then it is welcome to close this issue.
If you figure that this may not be a valid bug (for example just a mistake in configuration etc), it will be also welcome to close this issue
If still applicable in latest version, it will be welcome to add the comment as well, that this was still reproduced with latest Keycloak version as it is very valuable info. Anyone is welcome to comment with this or add other relevant comments to this issue.
I am required to provide an access token (which I generate with Keycloak) to a third party. This third party requires that the "sub" and "iss" claims be the same, however, this is difficult to do as Keycloak requires the "iss" be set to it's own URL.
I will check with my third party, if they are using this authorization library then that might be where this requirement is coming from.
This one also looks like an enhancement for me because we don't have mechanisms to trust only the values set in the trust claim. Doing that will require a different form of validation (e.g.: binding certs to trusted issuers).
I stumbled upon this while experimenting with Keycloak <> Kubernetes integrations. Essentially, I'd like to be able to have my Kubernetes service accounts authenticate to my Keycloak instance as Keycloak clients by using a service account token issued by the K8S cluster. That service account token is a signed JWT token, with the cluster's OIDC URL in the iss claim and the service account name in the sub claim. I'd love to be able to get this to work by configuring a validation policy along the lines of "for this client, trust issuer XYZ, and load the keys using OIDC key discovery" (potentially with TLS certificate pinning for the OIDC discovery service). This is, in a nutshell, also how you'd federate OIDC identities with AWS IAM.
Reason: this would make it much easier to set up new services that integrate with Keycloak in my cluster, because I can use pretty much the same config for all of my clients, and I can delegate all key management tasks to the Kubernetes API.
I can't imagine I'm the first person trying to set up something like this, but after some experimentation & googling I ended up here. Reading through the thread, I think the feature request made in the OP would address my use case as well.
(In the meantime, I guess I'll look for ways to extend Keycloak's client authentication system, but I figured I'd at least drop the use case here for future reference)
We hit this too when trying to trust a signed GitHub ID Token and use that generate a Keycloak access token using the client flow.
There is this stipulation in the spec, which I assume is where this comes from:
2. The JWT MUST contain a "sub" (subject) claim identifying the
principal that is the subject of the JWT. Two cases need to be
differentiated:
...
B. For client authentication, the subject MUST be the
"client_id" of the OAuth client.
That said, I think the code is still wrong - it checks if(!clientId.equals(token.getIssuer())) { throw... }here
Despite it referring to clientId it's actually (as the exception suggests) is comparing issuer to subject as String clientId = token.getSubject();here.
Should this be String clientId = context.getClient().getClientId(); instead?
Then we might be able to get our use-case working by setting the client_id to the subject - which I can understand more.
When I try to use this id_token on another client from a different realm, I get:
2024-09-03 15:57:53,042 ERROR [org.keycloak.services] (executor-thread-10) KC-SERVICES0025: Error when validating client assertion: java.lang.RuntimeException: Issuer mismatch. The issuer should match the subject
at org.keycloak.authentication.authenticators.client.JWTClientValidator.validateClient(JWTClientValidator.java:115)
at org.keycloak.authentication.authenticators.client.JWTClientAuthenticator.authenticateClient(JWTClientAuthenticator.java:75)
at org.keycloak.authentication.ClientAuthenticationFlow.processFlow(ClientAuthenticationFlow.java:72)
at org.keycloak.authentication.AuthenticationProcessor.authenticateClient(AuthenticationProcessor.java:894)
at org.keycloak.protocol.oidc.utils.AuthorizeClientUtil.authorizeClient(AuthorizeClientUtil.java:50)
at org.keycloak.protocol.oidc.endpoints.TokenEndpoint.checkClient(TokenEndpoint.java:253)
at org.keycloak.protocol.oidc.endpoints.TokenEndpoint.processGrantRequest(TokenEndpoint.java:201)
at org.keycloak.protocol.oidc.endpoints.TokenEndpoint$quarkusrestinvoker$processGrantRequest_6408e15340992839b66447750c221d9aaa837bd7.invoke(Unknown Source)
at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:145)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:840)
I think I have a similar problem during testing client credential flow with signed jwts.
If I understand it correctly I can't use a JWT token from Keycloak itself (from eg a different realm) to test this behaviour because I can't change the issuer in the token, which must be equal to the subject,
and the subject must be equal to the client_id in the request the contains the signed JWT.
So I'm stuck.
What if my external partner has an Keycloak as well. Then they can't used it to generate their signed JWT?
I must be missing something.
Can u help me?
JWTClientValidator.java:
public boolean validateClient() {
if (token == null) throw new IllegalStateException("Incorrect usage. Variable 'token' is null. Need to read JWS first before validateClient");
String clientId = token.getSubject();
if (clientId == null) {
throw new RuntimeException("Can't identify client. Subject missing on JWT token");
}
if (!clientId.equals(token.getIssuer())) {
throw new RuntimeException("Issuer mismatch. The issuer should match the subject");
}
String clientIdParam = params.getFirst(OAuth2Constants.CLIENT_ID);
if (clientIdParam != null && !clientIdParam.equals(clientId)) {
throw new RuntimeException("client_id parameter not matching with client from JWT token");
}
Activity
jbman commentedon Nov 29, 2022
section 3. states
Using the client ID at (sub) itself as expected issuer seems to be one option, where the client needs to forge tokens on its own.
If the client ID isn't used, some other issuer would need to be configured as expected for the client. right?
It's not very clear from the spec, but if not why does it talk about comparing issuer values?
michaelaird commentedon Nov 30, 2022
sschu commentedon Nov 30, 2022
If you don't require issuer and subject to be identical, you need a mechanism to configure which issuers to trust when it comes to making statements about clients. As such, I would say this is a feature request or an enhancement - not a bug.
michaelaird commentedon Nov 30, 2022
sschu commentedon Dec 1, 2022
The spec does not say that the two might not be the same, so it clearly does not violate the spec.
michaelaird commentedon Dec 1, 2022
mposolda commentedon Apr 4, 2023
Thanks for the report, but unfortunately due the amount of other reported issues and other priorities, Keycloak team does not have time to properly triage this bug. So preliminary added to Backlog for now.
It will be helpful if:
cmiles74 commentedon Apr 28, 2023
I am curious if this is related to my issue (#19953)...
I am required to provide an access token (which I generate with Keycloak) to a third party. This third party requires that the "sub" and "iss" claims be the same, however, this is difficult to do as Keycloak requires the "iss" be set to it's own URL.
I will check with my third party, if they are using this authorization library then that might be where this requirement is coming from.
pedroigor commentedon Mar 4, 2024
This one also looks like an enhancement for me because we don't have mechanisms to trust only the values set in the
trustclaim. Doing that will require a different form of validation (e.g.: binding certs to trusted issuers).It might be related to #24512.
5 remaining items
keycloak-github-bot commentedon Mar 4, 2024
Due to the amount of issues reported by the community we are not able to prioritise resolving this issue at the moment.
If you are affected by this issue, upvote it by adding a 👍 to the description. We would also welcome a contribution to fix the issue.
keycloak-github-bot commentedon Jun 3, 2024
Due to lack of updates in the last 180 days this issue will be automatically closed.
MatthiasValvekens commentedon Jul 8, 2024
I stumbled upon this while experimenting with Keycloak <> Kubernetes integrations. Essentially, I'd like to be able to have my Kubernetes service accounts authenticate to my Keycloak instance as Keycloak clients by using a service account token issued by the K8S cluster. That service account token is a signed JWT token, with the cluster's OIDC URL in the
issclaim and the service account name in thesubclaim. I'd love to be able to get this to work by configuring a validation policy along the lines of "for this client, trust issuer XYZ, and load the keys using OIDC key discovery" (potentially with TLS certificate pinning for the OIDC discovery service). This is, in a nutshell, also how you'd federate OIDC identities with AWS IAM.Reason: this would make it much easier to set up new services that integrate with Keycloak in my cluster, because I can use pretty much the same config for all of my clients, and I can delegate all key management tasks to the Kubernetes API.
I can't imagine I'm the first person trying to set up something like this, but after some experimentation & googling I ended up here. Reading through the thread, I think the feature request made in the OP would address my use case as well.
(In the meantime, I guess I'll look for ways to extend Keycloak's client authentication system, but I figured I'd at least drop the use case here for future reference)
timbrown5 commentedon Jul 18, 2024
We hit this too when trying to trust a signed GitHub ID Token and use that generate a Keycloak access token using the client flow.
There is this stipulation in the spec, which I assume is where this comes from:
That said, I think the code is still wrong - it checks
if(!clientId.equals(token.getIssuer())) { throw... }hereDespite it referring to
clientIdit's actually (as the exception suggests) is comparing issuer to subject asString clientId = token.getSubject();here.Should this be
String clientId = context.getClient().getClientId();instead?Then we might be able to get our use-case working by setting the
client_idto the subject - which I can understand more.eminwux commentedon Sep 3, 2024
This is needed also when authenticating between Keycloak realms.
For instance, this is the id_token I get when authenticating:
Here you can see that
sub!=iss.When I try to use this
id_tokenon another client from a different realm, I get:I could not find yet a workaround for this.
eminwux commentedon Sep 3, 2024
Anyone interested in following up on this issue, please see discussion 32626
yanxch commentedon Feb 6, 2025
I think I have a similar problem during testing client credential flow with signed jwts.
If I understand it correctly I can't use a JWT token from Keycloak itself (from eg a different realm) to test this behaviour because I can't change the issuer in the token, which must be equal to the subject,
and the subject must be equal to the client_id in the request the contains the signed JWT.
So I'm stuck.
What if my external partner has an Keycloak as well. Then they can't used it to generate their signed JWT?
I must be missing something.
Can u help me?