KEYCLOAK-18827 FAPI-CIBA-ID1 conformance test : Client JWT authentication should allow Backchannel Authentication endpoint as audience
This commit is contained in:
parent
02a9eb442d
commit
f76c07476c
2 changed files with 25 additions and 4 deletions
|
@ -19,6 +19,7 @@ package org.keycloak.authentication.authenticators.client;
|
||||||
|
|
||||||
|
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -36,6 +37,7 @@ import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.authentication.AuthenticationFlowError;
|
import org.keycloak.authentication.AuthenticationFlowError;
|
||||||
import org.keycloak.authentication.ClientAuthenticationFlowContext;
|
import org.keycloak.authentication.ClientAuthenticationFlowContext;
|
||||||
|
import org.keycloak.common.Profile;
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
import org.keycloak.jose.jws.JWSInput;
|
import org.keycloak.jose.jws.JWSInput;
|
||||||
import org.keycloak.keys.loader.PublicKeyStorageManager;
|
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.OIDCAdvancedConfigWrapper;
|
||||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||||
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
|
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.protocol.oidc.par.endpoints.ParEndpoint;
|
||||||
import org.keycloak.provider.ProviderConfigProperty;
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
import org.keycloak.representations.JsonWebToken;
|
import org.keycloak.representations.JsonWebToken;
|
||||||
|
@ -274,6 +277,11 @@ public class JWTClientAuthenticator extends AbstractClientAuthenticator {
|
||||||
String issuerUrl = Urls.realmIssuer(context.getUriInfo().getBaseUri(), realm.getName());
|
String issuerUrl = Urls.realmIssuer(context.getUriInfo().getBaseUri(), realm.getName());
|
||||||
String tokenUrl = OIDCLoginProtocolService.tokenUrl(context.getUriInfo().getBaseUriBuilder()).build(realm.getName()).toString();
|
String tokenUrl = OIDCLoginProtocolService.tokenUrl(context.getUriInfo().getBaseUriBuilder()).build(realm.getName()).toString();
|
||||||
String parEndpointUrl = ParEndpoint.parUrl(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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ import org.keycloak.admin.client.resource.ClientAttributeCertificateResource;
|
||||||
import org.keycloak.admin.client.resource.ClientResource;
|
import org.keycloak.admin.client.resource.ClientResource;
|
||||||
import org.keycloak.authentication.AuthenticationFlowError;
|
import org.keycloak.authentication.AuthenticationFlowError;
|
||||||
import org.keycloak.authentication.authenticators.client.JWTClientAuthenticator;
|
import org.keycloak.authentication.authenticators.client.JWTClientAuthenticator;
|
||||||
|
import org.keycloak.common.Profile;
|
||||||
import org.keycloak.common.constants.ServiceAccountConstants;
|
import org.keycloak.common.constants.ServiceAccountConstants;
|
||||||
import org.keycloak.common.util.*;
|
import org.keycloak.common.util.*;
|
||||||
import org.keycloak.constants.ServiceUrlConstants;
|
import org.keycloak.constants.ServiceUrlConstants;
|
||||||
|
@ -53,7 +54,6 @@ import org.keycloak.crypto.SignatureSignerContext;
|
||||||
import org.keycloak.events.Details;
|
import org.keycloak.events.Details;
|
||||||
import org.keycloak.events.Errors;
|
import org.keycloak.events.Errors;
|
||||||
import org.keycloak.events.EventType;
|
import org.keycloak.events.EventType;
|
||||||
import org.keycloak.jose.jwe.JWEException;
|
|
||||||
import org.keycloak.jose.jws.JWSBuilder;
|
import org.keycloak.jose.jws.JWSBuilder;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
|
import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
|
||||||
|
@ -72,6 +72,7 @@ import org.keycloak.testsuite.Assert;
|
||||||
import org.keycloak.testsuite.AssertEvents;
|
import org.keycloak.testsuite.AssertEvents;
|
||||||
import org.keycloak.testsuite.admin.ApiUtil;
|
import org.keycloak.testsuite.admin.ApiUtil;
|
||||||
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude;
|
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.auth.page.AuthRealm;
|
||||||
import org.keycloak.testsuite.client.resources.TestApplicationResourceUrls;
|
import org.keycloak.testsuite.client.resources.TestApplicationResourceUrls;
|
||||||
import org.keycloak.testsuite.client.resources.TestOIDCEndpointsApplicationResource;
|
import org.keycloak.testsuite.client.resources.TestOIDCEndpointsApplicationResource;
|
||||||
|
@ -87,7 +88,6 @@ import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.security.KeyFactory;
|
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.assertNotEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertNull;
|
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;
|
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer;
|
||||||
|
|
||||||
|
@ -793,6 +795,17 @@ public class ClientAuthSignedJWTTest extends AbstractKeycloakTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParEndpointAsAudience() throws Exception {
|
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;
|
ClientRepresentation clientRepresentation = app2;
|
||||||
ClientResource clientResource = getClient(testRealm.getRealm(), clientRepresentation.getId());
|
ClientResource clientResource = getClient(testRealm.getRealm(), clientRepresentation.getId());
|
||||||
clientRepresentation = clientResource.toRepresentation();
|
clientRepresentation = clientResource.toRepresentation();
|
||||||
|
@ -802,7 +815,7 @@ public class ClientAuthSignedJWTTest extends AbstractKeycloakTest {
|
||||||
PrivateKey privateKey = keyPair.getPrivate();
|
PrivateKey privateKey = keyPair.getPrivate();
|
||||||
JsonWebToken assertion = createRequestToken(app2.getClientId(), getRealmInfoUrl());
|
JsonWebToken assertion = createRequestToken(app2.getClientId(), getRealmInfoUrl());
|
||||||
|
|
||||||
assertion.audience(oauth.getParEndpointUrl());
|
assertion.audience(endpointUrl);
|
||||||
|
|
||||||
List<NameValuePair> parameters = new LinkedList<NameValuePair>();
|
List<NameValuePair> parameters = new LinkedList<NameValuePair>();
|
||||||
parameters.add(new BasicNameValuePair(OAuth2Constants.GRANT_TYPE, OAuth2Constants.CLIENT_CREDENTIALS));
|
parameters.add(new BasicNameValuePair(OAuth2Constants.GRANT_TYPE, OAuth2Constants.CLIENT_CREDENTIALS));
|
||||||
|
|
Loading…
Reference in a new issue