Stop looking up client in ClientAssertionState to prevent lookup by clientId in federated client authentication (#44448)

Closes #44447

Signed-off-by: stianst <stianst@gmail.com>
This commit is contained in:
Stian Thorgersen 2025-11-26 06:31:05 +01:00 committed by GitHub
parent 570ac40025
commit 2acfd41b19
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 36 additions and 10 deletions

View File

@ -21,8 +21,7 @@ public class ClientAssertionState {
private final JWSInput jws;
private final JsonWebToken token;
public ClientAssertionState(ClientModel client, String clientAssertionType, String clientAssertion, JWSInput jws, JsonWebToken token) {
this.client = client;
public ClientAssertionState(String clientAssertionType, String clientAssertion, JWSInput jws, JsonWebToken token) {
this.clientAssertionType = clientAssertionType;
this.clientAssertion = clientAssertion;
this.jws = jws;
@ -69,8 +68,6 @@ public class ClientAssertionState {
JWSInput jws = null;
JsonWebToken token = null;
ClientModel client = null;
if (clientAssertion != null) {
jws = new JWSInput(clientAssertion);
token = jws.readJsonContent(JsonWebToken.class);
@ -79,13 +76,9 @@ public class ClientAssertionState {
event.detail(Details.CLIENT_ASSERTION_ID, token.getId());
event.detail(Details.CLIENT_ASSERTION_ISSUER, token.getIssuer());
event.detail(Details.CLIENT_ASSERTION_SUB, token.getSubject());
if (token.getSubject() != null) {
client = context.getRealm().getClientByClientId(token.getSubject());
}
}
return new ClientAssertionState(client, clientAssertionType, clientAssertion, jws, token);
return new ClientAssertionState(clientAssertionType, clientAssertion, jws, token);
}
}

View File

@ -84,6 +84,11 @@ public class FederatedJWTClientAuthenticator extends AbstractClientAuthenticator
return;
}
// Ignore for self-signed client assertions
if (Objects.equals(clientAssertionState.getToken().getIssuer(), clientAssertionState.getToken().getSubject())) {
return;
}
ClientAssertionIdentityProviderFactory.ClientAssertionStrategy strategy = findStrategy(clientAssertionState.getClientAssertionType());
if (strategy == null) {
return;

View File

@ -25,6 +25,7 @@ import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import jakarta.ws.rs.core.Response;
@ -64,7 +65,20 @@ public class JWTClientAuthenticator extends AbstractClientAuthenticator {
@Override
public void authenticateClient(ClientAuthenticationFlowContext context) {
try {
ClientAssertionState clientAssertionState = context.getState(ClientAssertionState.class, ClientAssertionState.supplier());
JsonWebToken jwt = clientAssertionState.getToken();
// Ignore for client assertions signed by third-parties
if (!Objects.equals(jwt.getIssuer(), jwt.getSubject())) {
return;
}
if (clientAssertionState.getClient() == null) {
clientAssertionState.setClient(context.getRealm().getClientByClientId(jwt.getSubject()));
}
JWTClientValidator validator = new JWTClientValidator(context, this::verifySignature, getId());
if (!validator.validate()) return;
context.success();

View File

@ -22,6 +22,7 @@ import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import jakarta.ws.rs.core.Response;
@ -55,6 +56,18 @@ public class JWTClientSecretAuthenticator extends AbstractClientAuthenticator {
@Override
public void authenticateClient(ClientAuthenticationFlowContext context) {
try {
ClientAssertionState clientAssertionState = context.getState(ClientAssertionState.class, ClientAssertionState.supplier());
JsonWebToken jwt = clientAssertionState.getToken();
// Ignore for client assertions signed by third-parties
if (!Objects.equals(jwt.getIssuer(), jwt.getSubject())) {
return;
}
if (clientAssertionState.getClient() == null) {
clientAssertionState.setClient(context.getRealm().getClientByClientId(jwt.getSubject()));
}
JWTClientValidator validator = new JWTClientValidator(context, this::verifySignature, getId());
if (!validator.validate()) return;

View File

@ -51,7 +51,8 @@ public class JWTAuthorizationGrantValidator extends AbstractBaseJWTValidator imp
try {
JWSInput jws = new JWSInput(assertion);
JsonWebToken jwt = jws.readJsonContent(JsonWebToken.class);
ClientAssertionState clientAssertionState = new ClientAssertionState(client, OAuth2Constants.JWT_AUTHORIZATION_GRANT, assertion, jws, jwt);
ClientAssertionState clientAssertionState = new ClientAssertionState(OAuth2Constants.JWT_AUTHORIZATION_GRANT, assertion, jws, jwt);
clientAssertionState.setClient(client);
return new JWTAuthorizationGrantValidator(session, scope, clientAssertionState);
} catch (JWSInputException e) {
throw new RuntimeException("The provided assertion is not a valid JWT");