Skip to content

Commit

Permalink
protocol mappers changes for support List<String> fields, Bug Fix in …
Browse files Browse the repository at this point in the history
…Terms and Conditions
  • Loading branch information
cgeorgilakis-grnet committed Feb 12, 2024
1 parent bb06914 commit b9aa04c
Show file tree
Hide file tree
Showing 20 changed files with 124 additions and 29 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Our Keycloak version is working well with PostgreSQL database. For using other S
- Database script for migration from version 18.0.1-2.17 to 22.0.5-1.1
- Mapper for generating SAML attribute values or Claim values using IdP alias or IdP entity attributes or User Attribute values [Mapper for generating SAML attribute values or Claim values using other SAML attribute/Claim values as input](https://trello.com/c/8K46f2mo/1642-mapper-for-generating-saml-attribute-values-or-claim-values-using-other-saml-attribute-claim-values-as-input)
- SAML IdP entity attributes [How to store IdP entity attributes in Keycloak](https://trello.com/c/wzF5s6Oi/2409-how-to-store-idp-entity-attributes-in-keycloak)
- List<String> fields in protocol mappers [Fix problem with List<String> fields in client scopes & attribute mapper configuration](https://trello.com/c/TrJyTo1B/2349-fix-problem-with-liststring-fields-in-client-scopes-attribute-mapper-configuration)

### Changed
- Increase User Attribute Value length to 4000 [EOSC-KC-132](https://github.com/eosc-kc/keycloak/issues/132)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class ConfigPropertyRepresentation {
protected List<String> options;
protected boolean secret;
private boolean readOnly;
protected Boolean stringify;

public String getName() {
return name;
Expand Down Expand Up @@ -96,4 +97,12 @@ public void setReadOnly(boolean readOnly) {
public boolean isReadOnly() {
return readOnly;
}

public Boolean getStringify() {
return stringify;
}

public void setStringify(Boolean stringify) {
this.stringify = stringify;
}
}
3 changes: 2 additions & 1 deletion js/apps/admin-ui/public/locales/en/client-scopes.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,6 @@
"createPolicy": "Create Policy",
"addPolicyValue":"Add Policy Value",
"dynamicScopeFilteringClaim":"Dynamic scope filtering claim",
"userAttributeField": "User Attribute"
"userAttributeField": "User Attribute",
"addUserAttribute": "Add user attribute"
}
28 changes: 27 additions & 1 deletion js/apps/admin-ui/src/authentication/TermsAndConditions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ export default function TermsAndConditions() {
name: "defaultAction",
}) as boolean;

const resetEvery = useWatch({
control,
name: "config.reset_every",
}) as number;

useFetch(
async () => {
const requiredActions =
Expand Down Expand Up @@ -123,7 +128,12 @@ export default function TermsAndConditions() {
{ alias: termsAndConditions.alias! },
termsAndConditions,
);
setValue("enabled", !enabled);
// Update the corresponding state value
if (field === "enabled") {
setValue("enabled", !enabled);
} else if (field === "defaultAction") {
setValue("defaultAction", !defaultAction);
}
addAlert(t("updateTermsResetSuccess"), AlertVariant.success);
}
} catch (error) {
Expand Down Expand Up @@ -176,6 +186,9 @@ export default function TermsAndConditions() {
<Controller
name="config.reset_every"
control={control}
rules={{
min: 1,
}}
render={({ field }) => {
const v = Number(field.value);
return (
Expand All @@ -185,6 +198,7 @@ export default function TermsAndConditions() {
min={1}
max={2147483}
value={v}
validated={errors.config?.reset_every ? "error" : "default"}
allowEmptyInput={true}
readOnly
onPlus={() => field.onChange(v + 1)}
Expand All @@ -202,6 +216,15 @@ export default function TermsAndConditions() {
<Controller
name="config.reset_every_multiplier"
control={control}
rules={{
validate: (reset_every_multiplier) => {
if (resetEvery && !reset_every_multiplier) {
return "error";
} else {
return true;
}
},
}}
render={({ field }) => {
return (
<Select
Expand All @@ -213,6 +236,9 @@ export default function TermsAndConditions() {
setResetMultiplierOpen(false);
}}
variant={SelectVariant.single}
validated={
errors.config?.reset_every_multiplier ? "error" : "default"
}
isOpen={resetMultiplierOpen}
width={150}
selections={
Expand Down
9 changes: 8 additions & 1 deletion js/apps/admin-ui/src/client-scopes/EditClientScope.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ export default function EditClientScope() {
};
},
(clientScope) => {
if (clientScope.attributes?.["dynamic.scope.user.attribute"]) {
clientScope.attributes["dynamic.scope.user.attribute"] =
clientScope.attributes["dynamic.scope.user.attribute"].split("##");
}
setClientScope(clientScope);
},
[key, id],
Expand Down Expand Up @@ -118,7 +122,10 @@ export default function EditClientScope() {
...formData,
name: formData.name?.trim().replace(/ /g, "_"),
});

if (clientScope.attributes?.["dynamic.scope.user.attribute"]) {
clientScope.attributes["dynamic.scope.user.attribute"] =
clientScope.attributes["dynamic.scope.user.attribute"].join("##");
}
try {
await adminClient.clientScopes.update({ id }, clientScope);
await changeScope({ ...clientScope, id }, clientScope.type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ export default function MappingDetails() {
if (!data) {
throw new Error(t("common:notFound"));
}

const mapperTypes = serverInfo.protocolMapperTypes![data!.protocol!];
const mapping = mapperTypes.find(
(type) => type.id === data!.protocolMapper,
Expand Down
25 changes: 19 additions & 6 deletions js/apps/admin-ui/src/client-scopes/details/ScopeForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { useLoginProviders } from "../../context/server-info/ServerInfoProvider"
import { convertAttributeNameToForm, convertToFormValues } from "../../util";
import useIsFeatureEnabled, { Feature } from "../../utils/useIsFeatureEnabled";
import { toClientScopes } from "../routes/ClientScopes";
import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput";

type ScopeFormProps = {
clientScope?: ClientScopeRepresentation;
Expand Down Expand Up @@ -159,13 +160,25 @@ export const ScopeForm = ({ clientScope, save }: ScopeFormProps) => {
label={t("dynamicScopeFilteringClaim")}
labelIcon={t("client-scopes-help:dynamicScopeFilteringClaim")}
/>
<TextControl
name={convertAttributeNameToForm<ClientScopeDefaultOptionalType>(
"attributes.dynamic.scope.user.attribute",
)}
<FormGroup
label={t("userAttributeField")}
labelIcon={t("client-scopes-help:userAttributeField")}
/>
fieldId="kc-userAttributeField"
labelIcon={
<HelpItem
helpText={t("client-scopes-help:userAttributeField")}
fieldLabelId="userAttributeField"
/>
}
>
<MultiLineInput
name={convertAttributeNameToForm<ClientScopeDefaultOptionalType>(
"attributes.dynamic.scope.user.attribute",
)}
aria-label={t("webAuthnPolicyAcceptableAaguids")}
addButtonLabel={t("addUserAttribute")}
stringify={true}
/>
</FormGroup>
</>
)}
</FormProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export const MultiValuedStringComponent = ({
}: ComponentProps) => {
const { t } = useTranslation("dynamic");
const fieldName = convertToName(name!);

return (
<FormGroup
label={t(label!)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ export interface ConfigPropertyRepresentation {
defaultValue?: object;
options?: string[];
secret?: boolean;
stringify?: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -1001,6 +1001,7 @@ public static ConfigPropertyRepresentation toRepresentation(ProviderConfigProper
propRep.setOptions(prop.getOptions());
propRep.setHelpText(prop.getHelpText());
propRep.setSecret(prop.isSecret());
propRep.setStringify(prop.isStringify());
return propRep;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public class ProviderConfigProperty {
protected List<String> options;
protected boolean secret;
private boolean readOnly;
protected Boolean stringify = null;

public ProviderConfigProperty() {
}
Expand Down Expand Up @@ -197,4 +198,12 @@ public void setReadOnly(boolean readOnly) {
public boolean isReadOnly() {
return readOnly;
}

public Boolean isStringify() {
return stringify;
}

public void setStringify(Boolean stringify) {
this.stringify = stringify;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ public class HardcodedClaimBasedOnAttributeMapper extends AbstractOIDCProtocolMa
property.setName(ProtocolMapperUtils.CLAIM_VALUE);
property.setLabel(ProtocolMapperUtils.CLAIM_VALUE_LABEL);
property.setHelpText(ProtocolMapperUtils.CONDITIONAL_CLAIM_VALUE_HELP_TEXT);
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setType(ProviderConfigProperty.MULTIVALUED_STRING_TYPE);
property.setStringify(Boolean.TRUE);
property.setDefaultValue("");
configProperties.add(property);

property = new ProviderConfigProperty();
Expand All @@ -33,7 +35,9 @@ public class HardcodedClaimBasedOnAttributeMapper extends AbstractOIDCProtocolMa
property.setName(ProtocolMapperUtils.USER_ATTRIBUTE_VALUES);
property.setLabel(ProtocolMapperUtils.USER_MODEL_CONDITIONAL_VALUES_LABEL);
property.setHelpText(ProtocolMapperUtils.USER_MODEL_CONDITIONAL_VALUES_HELP_TEXT);
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setType(ProviderConfigProperty.MULTIVALUED_STRING_TYPE);
property.setStringify(Boolean.TRUE);
property.setDefaultValue("");
configProperties.add(property);

OIDCAttributeMapperHelper.addAttributeConfig(configProperties, HardcodedClaimBasedOnAttributeMapper.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ public class HardcodedClaimBasedOnIdPAttributesMapper extends AbstractOIDCProtoc
property.setName(ProtocolMapperUtils.CLAIM_VALUE);
property.setLabel(ProtocolMapperUtils.CLAIM_VALUE_LABEL);
property.setHelpText(ProtocolMapperUtils.CONDITIONAL_CLAIM_VALUE_HELP_TEXT);
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setType(ProviderConfigProperty.MULTIVALUED_STRING_TYPE);
property.setStringify(Boolean.TRUE);
property.setDefaultValue("");
configProperties.add(property);

property = new ProviderConfigProperty();
Expand All @@ -46,7 +48,9 @@ public class HardcodedClaimBasedOnIdPAttributesMapper extends AbstractOIDCProtoc
property.setName(ProtocolMapperUtils.IDP_ATTRIBUTE_VALUES);
property.setLabel(ProtocolMapperUtils.IDP_ATTRIBUTE_VALUES_LABEL);
property.setHelpText(ProtocolMapperUtils.IDP_ATTRIBUTE_VALUES_HELP_TEXT);
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setType(ProviderConfigProperty.MULTIVALUED_STRING_TYPE);
property.setStringify(Boolean.TRUE);
property.setDefaultValue("");
configProperties.add(property);

OIDCAttributeMapperHelper.addAttributeConfig(configProperties, HardcodedClaimBasedOnAttributeMapper.class);
Expand Down Expand Up @@ -96,7 +100,7 @@ protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSes
OIDCAttributeMapperHelper.mapClaim(token, mappingModel, attributeValues.size() == 1 ? attributeValues.get(0) : attributeValues);
}
} catch (IOException e) {
logger.warn("problem executing HardcodedClaimBasedOnIdPAttributesMapper");
logger.warn("problem executing HardcodedAttributeBasedOnIdPAttributesMapper");
e.printStackTrace();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,19 @@ public class HardcodedClaimBasedOnIdPMapper extends AbstractOIDCProtocolMapper i
ProviderConfigProperty property = new ProviderConfigProperty();
property.setName(ProtocolMapperUtils.CLAIM_VALUE);
property.setLabel(ProtocolMapperUtils.CLAIM_VALUE_LABEL);
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setHelpText(ProtocolMapperUtils.CONDITIONAL_CLAIM_VALUE_HELP_TEXT);
property.setType(ProviderConfigProperty.MULTIVALUED_STRING_TYPE);
property.setStringify(Boolean.TRUE);
property.setDefaultValue("");
configProperties.add(property);

property = new ProviderConfigProperty();
property.setName(ProtocolMapperUtils.IDP_ALIAS);
property.setLabel(ProtocolMapperUtils.IDP_ALIAS_LABEL);
property.setHelpText(ProtocolMapperUtils.IDP_ALIAS_HELP_TEXT);
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setType(ProviderConfigProperty.MULTIVALUED_STRING_TYPE);
property.setStringify(Boolean.TRUE);
property.setDefaultValue("");
configProperties.add(property);

property = new ProviderConfigProperty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ public class UserAttributeMapper extends AbstractOIDCProtocolMapper implements O
property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
property.setLabel(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_LABEL);
property.setHelpText(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_HELP_TEXT);
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setType(ProviderConfigProperty.MULTIVALUED_STRING_TYPE);
property.setStringify(Boolean.TRUE);
property.setDefaultValue("");
configProperties.add(property);
OIDCAttributeMapperHelper.addAttributeConfig(configProperties, UserAttributeMapper.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ public class HardcodedAttributeBasedOnAttributeMapper extends AbstractSAMLProtoc
property.setName(ProtocolMapperUtils.ATTRIBUTE_VALUE);
property.setLabel(ProtocolMapperUtils.ATTRIBUTE_CONDITIONAL_VALUES_LABEL);
property.setHelpText(ProtocolMapperUtils.ATTRIBUTE_CONDITIONAL_VALUES_HELP_TEXT);
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setType(ProviderConfigProperty.MULTIVALUED_STRING_TYPE);
property.setStringify(Boolean.TRUE);
property.setDefaultValue("");
configProperties.add(property);

property = new ProviderConfigProperty();
Expand All @@ -30,7 +32,9 @@ public class HardcodedAttributeBasedOnAttributeMapper extends AbstractSAMLProtoc
property.setName(ProtocolMapperUtils.USER_ATTRIBUTE_VALUES);
property.setLabel(ProtocolMapperUtils.USER_MODEL_CONDITIONAL_VALUES_LABEL);
property.setHelpText(ProtocolMapperUtils.USER_MODEL_CONDITIONAL_VALUES_HELP_TEXT);
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setType(ProviderConfigProperty.MULTIVALUED_STRING_TYPE);
property.setStringify(Boolean.TRUE);
property.setDefaultValue("");
configProperties.add(property);

property = new ProviderConfigProperty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,18 @@
import java.util.List;
import java.util.Map;

public class HardcodedClaimBasedOnIdPAttributesMapper extends AbstractSAMLProtocolMapper implements SAMLAttributeStatementMapper {
private static final Logger logger = Logger.getLogger(HardcodedClaimBasedOnIdPAttributesMapper.class);
public class HardcodedAttributeBasedOnIdPAttributesMapper extends AbstractSAMLProtocolMapper implements SAMLAttributeStatementMapper {
private static final Logger logger = Logger.getLogger(HardcodedAttributeBasedOnIdPAttributesMapper.class);
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();

static {
ProviderConfigProperty property = new ProviderConfigProperty();
property.setName(ProtocolMapperUtils.ATTRIBUTE_VALUE);
property.setLabel(ProtocolMapperUtils.ATTRIBUTE_CONDITIONAL_VALUES_LABEL);
property.setHelpText(ProtocolMapperUtils.ATTRIBUTE_CONDITIONAL_VALUES_HELP_TEXT);
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setType(ProviderConfigProperty.MULTIVALUED_STRING_TYPE);
property.setStringify(Boolean.TRUE);
property.setDefaultValue("");
configProperties.add(property);

property = new ProviderConfigProperty();
Expand All @@ -46,7 +48,9 @@ public class HardcodedClaimBasedOnIdPAttributesMapper extends AbstractSAMLProtoc
property.setName(ProtocolMapperUtils.IDP_ATTRIBUTE_VALUES);
property.setLabel(ProtocolMapperUtils.IDP_ATTRIBUTE_VALUES_LABEL);
property.setHelpText(ProtocolMapperUtils.IDP_ATTRIBUTE_VALUES_HELP_TEXT);
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setType(ProviderConfigProperty.MULTIVALUED_STRING_TYPE);
property.setStringify(Boolean.TRUE);
property.setDefaultValue("");
configProperties.add(property);

AttributeStatementHelper.setConfigProperties(configProperties);
Expand Down Expand Up @@ -97,7 +101,7 @@ public void transformAttributeStatement(AttributeStatementType attributeStatemen
AttributeStatementHelper.addAttributes(attributeStatement, mappingModel, attributeValues);
}
} catch (IOException e) {
logger.warn("problem executing HardcodedClaimBasedOnIdPAttributesMapper");
logger.warn("problem executing HardcodedAttributeBasedOnIdPAttributesMapper");
e.printStackTrace();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,18 @@ public class HardcodedAttributeBasedOnIdPMapper extends AbstractSAMLProtocolMapp
property.setName(ProtocolMapperUtils.ATTRIBUTE_VALUE);
property.setLabel(ProtocolMapperUtils.ATTRIBUTE_CONDITIONAL_VALUES_LABEL);
property.setHelpText(ProtocolMapperUtils.ATTRIBUTE_CONDITIONAL_VALUES_HELP_TEXT);
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setType(ProviderConfigProperty.MULTIVALUED_STRING_TYPE);
property.setStringify(Boolean.TRUE);
property.setDefaultValue("");
configProperties.add(property);

property = new ProviderConfigProperty();
property.setName(ProtocolMapperUtils.IDP_ALIAS);
property.setLabel(ProtocolMapperUtils.IDP_ALIAS_LABEL);
property.setHelpText(ProtocolMapperUtils.IDP_ALIAS_HELP_TEXT);
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setType(ProviderConfigProperty.MULTIVALUED_STRING_TYPE);
property.setStringify(Boolean.TRUE);
property.setDefaultValue("");
configProperties.add(property);
AttributeStatementHelper.setConfigProperties(configProperties);

Expand Down
Loading

0 comments on commit b9aa04c

Please sign in to comment.