Skip to content

Commit

Permalink
Model OIDC Gender as a simple string.
Browse files Browse the repository at this point in the history
  • Loading branch information
dzarras committed Nov 25, 2024
1 parent be9affd commit 3c6c255
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 35 deletions.
36 changes: 35 additions & 1 deletion docker-compose/keycloak/realms/pid-issuer-realm-realm.json
Original file line number Diff line number Diff line change
Expand Up @@ -1228,6 +1228,23 @@
"jsonType.label": "String"
}
},
{
"id": "5343c74e-e247-4b85-bf79-3ff843aee565",
"name": "gender_as_string",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "false",
"userinfo.token.claim": "true",
"user.attribute": "gender_as_string",
"id.token.claim": "false",
"lightweight.claim": "false",
"access.token.claim": "false",
"claim.name": "gender_as_string",
"jsonType.label": "String"
}
},
{
"id": "73819e2a-eed3-428c-911c-47b1077af59e",
"name": "birth_place",
Expand Down Expand Up @@ -1536,6 +1553,23 @@
"jsonType.label": "String"
}
},
{
"id": "0bba757d-b188-4434-8f10-ed760d266dc4",
"name": "gender_as_string",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "false",
"userinfo.token.claim": "true",
"user.attribute": "gender_as_string",
"id.token.claim": "false",
"lightweight.claim": "false",
"access.token.claim": "false",
"claim.name": "gender_as_string",
"jsonType.label": "String"
}
},
{
"id": "eb7435a1-ffa0-4d60-b14d-f26706b2872a",
"name": "birth_place",
Expand Down Expand Up @@ -1916,7 +1950,7 @@
"subComponents": {},
"config": {
"kc.user.profile.config": [
"{\"attributes\":[{\"name\":\"username\",\"displayName\":\"${username}\",\"validations\":{\"length\":{\"min\":3,\"max\":255},\"username-prohibited-characters\":{},\"up-username-not-idn-homograph\":{}},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"credentials\",\"multivalued\":false},{\"name\":\"email\",\"displayName\":\"${email}\",\"validations\":{\"email\":{},\"length\":{\"max\":255}},\"annotations\":{},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"credentials\",\"multivalued\":false},{\"name\":\"firstName\",\"displayName\":\"${firstName}\",\"validations\":{\"length\":{\"max\":255},\"person-name-prohibited-characters\":{}},\"annotations\":{},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"profile\",\"multivalued\":false},{\"name\":\"lastName\",\"displayName\":\"${lastName}\",\"validations\":{\"length\":{\"max\":255},\"person-name-prohibited-characters\":{}},\"annotations\":{},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"profile\",\"multivalued\":false},{\"name\":\"birth_given_name\",\"displayName\":\"First name given at birth\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"profile\",\"multivalued\":false},{\"name\":\"birth_family_name\",\"displayName\":\"Last name given at birth\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"profile\",\"multivalued\":false},{\"name\":\"gender\",\"displayName\":\"Gender\",\"validations\":{\"options\":{\"options\":[\"0\",\"1\",\"2\",\"9\"]}},\"annotations\":{\"inputOptionLabels\":{\"0\":\"Not known\",\"1\":\"Male\",\"2\":\"Female\",\"9\":\"Not applicable\"},\"inputType\":\"select-radiobuttons\"},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"profile\",\"multivalued\":false},{\"name\":\"birthdate\",\"displayName\":\"Birthdate\",\"validations\":{\"iso-date\":{}},\"annotations\":{\"inputType\":\"html5-date\"},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"profile\",\"multivalued\":false},{\"name\":\"age_over_18\",\"displayName\":\"Age over 18\",\"validations\":{\"options\":{\"options\":[\"true\",\"false\"]}},\"annotations\":{\"inputOptionLabels\":{\"true\":\"Yes\",\"false\":\"No\"},\"inputType\":\"select\"},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"profile\",\"multivalued\":false},{\"name\":\"picture\",\"displayName\":\"Picture\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"profile\",\"multivalued\":false},{\"name\":\"street\",\"displayName\":\"Street\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"address\",\"multivalued\":false},{\"name\":\"address_house_number\",\"displayName\":\"House Number\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"address\",\"multivalued\":false},{\"name\":\"locality\",\"displayName\":\"Locality\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"address\",\"multivalued\":false},{\"name\":\"region\",\"displayName\":\"Region\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"address\",\"multivalued\":false},{\"name\":\"postal_code\",\"displayName\":\"Postal Code\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"address\",\"multivalued\":false},{\"name\":\"country\",\"displayName\":\"Country\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"address\",\"multivalued\":false},{\"name\":\"formatted\",\"displayName\":\"Formatted\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"address\",\"multivalued\":false},{\"name\":\"birth_place\",\"displayName\":\"Place\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"birth_place\",\"multivalued\":false},{\"name\":\"birth_city\",\"displayName\":\"City\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"birth_place\",\"multivalued\":false},{\"name\":\"birth_state\",\"displayName\":\"State\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"birth_place\",\"multivalued\":false},{\"name\":\"birth_country\",\"displayName\":\"Country\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"birth_place\",\"multivalued\":false},{\"name\":\"nationality\",\"displayName\":\"Nationality\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"profile\",\"multivalued\":false}],\"groups\":[{\"name\":\"user-metadata\",\"displayHeader\":\"User metadata\",\"displayDescription\":\"Attributes, which refer to user metadata\"},{\"name\":\"address\",\"displayHeader\":\"Address\",\"displayDescription\":\"\",\"annotations\":{}},{\"name\":\"credentials\",\"displayHeader\":\"Credentials\",\"displayDescription\":\"\",\"annotations\":{}},{\"name\":\"profile\",\"displayHeader\":\"Profile\",\"displayDescription\":\"\",\"annotations\":{}},{\"name\":\"birth_place\",\"displayHeader\":\"Birth Place\",\"displayDescription\":\"\",\"annotations\":{}}]}"
"{\"attributes\":[{\"name\":\"username\",\"displayName\":\"${username}\",\"validations\":{\"length\":{\"min\":3,\"max\":255},\"username-prohibited-characters\":{},\"up-username-not-idn-homograph\":{}},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"credentials\",\"multivalued\":false},{\"name\":\"email\",\"displayName\":\"${email}\",\"validations\":{\"email\":{},\"length\":{\"max\":255}},\"annotations\":{},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"credentials\",\"multivalued\":false},{\"name\":\"firstName\",\"displayName\":\"${firstName}\",\"validations\":{\"length\":{\"max\":255},\"person-name-prohibited-characters\":{}},\"annotations\":{},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"profile\",\"multivalued\":false},{\"name\":\"lastName\",\"displayName\":\"${lastName}\",\"validations\":{\"length\":{\"max\":255},\"person-name-prohibited-characters\":{}},\"annotations\":{},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"profile\",\"multivalued\":false},{\"name\":\"birth_given_name\",\"displayName\":\"First name given at birth\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"profile\",\"multivalued\":false},{\"name\":\"birth_family_name\",\"displayName\":\"Last name given at birth\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"profile\",\"multivalued\":false},{\"name\":\"gender\",\"displayName\":\"Gender\",\"validations\":{\"options\":{\"options\":[\"0\",\"1\",\"2\",\"9\"]}},\"annotations\":{\"inputOptionLabels\":{\"0\":\"Not known\",\"1\":\"Male\",\"2\":\"Female\",\"9\":\"Not applicable\"},\"inputHelperTextAfter\":\"Select one of the above\",\"inputType\":\"select-radiobuttons\"},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"profile\",\"multivalued\":false},{\"name\":\"gender_as_string\",\"displayName\":\"Gender\",\"validations\":{},\"annotations\":{\"inputTypePlaceholder\":\"gender\",\"inputHelperTextAfter\":\"Or provide your own\"},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"profile\",\"multivalued\":false},{\"name\":\"birthdate\",\"displayName\":\"Birthdate\",\"validations\":{\"iso-date\":{}},\"annotations\":{\"inputType\":\"html5-date\"},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"profile\",\"multivalued\":false},{\"name\":\"age_over_18\",\"displayName\":\"Age over 18\",\"validations\":{\"options\":{\"options\":[\"true\",\"false\"]}},\"annotations\":{\"inputOptionLabels\":{\"true\":\"Yes\",\"false\":\"No\"},\"inputType\":\"select\"},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"profile\",\"multivalued\":false},{\"name\":\"picture\",\"displayName\":\"Picture\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"profile\",\"multivalued\":false},{\"name\":\"street\",\"displayName\":\"Street\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"address\",\"multivalued\":false},{\"name\":\"address_house_number\",\"displayName\":\"House Number\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"address\",\"multivalued\":false},{\"name\":\"locality\",\"displayName\":\"Locality\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"address\",\"multivalued\":false},{\"name\":\"region\",\"displayName\":\"Region\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"address\",\"multivalued\":false},{\"name\":\"postal_code\",\"displayName\":\"Postal Code\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"address\",\"multivalued\":false},{\"name\":\"country\",\"displayName\":\"Country\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"address\",\"multivalued\":false},{\"name\":\"formatted\",\"displayName\":\"Formatted\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"address\",\"multivalued\":false},{\"name\":\"birth_place\",\"displayName\":\"Place\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"birth_place\",\"multivalued\":false},{\"name\":\"birth_city\",\"displayName\":\"City\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"birth_place\",\"multivalued\":false},{\"name\":\"birth_state\",\"displayName\":\"State\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"birth_place\",\"multivalued\":false},{\"name\":\"birth_country\",\"displayName\":\"Country\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"birth_place\",\"multivalued\":false},{\"name\":\"nationality\",\"displayName\":\"Nationality\",\"validations\":{},\"annotations\":{},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"group\":\"profile\",\"multivalued\":false}],\"groups\":[{\"name\":\"user-metadata\",\"displayHeader\":\"User metadata\",\"displayDescription\":\"Attributes, which refer to user metadata\"},{\"name\":\"address\",\"displayHeader\":\"Address\",\"displayDescription\":\"\",\"annotations\":{}},{\"name\":\"credentials\",\"displayHeader\":\"Credentials\",\"displayDescription\":\"\",\"annotations\":{}},{\"name\":\"profile\",\"displayHeader\":\"Profile\",\"displayDescription\":\"\",\"annotations\":{}},{\"name\":\"birth_place\",\"displayHeader\":\"Birth Place\",\"displayDescription\":\"\",\"annotations\":{}}]}"
]
}
}
Expand Down
3 changes: 3 additions & 0 deletions docker-compose/keycloak/realms/pid-issuer-realm-users-0.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
"gender": [
"1"
],
"gender_as_string": [
"male"
],
"birthdate": [
"1955-04-12"
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ import org.slf4j.LoggerFactory
import java.time.Clock
import java.time.Instant
import java.time.ZonedDateTime
import eu.europa.ec.eudi.pidissuer.adapter.out.oauth.OidcGender as OidcGenderAttribute

private val log = LoggerFactory.getLogger(EncodePidInSdJwtVc::class.java)

Expand Down Expand Up @@ -157,7 +156,7 @@ private fun selectivelyDisclosed(
address.houseNumber?.let { sd("house_number", it) }
}
}
pid.gender?.let { sd(OidcGenderAttribute.name, it.toOidGender().value) }
pid.genderAsString?.let { sd(OidcGender.name, it) }
pid.nationality?.let {
val nationalities = buildJsonArray { add(it.value) }
sd(OidcAssuranceNationalities.name, nationalities)
Expand Down Expand Up @@ -218,15 +217,3 @@ private object Printer {
return str
}
}

