diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java
index 5139e3a..789d381 100644
--- a/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java
@@ -30,6 +30,7 @@ import java.util.Set;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
import org.keycloak.OAuth2Constants;
import org.keycloak.authentication.AuthenticationFlowError;
@@ -42,6 +43,7 @@ import org.keycloak.models.ClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.JsonWebToken;
import org.keycloak.representations.idm.CertificateRepresentation;
@@ -139,10 +141,11 @@ public class JWTClientAuthenticator extends AbstractClientAuthenticator {
throw new RuntimeException("Signature on JWT token failed validation");
}
- // Validate other things
- String expectedAudience = Urls.realmIssuer(context.getUriInfo().getBaseUri(), realm.getName());
- if (!token.hasAudience(expectedAudience)) {
- throw new RuntimeException("Token audience doesn't match domain. Realm audience is '" + expectedAudience + "' but audience from token is '" + Arrays.asList(token.getAudience()).toString() + "'");
+ // Allow both "issuer" or "token-endpoint" as audience
+ String issuerUrl = Urls.realmIssuer(context.getUriInfo().getBaseUri(), realm.getName());
+ String tokenUrl = OIDCLoginProtocolService.tokenUrl(context.getUriInfo().getBaseUriBuilder()).build(realm.getName()).toString();
+ if (!token.hasAudience(issuerUrl) && !token.hasAudience(tokenUrl)) {
+ throw new RuntimeException("Token audience doesn't match domain. Realm issuer is '" + issuerUrl + "' but audience from token is '" + Arrays.asList(token.getAudience()).toString() + "'");
}
if (!token.isActive()) {
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCClientRegistrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCClientRegistrationTest.java
index 5d7d2c1..1c6b85b 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCClientRegistrationTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCClientRegistrationTest.java
@@ -37,8 +37,10 @@ import org.keycloak.constants.ServiceUrlConstants;
import org.keycloak.jose.jwk.JSONWebKeySet;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
import org.keycloak.protocol.oidc.utils.OIDCResponseType;
import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.JsonWebToken;
import org.keycloak.representations.idm.ClientInitialAccessCreatePresentation;
import org.keycloak.representations.idm.ClientInitialAccessPresentation;
import org.keycloak.representations.idm.ClientRegistrationTrustedHostRepresentation;
@@ -53,6 +55,7 @@ import java.util.LinkedList;
import java.util.List;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
import static org.junit.Assert.*;
import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson;
@@ -260,7 +263,18 @@ public class OIDCClientRegistrationTest extends AbstractClientRegistrationTest {
PrivateKey privateKey = KeycloakModelUtils.getPrivateKey(PRIVATE_KEY);
- JWTClientCredentialsProvider jwtProvider = new JWTClientCredentialsProvider();
+ // Use token-endpoint as audience as OIDC conformance testsuite is using it too.
+ JWTClientCredentialsProvider jwtProvider = new JWTClientCredentialsProvider() {
+
+ @Override
+ protected JsonWebToken createRequestToken(String clientId, String realmInfoUrl) {
+ JsonWebToken jwt = super.createRequestToken(clientId, realmInfoUrl);
+ String tokenEndpointUrl = OIDCLoginProtocolService.tokenUrl(UriBuilder.fromUri(getAuthServerRoot())).build(REALM_NAME).toString();
+ jwt.audience(tokenEndpointUrl);
+ return jwt;
+ }
+
+ };
jwtProvider.setPrivateKey(privateKey);
jwtProvider.setTokenTimeout(10);
return jwtProvider.createSignedRequestToken(clientId, realmInfoUrl);