fix: hardcoded conditional rendering of client secret input field (#25776)

Closes #22660

Signed-off-by: ImFlog <garcia.florian.perso@gmail.com>
Co-authored-by: useresd <yousifmagdi@gmail.com>
This commit is contained in:
Florian Garcia 2024-01-24 16:30:22 +01:00 committed by GitHub
parent 4061abf588
commit af0b9164e3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 55 additions and 32 deletions

View file

@ -67,6 +67,10 @@ export const Credentials = ({ client, save, refresh }: CredentialsProps) => {
const [accessToken, setAccessToken] = useState("");
const [open, isOpen] = useState(false);
const selectedProvider = providers.find(
(provider) => provider.id === clientAuthenticatorType,
);
useFetch(
() =>
Promise.all([
@ -200,17 +204,17 @@ export const Credentials = ({ client, save, refresh }: CredentialsProps) => {
</Button>
</ActionGroup>
</CardBody>
{(clientAuthenticatorType === "client-secret" ||
clientAuthenticatorType === "client-secret-jwt") && <Divider />}
{(clientAuthenticatorType === "client-secret" ||
clientAuthenticatorType === "client-secret-jwt") && (
<CardBody>
<ClientSecret
client={client}
secret={secret}
toggle={toggleClientSecretConfirm}
/>
</CardBody>
{selectedProvider?.supportsSecret && (
<>
<Divider />
<CardBody>
<ClientSecret
client={client}
secret={secret}
toggle={toggleClientSecretConfirm}
/>
</CardBody>
</>
)}
</Card>
<Card isFlat>

View file

@ -13,4 +13,5 @@ export interface AuthenticationProviderRepresentation {
id?: string;
displayName?: string;
description?: string;
supportsSecret?: boolean;
}

View file

@ -158,17 +158,27 @@ public class AuthenticationManagementResource {
@Operation( summary = "Get client authenticator providers Returns a stream of client authenticator providers.")
public Stream<Map<String, Object>> getClientAuthenticatorProviders() {
auth.realm().requireViewClientAuthenticatorProviders();
Stream<ProviderFactory> factories = session.getKeycloakSessionFactory().getProviderFactoriesStream(ClientAuthenticator.class);
return buildProviderMetadata(session.getKeycloakSessionFactory().getProviderFactoriesStream(ClientAuthenticator.class));
return factories.map(factory -> {
Map<String, Object> data = new HashMap<>();
buildProviderMetadataHelper(data, factory);
data.put("supportsSecret", ((ClientAuthenticatorFactory) factory).supportsSecret());
return data;
});
}
private void buildProviderMetadataHelper(Map<String, Object> data, ProviderFactory factory) {
data.put("id", factory.getId());
ConfigurableAuthenticatorFactory configured = (ConfigurableAuthenticatorFactory) factory;
data.put("description", configured.getHelpText());
data.put("displayName", configured.getDisplayType());
}
public Stream<Map<String, Object>> buildProviderMetadata(Stream<ProviderFactory> factories) {
return factories.map(factory -> {
Map<String, Object> data = new HashMap<>();
data.put("id", factory.getId());
ConfigurableAuthenticatorFactory configured = (ConfigurableAuthenticatorFactory)factory;
data.put("description", configured.getHelpText());
data.put("displayName", configured.getDisplayType());
buildProviderMetadataHelper(data, factory);
return data;
});
}

View file

@ -80,20 +80,20 @@ public class ProvidersTest extends AbstractAuthenticationTest {
List<Map<String, Object>> result = authMgmtResource.getClientAuthenticatorProviders();
List<Map<String, Object>> expected = new LinkedList<>();
addProviderInfo(expected, "client-jwt", "Signed Jwt",
"Validates client based on signed JWT issued by client and signed with the Client private key");
addProviderInfo(expected, "client-secret", "Client Id and Secret", "Validates client based on 'client_id' and " +
"'client_secret' sent either in request parameters or in 'Authorization: Basic' header");
addProviderInfo(expected, "testsuite-client-passthrough", "Testsuite Dummy Client Validation", "Testsuite dummy authenticator, " +
"which automatically authenticates hardcoded client (like 'test-app' )");
addProviderInfo(expected, "testsuite-client-dummy", "Testsuite ClientId Dummy",
"Dummy client authenticator, which authenticates the client with clientId only");
addProviderInfo(expected, "client-x509", "X509 Certificate",
"Validates client based on a X509 Certificate");
addProviderInfo(expected, "client-secret-jwt", "Signed Jwt with Client Secret",
"Validates client based on signed JWT issued by client and signed with the Client Secret");
addProviderInfo(expected, "testsuite-client-id-required", "Signed Jwt",
"Validates client based on signed JWT issued by client and signed with the Client private key");
addClientAuthenticatorProviderInfo(expected, "client-jwt", "Signed Jwt",
"Validates client based on signed JWT issued by client and signed with the Client private key", false);
addClientAuthenticatorProviderInfo(expected, "client-secret", "Client Id and Secret", "Validates client based on 'client_id' and " +
"'client_secret' sent either in request parameters or in 'Authorization: Basic' header", true);
addClientAuthenticatorProviderInfo(expected, "testsuite-client-id-required", "Signed Jwt", "Validates client based on signed JWT issued by client " +
"and signed with the Client private key", false);
addClientAuthenticatorProviderInfo(expected, "testsuite-client-passthrough", "Testsuite Dummy Client Validation", "Testsuite dummy authenticator, " +
"which automatically authenticates hardcoded client (like 'test-app' )", false);
addClientAuthenticatorProviderInfo(expected, "testsuite-client-dummy", "Testsuite ClientId Dummy",
"Dummy client authenticator, which authenticates the client with clientId only", false);
addClientAuthenticatorProviderInfo(expected, "client-x509", "X509 Certificate",
"Validates client based on a X509 Certificate", false);
addClientAuthenticatorProviderInfo(expected, "client-secret-jwt", "Signed Jwt with Client Secret",
"Validates client based on signed JWT issued by client and signed with the Client Secret", true);
compareProviders(expected, result);
}
@ -259,12 +259,20 @@ public class ProvidersTest extends AbstractAuthenticationTest {
list.add(item);
}
private void addClientAuthenticatorProviderInfo(List<Map<String, Object>> list, String id, String displayName, String description, boolean supportsSecret) {
HashMap<String, Object> item = new HashMap<>();
item.put("id", id);
item.put("displayName", displayName);
item.put("description", description);
item.put("supportsSecret", supportsSecret);
list.add(item);
}
private static class ProviderComparator implements Comparator<Map<String, Object>> {
@Override
public int compare(Map<String, Object> o1, Map<String, Object> o2) {
return String.valueOf(o1.get("id")).compareTo(String.valueOf(o2.get("id")));
}
}
}