KEYCLOAK-17928 Determine public client based on token_endpoint_auth_method during OIDC dynamic client registration

This commit is contained in:
Takashi Norimatsu 2021-05-06 12:30:46 +09:00 committed by Marek Posolda
parent 624d300a55
commit b4e4e75743
2 changed files with 36 additions and 23 deletions

View file

@ -88,8 +88,6 @@ public class DescriptionConverter {
client.setStandardFlowEnabled(responseType.hasResponseType(OIDCResponseType.CODE));
client.setImplicitFlowEnabled(responseType.isImplicitOrHybridFlow());
client.setPublicClient(responseType.isImplicitFlow());
if (oidcGrantTypes != null) {
client.setDirectAccessGrantsEnabled(oidcGrantTypes.contains(OAuth2Constants.PASSWORD));
client.setServiceAccountsEnabled(oidcGrantTypes.contains(OAuth2Constants.CLIENT_CREDENTIALS));
@ -100,6 +98,11 @@ public class DescriptionConverter {
}
String authMethod = clientOIDC.getTokenEndpointAuthMethod();
client.setPublicClient(Boolean.FALSE);
if ("none".equals(authMethod)) {
client.setClientAuthenticatorType("none");
client.setPublicClient(Boolean.TRUE);
} else {
ClientAuthenticatorFactory clientAuthFactory;
if (authMethod == null) {
clientAuthFactory = (ClientAuthenticatorFactory) session.getKeycloakSessionFactory().getProviderFactory(ClientAuthenticator.class, KeycloakModelUtils.getDefaultClientAuthenticatorType());
@ -111,6 +114,7 @@ public class DescriptionConverter {
throw new ClientRegistrationException("Not found clientAuthenticator for requested token_endpoint_auth_method");
}
client.setClientAuthenticatorType(clientAuthFactory.getId());
}
boolean publicKeySet = setPublicKey(clientOIDC, client);
if (authMethod != null && authMethod.equals(OIDCLoginProtocol.PRIVATE_KEY_JWT) && !publicKeySet) {
@ -238,11 +242,15 @@ public class DescriptionConverter {
OIDCClientRepresentation response = new OIDCClientRepresentation();
response.setClientId(client.getClientId());
if ("none".equals(client.getClientAuthenticatorType())) {
response.setTokenEndpointAuthMethod("none");
} else {
ClientAuthenticatorFactory clientAuth = (ClientAuthenticatorFactory) session.getKeycloakSessionFactory().getProviderFactory(ClientAuthenticator.class, client.getClientAuthenticatorType());
Set<String> oidcClientAuthMethods = clientAuth.getProtocolAuthenticatorMethods(OIDCLoginProtocol.LOGIN_PROTOCOL);
if (oidcClientAuthMethods != null && !oidcClientAuthMethods.isEmpty()) {
response.setTokenEndpointAuthMethod(oidcClientAuthMethods.iterator().next());
}
}
if (client.getClientAuthenticatorType().equals(ClientIdAndSecretAuthenticator.PROVIDER_ID)) {
response.setClientSecret(client.getSecret());

View file

@ -254,22 +254,27 @@ public class OIDCClientRegistrationTest extends AbstractClientRegistrationTest {
public void createClientImplicitFlow() throws ClientRegistrationException {
OIDCClientRepresentation clientRep = createRep();
// create implicitFlow client and assert it's public client
clientRep.setResponseTypes(Arrays.asList("id_token token"));
OIDCClientRepresentation response = reg.oidc().create(clientRep);
String clientId = response.getClientId();
ClientRepresentation kcClientRep = getKeycloakClient(clientId);
Assert.assertFalse(kcClientRep.isPublicClient());
Assert.assertNull(kcClientRep.getSecret());
}
@Test
public void createPublicClient() throws ClientRegistrationException {
OIDCClientRepresentation clientRep = createRep();
clientRep.setTokenEndpointAuthMethod("none");
OIDCClientRepresentation response = reg.oidc().create(clientRep);
Assert.assertEquals("none", response.getTokenEndpointAuthMethod());
String clientId = response.getClientId();
ClientRepresentation kcClientRep = getKeycloakClient(clientId);
Assert.assertTrue(kcClientRep.isPublicClient());
Assert.assertNull(kcClientRep.getSecret());
// Update client to hybrid and check it's not public client anymore
reg.auth(Auth.token(response));
response.setResponseTypes(Arrays.asList("id_token token", "code id_token", "code"));
reg.oidc().update(response);
kcClientRep = getKeycloakClient(clientId);
Assert.assertFalse(kcClientRep.isPublicClient());
}
// KEYCLOAK-6771 Certificate Bound Token