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

View file

@ -13,4 +13,5 @@ export interface AuthenticationProviderRepresentation {
id?: string; id?: string;
displayName?: string; displayName?: string;
description?: 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.") @Operation( summary = "Get client authenticator providers Returns a stream of client authenticator providers.")
public Stream<Map<String, Object>> getClientAuthenticatorProviders() { public Stream<Map<String, Object>> getClientAuthenticatorProviders() {
auth.realm().requireViewClientAuthenticatorProviders(); 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) { public Stream<Map<String, Object>> buildProviderMetadata(Stream<ProviderFactory> factories) {
return factories.map(factory -> { return factories.map(factory -> {
Map<String, Object> data = new HashMap<>(); Map<String, Object> data = new HashMap<>();
data.put("id", factory.getId()); buildProviderMetadataHelper(data, factory);
ConfigurableAuthenticatorFactory configured = (ConfigurableAuthenticatorFactory)factory;
data.put("description", configured.getHelpText());
data.put("displayName", configured.getDisplayType());
return data; return data;
}); });
} }

View file

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