Fixes SAML provider AuthnContext Constraints fields (#2231)

* no multiline for now

* multiline work in progress

* changed to JSON.stringify

* both multiline fields working

* check for undefined to prevent JSON issue

* streamline saml and oidc provider tests

* final tests and misc fixes

Co-authored-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
This commit is contained in:
mfrances17 2022-03-16 07:25:01 -04:00 committed by GitHub
parent e672849935
commit 45b6be4fe8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 122 additions and 58 deletions

View file

@ -26,7 +26,6 @@ describe("OIDC identity provider test", () => {
const authorizationUrl = `${keycloakServer}/realms/master/protocol/openid-connect/auth`;
describe("OIDC Identity provider creation", () => {
const identityProviderName = "github";
const oidcProviderName = "oidc";
const secret = "123";
@ -36,25 +35,14 @@ describe("OIDC identity provider test", () => {
sidebarPage.goToIdentityProviders();
});
it("should create provider", () => {
createProviderPage.checkGitHubCardVisible().clickGitHubCard();
createProviderPage.checkAddButtonDisabled();
createProviderPage
.fill(identityProviderName)
.clickAdd()
.checkClientIdRequiredMessage(true);
createProviderPage.fill(identityProviderName, secret).clickAdd();
masthead.checkNotificationMessage(createSuccessMsg, true);
sidebarPage.goToIdentityProviders();
listingPage.itemExist(identityProviderName);
});
it("should create an OIDC provider using discovery url", () => {
createProviderPage
.clickCreateDropdown()
.clickItem(oidcProviderName)
.checkVisible(oidcProviderName)
.clickCard(oidcProviderName);
createProviderPage.checkAddButtonDisabled();
createProviderPage
.fillDiscoveryUrl(discoveryUrl)
.shouldBeSuccessful()
.fill(oidcProviderName, secret)
@ -88,11 +76,6 @@ describe("OIDC identity provider test", () => {
listingPage.itemExist(oidcProviderName).deleteItem(oidcProviderName);
modalUtils.checkModalTitle(deletePrompt).confirmModal();
masthead.checkNotificationMessage(deleteSuccessMsg, true);
listingPage
.itemExist(identityProviderName)
.deleteItem(identityProviderName);
modalUtils.checkModalTitle(deletePrompt).confirmModal();
masthead.checkNotificationMessage(deleteSuccessMsg, true);
});
});
});

View file

@ -7,7 +7,7 @@ import CreateProviderPage from "../support/pages/admin_console/manage/identity_p
import ModalUtils from "../support/util/ModalUtils";
import AddMapperPage from "../support/pages/admin_console/manage/identity_providers/AddMapperPage";
describe("Identity provider test", () => {
describe("SAML identity provider test", () => {
const loginPage = new LoginPage();
const sidebarPage = new SidebarPage();
const masthead = new Masthead();
@ -16,19 +16,22 @@ describe("Identity provider test", () => {
const addMapperPage = new AddMapperPage();
const createSuccessMsg = "Identity provider successfully created";
const saveSuccessMsg = "Provider successfully updated";
const createMapperSuccessMsg = "Mapper created successfully.";
const saveMapperSuccessMsg = "Mapper saved successfully.";
const deletePrompt = "Delete provider?";
const deleteSuccessMsg = "Provider successfully deleted";
const classRefName = "acClassRef-1";
const declRefName = "acDeclRef-1";
const keycloakServer = Cypress.env("KEYCLOAK_SERVER");
const samlDiscoveryUrl = `${keycloakServer}/realms/master/protocol/saml/descriptor`;
describe("SAML identity provider creation", () => {
const identityProviderName = "github";
const samlProviderName = "saml";
const secret = "123";
beforeEach(() => {
keycloakBefore();
@ -36,31 +39,30 @@ describe("Identity provider test", () => {
sidebarPage.goToIdentityProviders();
});
it("should create provider", () => {
createProviderPage.checkGitHubCardVisible().clickGitHubCard();
it("should create a SAML provider using entity descriptor", () => {
createProviderPage
.checkVisible(samlProviderName)
.clickCard(samlProviderName);
createProviderPage.checkAddButtonDisabled();
createProviderPage
.fill(identityProviderName)
.clickAdd()
.checkClientIdRequiredMessage(true);
createProviderPage.fill(identityProviderName, secret).clickAdd();
masthead.checkNotificationMessage(createSuccessMsg, true);
sidebarPage.goToIdentityProviders();
listingPage.itemExist(identityProviderName);
});
it("should create a SAML provider using SSO service url", () => {
createProviderPage
.clickCreateDropdown()
.clickItem(samlProviderName)
.fillDiscoveryUrl(samlDiscoveryUrl)
.shouldBeSuccessful()
.clickAdd();
masthead.checkNotificationMessage(createSuccessMsg, true);
});
it("should add auth constraints to existing SAML provider", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails(samlProviderName);
createProviderPage
.fillAuthnContextClassRefs(classRefName)
.clickClassRefsAdd()
.fillAuthnContextDeclRefs(declRefName)
.clickDeclRefsAdd()
.clickSave();
masthead.checkNotificationMessage(saveSuccessMsg, true);
});
it("should add SAML mapper of type Advanced Attribute to Role", () => {
sidebarPage.goToIdentityProviders();
listingPage.goToItemDetails(samlProviderName);
@ -153,11 +155,6 @@ describe("Identity provider test", () => {
listingPage.itemExist(samlProviderName).deleteItem(samlProviderName);
modalUtils.checkModalTitle(deletePrompt).confirmModal();
masthead.checkNotificationMessage(deleteSuccessMsg, true);
listingPage
.itemExist(identityProviderName)
.deleteItem(identityProviderName);
modalUtils.checkModalTitle(deletePrompt).confirmModal();
masthead.checkNotificationMessage(deleteSuccessMsg, true);
});
});
});

View file

@ -7,7 +7,13 @@ export default class CreateProviderPage {
private discoveryEndpoint = "discoveryEndpoint";
private authorizationUrl = "authorizationUrl";
private addButton = "createProvider";
private saveButton = "save";
private ssoServiceUrl = "sso-service-url";
private authnContextClassRefs = "classref-field";
private authnContextDeclRefs = "declref-field";
private addProvider = "Add provider";
private addClassRef = "Add AuthnContext ClassRef";
private addDeclRef = "Add AuthnContext DeclRef";
checkVisible(name: string) {
cy.findByTestId(`${name}-card`).should("exist");
@ -47,8 +53,23 @@ export default class CreateProviderPage {
return this;
}
clickSave() {
cy.findByTestId(this.saveButton).click();
return this;
}
clickClassRefsAdd() {
cy.contains(this.addClassRef).click();
return this;
}
clickDeclRefsAdd() {
cy.contains(this.addDeclRef).click();
return this;
}
clickCreateDropdown() {
cy.contains("Add provider").click();
cy.contains(this.addProvider).click();
return this;
}
@ -77,6 +98,18 @@ export default class CreateProviderPage {
return this;
}
fillAuthnContextClassRefs(value: string) {
cy.findByTestId(this.authnContextClassRefs).type("x");
cy.findByTestId(this.authnContextClassRefs).clear().type(value).blur();
return this;
}
fillAuthnContextDeclRefs(value: string) {
cy.findByTestId(this.authnContextDeclRefs).type("x");
cy.findByTestId(this.authnContextDeclRefs).clear().type(value).blur();
return this;
}
fillSsoServiceUrl(value: string) {
cy.findByTestId(this.ssoServiceUrl).type("x");
cy.findByTestId(this.ssoServiceUrl).clear().type(value).blur();

View file

@ -141,12 +141,34 @@ export default function DetailSettings() {
reset(fetchedProvider);
setProvider(fetchedProvider);
if (fetchedProvider.config!.authnContextClassRefs) {
form.setValue(
"config.authnContextClassRefs",
JSON.parse(fetchedProvider.config?.authnContextClassRefs)
);
}
if (fetchedProvider.config!.authnContextDeclRefs) {
form.setValue(
"config.authnContextDeclRefs",
JSON.parse(fetchedProvider.config?.authnContextDeclRefs)
);
}
},
[]
);
const save = async (provider?: IdentityProviderRepresentation) => {
const p = provider || getValues();
if (p.config?.authnContextClassRefs)
p.config.authnContextClassRefs = JSON.stringify(
p.config.authnContextClassRefs
);
if (p.config?.authnContextDeclRefs)
p.config.authnContextDeclRefs = JSON.stringify(
p.config.authnContextDeclRefs
);
try {
await adminClient.identityProviders.update(
{ alias },

View file

@ -8,7 +8,7 @@ import {
SelectVariant,
} from "@patternfly/react-core";
import { TextField } from "../component/TextField";
import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput";
import { HelpItem } from "../../components/help-enabler/HelpItem";
const comparisonValues = ["exact", "minimum", "maximum", "better"];
@ -61,14 +61,40 @@ export const ReqAuthnConstraints = () => {
)}
/>
</FormGroup>
<TextField
field="config.authnContextClassRefs"
label="authnContextClassRefs"
/>
<TextField
field="config.authnContextDeclRefs"
label="authnContextDeclRefs"
/>
<FormGroup
label={t("authnContextClassRefs")}
fieldId="kc-authnContextClassRefs"
labelIcon={
<HelpItem
helpText="identity-providers-help:authnContextClassRefs"
fieldLabelId="authnContextClassRefs"
/>
}
>
<MultiLineInput
name="config.authnContextClassRefs"
aria-label={t("identify-providers:authnContextClassRefs")}
addButtonLabel="identity-providers:addAuthnContextClassRef"
data-testid="classref-field"
/>
</FormGroup>
<FormGroup
label={t("authnContextDeclRefs")}
fieldId="kc-authnContextDeclRefs"
labelIcon={
<HelpItem
helpText="identity-providers-help:authnContextDeclRefs"
fieldLabelId="authnContextDeclRefs"
/>
}
>
<MultiLineInput
name="config.authnContextDeclRefs"
aria-label={t("identify-providers:authnContextDeclRefs")}
addButtonLabel="identity-providers:addAuthnContextDeclRef"
data-testid="declref-field"
/>
</FormGroup>
</>
);
};

View file

@ -27,6 +27,7 @@ export const DisplayOrder = () => {
defaultValue=""
render={({ onChange, value }) => (
<TextInput
id="displayOrder"
type="number"
value={value}
data-testid="displayOrder"

View file

@ -147,7 +147,9 @@ export default {
storedTokensReadable: "Stored tokens readable",
comparison: "Comparison",
authnContextClassRefs: "AuthnContext ClassRefs",
addAuthnContextClassRef: "Add AuthnContext ClassRef",
authnContextDeclRefs: "AuthnContext DeclRefs",
addAuthnContextDeclRef: "Add AuthnContext DeclRef",
trustEmail: "Trust Email",
accountLinkingOnly: "Account linking only",
hideOnLoginPage: "Hide on login page",