KEYCLOAK-18827 FAPI-CIBA-ID1 conformance test : Client JWT authentication should allow Backchannel Authentication endpoint as audience

This commit is contained in:
Takashi Norimatsu 2021-07-20 09:14:06 +09:00 committed by Marek Posolda
parent 02a9eb442d
commit f76c07476c
2 changed files with 25 additions and 4 deletions

View file

@ -19,6 +19,7 @@ package org.keycloak.authentication.authenticators.client;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@ -36,6 +37,7 @@ import org.keycloak.OAuth2Constants;
import org.keycloak.OAuthErrorException;
import org.keycloak.authentication.AuthenticationFlowError;
import org.keycloak.authentication.ClientAuthenticationFlowContext;
import org.keycloak.common.Profile;
import org.keycloak.common.util.Time;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.keys.loader.PublicKeyStorageManager;
@ -46,6 +48,7 @@ import org.keycloak.models.SingleUseTokenStoreProvider;
import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
import org.keycloak.protocol.oidc.grants.ciba.CibaGrantType;
import org.keycloak.protocol.oidc.par.endpoints.ParEndpoint;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.JsonWebToken;
@ -274,6 +277,11 @@ public class JWTClientAuthenticator extends AbstractClientAuthenticator {
String issuerUrl = Urls.realmIssuer(context.getUriInfo().getBaseUri(), realm.getName());
String tokenUrl = OIDCLoginProtocolService.tokenUrl(context.getUriInfo().getBaseUriBuilder()).build(realm.getName()).toString();
String parEndpointUrl = ParEndpoint.parUrl(context.getUriInfo().getBaseUriBuilder()).build(realm.getName()).toString();
return Arrays.asList(issuerUrl, tokenUrl, parEndpointUrl);
List<String> expectedAudiences = new ArrayList<>(Arrays.asList(issuerUrl, tokenUrl, parEndpointUrl));
if (Profile.isFeatureEnabled(Profile.Feature.CIBA)) {
String backchannelAuthenticationUrl = CibaGrantType.authorizationUrl(context.getUriInfo().getBaseUriBuilder()).build(realm.getName()).toString();
expectedAudiences.add(backchannelAuthenticationUrl);
}
return expectedAudiences;
}
}

View file

@ -43,6 +43,7 @@ import org.keycloak.admin.client.resource.ClientAttributeCertificateResource;
import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.authentication.AuthenticationFlowError;
import org.keycloak.authentication.authenticators.client.JWTClientAuthenticator;
import org.keycloak.common.Profile;
import org.keycloak.common.constants.ServiceAccountConstants;
import org.keycloak.common.util.*;
import org.keycloak.constants.ServiceUrlConstants;
@ -53,7 +54,6 @@ import org.keycloak.crypto.SignatureSignerContext;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventType;
import org.keycloak.jose.jwe.JWEException;
import org.keycloak.jose.jws.JWSBuilder;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
@ -72,6 +72,7 @@ import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude;
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
import org.keycloak.testsuite.auth.page.AuthRealm;
import org.keycloak.testsuite.client.resources.TestApplicationResourceUrls;
import org.keycloak.testsuite.client.resources.TestOIDCEndpointsApplicationResource;
@ -87,7 +88,6 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.nio.file.Files;
import java.security.KeyFactory;
@ -113,6 +113,8 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer.QUARKUS;
import static org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer.REMOTE;
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer;
@ -793,6 +795,17 @@ public class ClientAuthSignedJWTTest extends AbstractKeycloakTest {
@Test
public void testParEndpointAsAudience() throws Exception {
testEndpointAsAudience(oauth.getParEndpointUrl());
}
@EnableFeature(value = Profile.Feature.CIBA, skipRestart = true)
@AuthServerContainerExclude({REMOTE, QUARKUS})
@Test
public void testBackchannelAuthenticationEndpointAsAudience() throws Exception {
testEndpointAsAudience(oauth.getBackchannelAuthenticationUrl());
}
private void testEndpointAsAudience(String endpointUrl) throws Exception {
ClientRepresentation clientRepresentation = app2;
ClientResource clientResource = getClient(testRealm.getRealm(), clientRepresentation.getId());
clientRepresentation = clientResource.toRepresentation();
@ -802,7 +815,7 @@ public class ClientAuthSignedJWTTest extends AbstractKeycloakTest {
PrivateKey privateKey = keyPair.getPrivate();
JsonWebToken assertion = createRequestToken(app2.getClientId(), getRealmInfoUrl());
assertion.audience(oauth.getParEndpointUrl());
assertion.audience(endpointUrl);
List<NameValuePair> parameters = new LinkedList<NameValuePair>();
parameters.add(new BasicNameValuePair(OAuth2Constants.GRANT_TYPE, OAuth2Constants.CLIENT_CREDENTIALS));