/**
* Converts an [IsoGender] to an [OidcGender].
*/
private fun IsoGender.toOidGender(): OidcGender =
when (value) {
0u -> OidcGender("not known")
1u -> OidcGender.Male
2u -> OidcGender.Female
9u -> OidcGender("not applicable")
else -> OidcGender(value.toString())
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ class GetPidDataFromAuthServer(
address = user.address(),
birthDate = user.attributes["birthdate"]?.firstOrNull(),
gender = user.attributes["gender"]?.firstOrNull()?.toUInt(),
genderAsString = user.attributes["gender_as_string"]?.firstOrNull(),
placeOfBirth = user.birthPlace(),
ageOver18 = user.attributes["age_over_18"]?.firstOrNull()?.toBoolean(),
picture = null,
Expand Down Expand Up @@ -174,6 +175,7 @@ class GetPidDataFromAuthServer(
residentPostalCode = userInfo.address?.postalCode?.let { PostalCode(it) },
residentHouseNumber = userInfo.address?.houseNumber,
gender = userInfo.gender?.let { IsoGender(it) },
genderAsString = userInfo.genderAsString,
nationality = userInfo.nationality?.let { IsoCountry(it) },
)

Expand All @@ -194,6 +196,7 @@ private data class UserInfo(
@SerialName(OidcAddressClaim.NAME) val address: OidcAddressClaim? = null,
@SerialName("birthdate") val birthDate: String? = null,
@SerialName("gender") val gender: UInt? = null,
@SerialName("gender_as_string") val genderAsString: String? = null,
@SerialName(OidcAssurancePlaceOfBirth.NAME) val placeOfBirth: OidcAssurancePlaceOfBirth? = null,
@SerialName("age_over_18") val ageOver18: Boolean? = null,
val picture: String? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import java.time.Clock
import java.time.Instant
import java.time.ZonedDateTime
import java.util.*
import eu.europa.ec.eudi.pidissuer.adapter.out.oauth.OidcGender as OidcGenderAttribute

val PidSdJwtVcScope: Scope = Scope("eu.europa.ec.eudi.pid_vc_sd_jwt")

Expand Down Expand Up @@ -76,7 +75,7 @@ internal object Attributes {
OidcAssuranceBirthGivenName,
OidcAssurancePlaceOfBirth.attribute,
OidcAddressClaim.attribute,
OidcGenderAttribute,
OidcGender,
OidcAssuranceNationalities,
IssuingAuthorityAttribute,
DocumentNumberAttribute,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,24 +52,6 @@ typealias Address = String
@JvmInline
value class IsoGender(val value: UInt)

/**
* Gender, using a value as defined in OpenID Connect Core 1.0.
*/
@JvmInline
value class OidcGender private constructor(val value: String) {
companion object {
val Male: OidcGender = OidcGender("male")
val Female: OidcGender = OidcGender("female")

operator fun invoke(value: String): OidcGender =
when (value) {
"male" -> Male
"female" -> Female
else -> OidcGender(value)
}
}
}

typealias Nationality = IsoCountry

/**
Expand Down Expand Up @@ -122,6 +104,7 @@ data class Pid(
val residentPostalCode: PostalCode? = null,
val residentHouseNumber: String? = null,
val gender: IsoGender? = null,
val genderAsString: String? = null,
val nationality: Nationality? = null,
) {
init {
Expand Down

0 comments on commit 3c6c255

Please sign in to comment.