KEYCLOAK-3424 Issuer or token-endpoint as audience in signed JWT
This commit is contained in:
parent
a7f9a6e095
commit
f4aee129e4
2 changed files with 22 additions and 5 deletions
|
@ -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()) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue