diff --git a/docs/resources/keycloak_openid_user_attribute_protocol_mapper.md b/docs/resources/keycloak_openid_user_attribute_protocol_mapper.md index a7ea7a888..244a340a8 100644 --- a/docs/resources/keycloak_openid_user_attribute_protocol_mapper.md +++ b/docs/resources/keycloak_openid_user_attribute_protocol_mapper.md @@ -77,7 +77,7 @@ The following arguments are supported: - `add_to_id_token` - (Optional) Indicates if the attribute should be added as a claim to the id token. Defaults to `true`. - `add_to_access_token` - (Optional) Indicates if the attribute should be added as a claim to the access token. Defaults to `true`. - `add_to_userinfo` - (Optional) Indicates if the attribute should be added as a claim to the UserInfo response body. Defaults to `true`. - +- `aggregate_attributes`- (Optional) Indicates whether this attribute is a single value or an array of values. Defaults to `false`. ### Import Protocol mappers can be imported using one of the following formats: diff --git a/keycloak/openid_user_attribute_protocol_mapper.go b/keycloak/openid_user_attribute_protocol_mapper.go index ea9faf3a8..5a92d5628 100644 --- a/keycloak/openid_user_attribute_protocol_mapper.go +++ b/keycloak/openid_user_attribute_protocol_mapper.go @@ -20,7 +20,8 @@ type OpenIdUserAttributeProtocolMapper struct { ClaimName string ClaimValueType string - Multivalued bool // indicates whether is this an array of attributes or a single attribute + Multivalued bool // indicates whether is this an array of attributes or a single attribute + AggregateAttributeValues bool } func (mapper *OpenIdUserAttributeProtocolMapper) convertToGenericProtocolMapper() *protocolMapper { @@ -30,13 +31,14 @@ func (mapper *OpenIdUserAttributeProtocolMapper) convertToGenericProtocolMapper( Protocol: "openid-connect", ProtocolMapper: "oidc-usermodel-attribute-mapper", Config: map[string]string{ - addToIdTokenField: strconv.FormatBool(mapper.AddToIdToken), - addToAccessTokenField: strconv.FormatBool(mapper.AddToAccessToken), - addToUserInfoField: strconv.FormatBool(mapper.AddToUserInfo), - userAttributeField: mapper.UserAttribute, - claimNameField: mapper.ClaimName, - claimValueTypeField: mapper.ClaimValueType, - multivaluedField: strconv.FormatBool(mapper.Multivalued), + addToIdTokenField: strconv.FormatBool(mapper.AddToIdToken), + addToAccessTokenField: strconv.FormatBool(mapper.AddToAccessToken), + addToUserInfoField: strconv.FormatBool(mapper.AddToUserInfo), + userAttributeField: mapper.UserAttribute, + claimNameField: mapper.ClaimName, + claimValueTypeField: mapper.ClaimValueType, + multivaluedField: strconv.FormatBool(mapper.Multivalued), + aggregateAttributeValuesField: strconv.FormatBool(mapper.AggregateAttributeValues), }, } } @@ -63,6 +65,11 @@ func (protocolMapper *protocolMapper) convertToOpenIdUserAttributeProtocolMapper return nil, err } + aggregateAttributeValues, err := strconv.ParseBool(protocolMapper.Config[aggregateAttributeValuesField]) + if err != nil { + return nil, err + } + return &OpenIdUserAttributeProtocolMapper{ Id: protocolMapper.Id, Name: protocolMapper.Name, @@ -74,10 +81,11 @@ func (protocolMapper *protocolMapper) convertToOpenIdUserAttributeProtocolMapper AddToAccessToken: addToAccessToken, AddToUserInfo: addToUserInfo, - UserAttribute: protocolMapper.Config[userAttributeField], - ClaimName: protocolMapper.Config[claimNameField], - ClaimValueType: protocolMapper.Config[claimValueTypeField], - Multivalued: multivalued, + UserAttribute: protocolMapper.Config[userAttributeField], + ClaimName: protocolMapper.Config[claimNameField], + ClaimValueType: protocolMapper.Config[claimValueTypeField], + Multivalued: multivalued, + AggregateAttributeValues: aggregateAttributeValues, }, nil } diff --git a/keycloak/protocol_mapper.go b/keycloak/protocol_mapper.go index a72d57e4b..b041e36e8 100644 --- a/keycloak/protocol_mapper.go +++ b/keycloak/protocol_mapper.go @@ -28,6 +28,7 @@ var ( userAttributeField = "user.attribute" userPropertyField = "user.attribute" userRealmRoleMappingRolePrefixField = "usermodel.realmRoleMapping.rolePrefix" + aggregateAttributeValuesField = "aggregate.attrs" ) func protocolMapperPath(realmId, clientId, clientScopeId string) string { diff --git a/provider/resource_keycloak_openid_user_attribute_protocol_mapper.go b/provider/resource_keycloak_openid_user_attribute_protocol_mapper.go index 0800d0d04..1e87ca8a3 100644 --- a/provider/resource_keycloak_openid_user_attribute_protocol_mapper.go +++ b/provider/resource_keycloak_openid_user_attribute_protocol_mapper.go @@ -84,6 +84,12 @@ func resourceKeycloakOpenIdUserAttributeProtocolMapper() *schema.Resource { Default: "String", ValidateFunc: validation.StringInSlice([]string{"JSON", "String", "long", "int", "boolean"}, true), }, + "aggregate_attributes": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Indicates if attribute values should be aggregated within the group attributes", + }, }, } } @@ -99,10 +105,11 @@ func mapFromDataToOpenIdUserAttributeProtocolMapper(data *schema.ResourceData) * AddToAccessToken: data.Get("add_to_access_token").(bool), AddToUserInfo: data.Get("add_to_userinfo").(bool), - UserAttribute: data.Get("user_attribute").(string), - ClaimName: data.Get("claim_name").(string), - ClaimValueType: data.Get("claim_value_type").(string), - Multivalued: data.Get("multivalued").(bool), + UserAttribute: data.Get("user_attribute").(string), + ClaimName: data.Get("claim_name").(string), + ClaimValueType: data.Get("claim_value_type").(string), + Multivalued: data.Get("multivalued").(bool), + AggregateAttributeValues: data.Get("aggregate_attributes").(bool), } } @@ -124,6 +131,7 @@ func mapFromOpenIdUserAttributeMapperToData(mapper *keycloak.OpenIdUserAttribute data.Set("claim_name", mapper.ClaimName) data.Set("claim_value_type", mapper.ClaimValueType) data.Set("multivalued", mapper.Multivalued) + data.Set("aggregate_attributes", mapper.AggregateAttributeValues) } func resourceKeycloakOpenIdUserAttributeProtocolMapperCreate(data *schema.ResourceData, meta interface{}) error {