Moved PKCE Code Challenge Method to more prominent section (#39631)

fixes: #30227

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
This commit is contained in:
Erik Jan de Wit 2025-05-22 13:56:50 +02:00 committed by GitHub
parent 4c1507f4ff
commit 59e99ed5d5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 44 additions and 81 deletions

View File

@ -1,16 +1,16 @@
import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation";
import { HelpItem, SelectControl } from "@keycloak/keycloak-ui-shared";
import {
Checkbox,
FormGroup,
Grid,
GridItem,
InputGroup,
Switch,
InputGroupItem,
Switch,
} from "@patternfly/react-core";
import { Controller, useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { HelpItem } from "@keycloak/keycloak-ui-shared";
import { DefaultSwitchControl } from "../../components/SwitchControl";
import { FormAccess } from "../../components/form/FormAccess";
import { convertAttributeNameToForm } from "../../util";
@ -338,6 +338,20 @@ export const CapabilityConfig = ({
</GridItem>
</Grid>
</FormGroup>
<SelectControl
id="keyForCodeExchange"
label={t("keyForCodeExchange")}
labelIcon={t("keyForCodeExchangeHelp")}
controller={{ defaultValue: "" }}
name={convertAttributeNameToForm<FormFields>(
"attributes.pkce.code.challenge.method",
)}
options={[
{ key: "", value: t("choose") },
{ key: "S256", value: "S256" },
{ key: "plain", value: "plain" },
]}
/>
</>
)}
{protocol === "saml" && (

View File

@ -1,14 +1,5 @@
import { HelpItem, TextControl } from "@keycloak/keycloak-ui-shared";
import {
ActionGroup,
Button,
FormGroup,
MenuToggle,
Select,
SelectList,
SelectOption,
} from "@patternfly/react-core";
import { useState } from "react";
import { ActionGroup, Button, FormGroup } from "@patternfly/react-core";
import { Controller, useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { DefaultSwitchControl } from "../../components/SwitchControl";
@ -36,7 +27,6 @@ export const AdvancedSettings = ({
hasConfigureAccess,
}: AdvancedSettingsProps) => {
const { t } = useTranslation();
const [open, setOpen] = useState(false);
const { realmRepresentation: realm } = useRealm();
@ -144,54 +134,6 @@ export const AdvancedSettings = ({
stringify
/>
)}
<FormGroup
label={t("keyForCodeExchange")}
fieldId="keyForCodeExchange"
hasNoPaddingTop
labelIcon={
<HelpItem
helpText={t("keyForCodeExchangeHelp")}
fieldLabelId="keyForCodeExchange"
/>
}
>
<Controller
name={convertAttributeNameToForm<FormFields>(
"attributes.pkce.code.challenge.method",
)}
defaultValue=""
control={control}
render={({ field }) => (
<Select
toggle={(ref) => (
<MenuToggle
id="keyForCodeExchange"
ref={ref}
onClick={() => setOpen(!open)}
isExpanded={open}
>
{[field.value || t("choose")]}
</MenuToggle>
)}
isOpen={open}
onOpenChange={(isOpen) => setOpen(isOpen)}
onSelect={(_, value) => {
field.onChange(value);
setOpen(false);
}}
selected={field.value}
>
<SelectList>
{["", "S256", "plain"].map((v) => (
<SelectOption key={v} value={v}>
{v || t("choose")}
</SelectOption>
))}
</SelectList>
</Select>
)}
/>
</FormGroup>
<DefaultSwitchControl
name={convertAttributeNameToForm<FormFields>(
"attributes.require.pushed.authorization.requests",

View File

@ -8,7 +8,6 @@ import {
assertAccessTokenSignatureAlgorithm,
assertAdvancedSwitchesOn,
assertBrowserFlowInput,
assertKeyForCodeExchangeInput,
assertOnExcludeSessionStateSwitch,
assertTestClusterAvailability,
assertTokenLifespanClientOfflineSessionMaxVisible,
@ -28,7 +27,6 @@ import {
selectAccessTokenSignatureAlgorithm,
selectBrowserFlowInput,
selectDirectGrantInput,
selectKeyForCodeExchangeInput,
switchOffExcludeSessionStateSwitch,
saveAuthFlowOverride,
revertAuthFlowOverride,
@ -83,15 +81,10 @@ test.describe("Advanced tab test", () => {
test("Advanced settings", async ({ page }) => {
await clickAdvancedSwitches(page);
await selectKeyForCodeExchangeInput(page, "S256");
await saveAdvanced(page);
await assertAdvancedSwitchesOn(page);
await assertKeyForCodeExchangeInput(page, "S256");
await selectKeyForCodeExchangeInput(page, "plain");
await assertKeyForCodeExchangeInput(page, "plain");
await clickAdvancedSwitches(page, false);
await revertAdvanced(page);
await assertKeyForCodeExchangeInput(page, "S256");
await assertAdvancedSwitchesOn(page);
});

View File

@ -125,18 +125,6 @@ export async function assertAdvancedSwitchesOn(page: Page) {
).toBeChecked();
}
function getKeyForCodeExchangeInput(page: Page) {
return page.locator("#keyForCodeExchange");
}
export async function selectKeyForCodeExchangeInput(page: Page, value: string) {
await selectItem(page, getKeyForCodeExchangeInput(page), value);
}
export async function assertKeyForCodeExchangeInput(page: Page, value: string) {
await assertSelectValue(getKeyForCodeExchangeInput(page), value);
}
export async function saveAdvanced(page: Page) {
await page.getByTestId("OIDCAdvancedSave").click();
}

View File

@ -5,8 +5,12 @@ import { assertRequiredFieldError } from "../utils/form";
import { login } from "../utils/login";
import { assertNotificationMessage } from "../utils/masthead";
import { goToClients, goToRealm } from "../utils/sidebar";
import { searchItem } from "../utils/table";
import { clickTableRowItem, searchItem } from "../utils/table";
import { continueNext, createClient, save } from "./utils";
import {
assertKeyForCodeExchangeInput,
selectKeyForCodeExchangeInput,
} from "./details";
test.describe("Clients details test", () => {
const realmName = `clients-details-realm-${uuid()}`;
@ -61,4 +65,12 @@ test.describe("Clients details test", () => {
await assertNotificationMessage(page, "Client created successfully");
});
test("Should be able to update a client", async ({ page }) => {
await clickTableRowItem(page, clientId);
await selectKeyForCodeExchangeInput(page, "S256");
await save(page);
await assertNotificationMessage(page, "Client successfully updated");
await assertKeyForCodeExchangeInput(page, "S256");
});
});

View File

@ -0,0 +1,14 @@
import { Page } from "@playwright/test";
import { selectItem, assertSelectValue } from "../utils/form";
function getKeyForCodeExchangeInput(page: Page) {
return page.locator("#keyForCodeExchange");
}
export async function selectKeyForCodeExchangeInput(page: Page, value: string) {
await selectItem(page, getKeyForCodeExchangeInput(page), value);
}
export async function assertKeyForCodeExchangeInput(page: Page, value: string) {
await assertSelectValue(getKeyForCodeExchangeInput(page), value);
}