From de557ed071a873e643bcd5241eb9dacf7e2950a4 Mon Sep 17 00:00:00 2001 From: Frederic Kneier Date: Wed, 22 May 2024 09:35:40 +0200 Subject: [PATCH] Allows to set public url --- .../de/solugo/oidc/ConfigurationProvider.kt | 6 +++--- .../kotlin/de/solugo/oidc/ServerProperties.kt | 10 +++++++++- .../controller/ConfigurationController.kt | 19 +++++++++++++------ .../oidc/controller/KeySetController.kt | 16 +++++++++++----- .../solugo/oidc/controller/TokenController.kt | 14 ++++++++++---- src/main/kotlin/de/solugo/oidc/util/Util.kt | 5 +++++ src/test/kotlin/IntegrationTest.kt | 4 +++- .../oidc/controller/TokenControllerTest.kt | 13 ++++++++++++- 8 files changed, 66 insertions(+), 21 deletions(-) diff --git a/src/main/kotlin/de/solugo/oidc/ConfigurationProvider.kt b/src/main/kotlin/de/solugo/oidc/ConfigurationProvider.kt index 7703b5f..66bd14e 100644 --- a/src/main/kotlin/de/solugo/oidc/ConfigurationProvider.kt +++ b/src/main/kotlin/de/solugo/oidc/ConfigurationProvider.kt @@ -1,7 +1,7 @@ package de.solugo.oidc -import org.springframework.web.util.UriComponentsBuilder +import org.springframework.web.server.ServerWebExchange interface ConfigurationProvider { - fun provide(builder: UriComponentsBuilder): Map -} \ No newline at end of file + fun provide(exchange: ServerWebExchange): Map +} diff --git a/src/main/kotlin/de/solugo/oidc/ServerProperties.kt b/src/main/kotlin/de/solugo/oidc/ServerProperties.kt index cfa87b0..8a0ac17 100644 --- a/src/main/kotlin/de/solugo/oidc/ServerProperties.kt +++ b/src/main/kotlin/de/solugo/oidc/ServerProperties.kt @@ -1,8 +1,16 @@ package de.solugo.oidc +import de.solugo.oidc.util.uri import org.springframework.boot.context.properties.ConfigurationProperties +import org.springframework.web.server.ServerWebExchange +import org.springframework.web.util.UriComponentsBuilder @ConfigurationProperties("server") data class ServerProperties( + val publicUrl: String? = null, val claims: Map = emptyMap(), -) \ No newline at end of file +) { + fun ServerWebExchange.issuerUri( + block: UriComponentsBuilder.() -> Unit, + ) = uri(publicUrl ?: request.uri.toString(), block) +} diff --git a/src/main/kotlin/de/solugo/oidc/controller/ConfigurationController.kt b/src/main/kotlin/de/solugo/oidc/controller/ConfigurationController.kt index dbbffbb..0b403ec 100644 --- a/src/main/kotlin/de/solugo/oidc/controller/ConfigurationController.kt +++ b/src/main/kotlin/de/solugo/oidc/controller/ConfigurationController.kt @@ -1,21 +1,28 @@ package de.solugo.oidc.controller import de.solugo.oidc.ConfigurationProvider +import de.solugo.oidc.ServerProperties import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RestController -import org.springframework.web.util.UriComponentsBuilder +import org.springframework.web.server.ServerWebExchange @RestController class ConfigurationController( private val configurationProviders: List, + private val properties: ServerProperties, ) { @GetMapping(".well-known/openid-configuration") - fun configuration(builder: UriComponentsBuilder) = buildMap { - put("issuer", builder.replacePath("/").toUriString()) - configurationProviders.forEach { - putAll(it.provide(builder)) + fun configuration(exchange: ServerWebExchange) = with(properties) { + buildMap { + put("issuer", exchange.issuerUri { + replacePath("/") + }) + configurationProviders.forEach { + putAll(it.provide(exchange)) + } } } -} \ No newline at end of file + +} diff --git a/src/main/kotlin/de/solugo/oidc/controller/KeySetController.kt b/src/main/kotlin/de/solugo/oidc/controller/KeySetController.kt index 69562b1..ad882d4 100644 --- a/src/main/kotlin/de/solugo/oidc/controller/KeySetController.kt +++ b/src/main/kotlin/de/solugo/oidc/controller/KeySetController.kt @@ -1,22 +1,28 @@ package de.solugo.oidc.controller import de.solugo.oidc.ConfigurationProvider +import de.solugo.oidc.ServerProperties import de.solugo.oidc.service.KeySetService import org.jose4j.jwk.JsonWebKey import org.springframework.boot.autoconfigure.condition.ConditionalOnBean import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RestController -import org.springframework.web.util.UriComponentsBuilder +import org.springframework.web.server.ServerWebExchange @RestController @ConditionalOnBean(KeySetService::class) class KeySetController( private val keySetService: KeySetService, + private val properties: ServerProperties, ) : ConfigurationProvider { - override fun provide(builder: UriComponentsBuilder) = mapOf( - "jwks_uri" to builder.replacePath(".well-known/jwks.json").toUriString(), - ) + override fun provide(exchange: ServerWebExchange) = with(properties) { + mapOf( + "jwks_uri" to exchange.issuerUri { + replacePath("/.well-known/jwks.json") + }, + ) + } @GetMapping(".well-known/jwks.json") fun getJwks() = mapOf( @@ -25,4 +31,4 @@ class KeySetController( } ) -} \ No newline at end of file +} diff --git a/src/main/kotlin/de/solugo/oidc/controller/TokenController.kt b/src/main/kotlin/de/solugo/oidc/controller/TokenController.kt index f82351d..b0ebcdd 100644 --- a/src/main/kotlin/de/solugo/oidc/controller/TokenController.kt +++ b/src/main/kotlin/de/solugo/oidc/controller/TokenController.kt @@ -2,6 +2,7 @@ package de.solugo.oidc.controller import de.solugo.oidc.ConfigurationProvider +import de.solugo.oidc.ServerProperties import de.solugo.oidc.service.TokenService import de.solugo.oidc.token.* import de.solugo.oidc.util.plus @@ -23,13 +24,18 @@ class TokenController( private val grants: List, private val tokenService: TokenService, private val tokenProcessors: List, + private val properties: ServerProperties, ) : ConfigurationProvider { private val logger = LoggerFactory.getLogger(javaClass) - override fun provide(builder: UriComponentsBuilder) = mapOf( - "token_endpoint" to builder.replacePath("/token").toUriString(), - ) + override fun provide(exchange: ServerWebExchange) = with(properties) { + mapOf( + "token_endpoint" to exchange.issuerUri { + replacePath("/token") + } + ) + } @PostMapping("/token", consumes = [MediaType.APPLICATION_FORM_URLENCODED_VALUE]) suspend fun createToken( @@ -126,4 +132,4 @@ class TokenController( } } -} \ No newline at end of file +} diff --git a/src/main/kotlin/de/solugo/oidc/util/Util.kt b/src/main/kotlin/de/solugo/oidc/util/Util.kt index f7d3234..0bb5dd9 100644 --- a/src/main/kotlin/de/solugo/oidc/util/Util.kt +++ b/src/main/kotlin/de/solugo/oidc/util/Util.kt @@ -1,5 +1,6 @@ package de.solugo.oidc.util +import org.springframework.web.util.UriComponentsBuilder import java.util.* fun uuid(value: String? = null) = when { @@ -7,3 +8,7 @@ fun uuid(value: String? = null) = when { else -> UUID.randomUUID().toString() } +fun uri(uri: String, block: UriComponentsBuilder.() -> Unit) = UriComponentsBuilder.fromUriString(uri).run { + block() + toUriString() +} diff --git a/src/test/kotlin/IntegrationTest.kt b/src/test/kotlin/IntegrationTest.kt index c148627..52a0f8c 100644 --- a/src/test/kotlin/IntegrationTest.kt +++ b/src/test/kotlin/IntegrationTest.kt @@ -32,8 +32,10 @@ abstract class IntegrationTest { companion object { @JvmStatic @DynamicPropertySource + @Suppress("unused") fun configure(registry: DynamicPropertyRegistry) { + registry.add("server.publicUrl") { "https://my_issuer" } } } -} \ No newline at end of file +} diff --git a/src/test/kotlin/de/solugo/oidc/controller/TokenControllerTest.kt b/src/test/kotlin/de/solugo/oidc/controller/TokenControllerTest.kt index 6a945c9..db636fa 100644 --- a/src/test/kotlin/de/solugo/oidc/controller/TokenControllerTest.kt +++ b/src/test/kotlin/de/solugo/oidc/controller/TokenControllerTest.kt @@ -13,6 +13,17 @@ import org.junit.jupiter.api.Test class TokenControllerTest : IntegrationTest() { + @Test + fun `Get openid configuration`() = runTest { + rest.get(".well-known/openid-configuration").apply { + status shouldBe HttpStatusCode.OK + body().apply { + at("/issuer").textValue() shouldBe "https://my_issuer/" + } + } + } + + @Test fun `Create token using password grant`() = runTest { val parameters = parametersOf( @@ -93,4 +104,4 @@ class TokenControllerTest : IntegrationTest() { } } } -} \ No newline at end of file +}