Skip to content

Commit

Permalink
Regarding the API configuration, KeycloakJwtAuthenticationConverter l…
Browse files Browse the repository at this point in the history
…eads to HTTP 500 error

When application identity runs a simulation, if principalJwtClaim is set to a user specific claim name, it crashes.
We add the same fallback mechanism as SecurityUtils.getCurrentAuthenticatedUserName (used during Cosmo resource creation)
  • Loading branch information
jreynard-code committed Feb 4, 2025
1 parent f8f892e commit e63897e
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ class KeycloakJwtAuthenticationConverter(private val csmPlatformProperties: CsmP
KeycloakJwtGrantedAuthoritiesConverter(csmPlatformProperties).convert(jwt)
val principalClaimValue: String =
jwt.getClaimAsString(csmPlatformProperties.authorization.principalJwtClaim)
?: jwt.getClaimAsString(csmPlatformProperties.authorization.applicationIdJwtClaim)
?: throw IllegalStateException("User Authentication not found in Security Context")
return JwtAuthenticationToken(jwt, authorities, principalClaimValue)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@ class KeycloakJwtAuthenticationConverterTests {
@Test
fun `convertRolesToAuthorities with correct values`() {
val principalClaimValue = "my.principal@me.com"
val principalClaimName = "email"
val claims =
mutableMapOf(
"claim1" to "10",
"claimRoles" to listOf("role1", "role2", "role3"),
"claimName" to "myClaimName",
"sub" to principalClaimValue)
"sub" to "123-456-798",
principalClaimName to principalClaimValue)
val expectedSimpleGrantedAuthorities =
listOf(
SimpleGrantedAuthority("role1"),
Expand All @@ -49,53 +51,139 @@ class KeycloakJwtAuthenticationConverterTests {

every { jwt.claims } returns claims
every { csmPlatformProperties.authorization.rolesJwtClaim } returns "claimRoles"
every { csmPlatformProperties.authorization.principalJwtClaim } returns principalClaimValue
every { jwt.getClaimAsString(principalClaimValue) } returns principalClaimValue
every { csmPlatformProperties.authorization.principalJwtClaim } returns principalClaimName
every { jwt.getClaimAsString(principalClaimName) } returns principalClaimValue

val jwtConverted = keycloakJwtAuthenticationConverter.convert(jwt)

assertEquals(
JwtAuthenticationToken(jwt, expectedSimpleGrantedAuthorities, principalClaimValue),
JwtAuthenticationToken(jwt, expectedSimpleGrantedAuthorities, principalClaimName),
jwtConverted)
}

@Test
fun `convertRolesToAuthorities with correct values when no principalJwtClaim set`() {
val principalClaimName = "unexisting-principal-claim"
val applicationIdClaimValue = "123-456-798"
val applicationIdClaimName = "sub"
val claims =
mutableMapOf(
"claim1" to "10",
"claimRoles" to listOf("role1", "role2", "role3"),
"claimName" to "myClaimName",
applicationIdClaimName to applicationIdClaimValue)
val expectedSimpleGrantedAuthorities =
listOf(
SimpleGrantedAuthority("role1"),
SimpleGrantedAuthority("role2"),
SimpleGrantedAuthority("role3"))

every { jwt.claims } returns claims
every { csmPlatformProperties.authorization.rolesJwtClaim } returns "claimRoles"
every { csmPlatformProperties.authorization.principalJwtClaim } returns principalClaimName
every { csmPlatformProperties.authorization.applicationIdJwtClaim } returns applicationIdClaimName
every { jwt.getClaimAsString(principalClaimName) } returns null
every { jwt.getClaimAsString(applicationIdClaimName) } returns applicationIdClaimValue

val jwtConverted = keycloakJwtAuthenticationConverter.convert(jwt)

assertEquals(
JwtAuthenticationToken(jwt, expectedSimpleGrantedAuthorities, applicationIdClaimValue),
jwtConverted)
}

@Test
fun `convertRolesToAuthorities with non-existing role claim values`() {
val principalClaimValue = "my.principal@me.com"
val principalClaimName = "email"
val claims =
mutableMapOf(
"claim1" to "10",
"claimRoles" to listOf("role1", "role2", "role3"),
"claimName" to "myClaimName",
"sub" to principalClaimValue)
"sub" to "123-456-798",
principalClaimName to principalClaimValue)

every { jwt.claims } returns claims
every { csmPlatformProperties.authorization.rolesJwtClaim } returns "unexisting-role-claim"
every { csmPlatformProperties.authorization.principalJwtClaim } returns principalClaimValue
every { jwt.getClaimAsString(principalClaimValue) } returns principalClaimValue
every { csmPlatformProperties.authorization.principalJwtClaim } returns principalClaimName
every { jwt.getClaimAsString(principalClaimName) } returns principalClaimValue

val jwtConverted = keycloakJwtAuthenticationConverter.convert(jwt)

assertEquals(JwtAuthenticationToken(jwt, emptyList(), principalClaimValue), jwtConverted)
assertEquals(JwtAuthenticationToken(jwt, emptyList(), principalClaimName), jwtConverted)
}

@Test
fun `convertRolesToAuthorities with non-existing role claim values when no principalJwtClaim set`() {
val principalClaimName = "unexisting-principal-claim"
val applicationIdClaimValue = "123-456-798"
val applicationIdClaimName = "sub"
val claims =
mutableMapOf(
"claim1" to "10",
"claimRoles" to listOf("role1", "role2", "role3"),
"claimName" to "myClaimName",
"sub" to "123-456-798")

every { jwt.claims } returns claims
every { csmPlatformProperties.authorization.rolesJwtClaim } returns "unexisting-role-claim"
every { csmPlatformProperties.authorization.principalJwtClaim } returns principalClaimName
every { csmPlatformProperties.authorization.applicationIdJwtClaim } returns applicationIdClaimName
every { jwt.getClaimAsString(principalClaimName) } returns null
every { jwt.getClaimAsString(applicationIdClaimName) } returns applicationIdClaimValue

val jwtConverted = keycloakJwtAuthenticationConverter.convert(jwt)

assertEquals(JwtAuthenticationToken(jwt, emptyList(), applicationIdClaimName), jwtConverted)
}

@Test
fun `convertRolesToAuthorities with existing role claim but no roles defined`() {
val principalClaimValue = "my.principal@me.com"
val principalClaimValue = "my.principal@me.com"
val principalClaimName = "email"
val claims =
mutableMapOf(
"claim1" to "10",
"claimRoles" to emptyList<String>(),
"claimName" to "myClaimName",
"sub" to principalClaimValue)
"sub" to "123-456-798",
principalClaimName to principalClaimValue)

every { jwt.claims } returns claims
every { csmPlatformProperties.authorization.rolesJwtClaim } returns "claimRoles"
every { csmPlatformProperties.authorization.principalJwtClaim } returns principalClaimValue
every { jwt.getClaimAsString(principalClaimValue) } returns principalClaimValue
every { csmPlatformProperties.authorization.principalJwtClaim } returns principalClaimName
every { jwt.getClaimAsString(principalClaimName) } returns principalClaimValue

val jwtConverted = keycloakJwtAuthenticationConverter.convert(jwt)

assertEquals(JwtAuthenticationToken(jwt, emptyList(), principalClaimValue), jwtConverted)
assertEquals(JwtAuthenticationToken(jwt, emptyList(), principalClaimName), jwtConverted)
}

@Test
fun `convertRolesToAuthorities with existing role claim but no roles defined when no principalJwtClaim set`() {
val principalClaimName = "unexisting-principal-claim"
val applicationIdClaimValue = "123-456-798"
val applicationIdClaimName = "sub"
val claims =
mutableMapOf(
"claim1" to "10",
"claimRoles" to emptyList<String>(),
"claimName" to "myClaimName",
"sub" to "123-456-798")

every { jwt.claims } returns claims
every { csmPlatformProperties.authorization.rolesJwtClaim } returns "claimRoles"
every { csmPlatformProperties.authorization.principalJwtClaim } returns principalClaimName
every { csmPlatformProperties.authorization.applicationIdJwtClaim } returns applicationIdClaimName
every { jwt.getClaimAsString(principalClaimName) } returns null
every { jwt.getClaimAsString(applicationIdClaimName) } returns applicationIdClaimValue

val jwtConverted = keycloakJwtAuthenticationConverter.convert(jwt)

assertEquals(JwtAuthenticationToken(jwt, emptyList(), applicationIdClaimName), jwtConverted)
}



}

0 comments on commit e63897e

Please sign in to comment.