From e355ac0ef0aca769e40dd3a02b6603d500f4e31d Mon Sep 17 00:00:00 2001 From: Richard Borge Date: Thu, 8 Feb 2024 10:12:26 +0100 Subject: [PATCH] (MAJOR) Fjerner gamle og ubrukte ting Co-authored-by: Robin Tordly Co-authored-by: Sturle Helland Co-authored-by: Vetle Hollund --- ktor-auth-azuread/build.gradle.kts | 17 ---- .../aap/ktor/client/AzureAdTokenProvider.kt | 64 ------------- .../no/nav/aap/ktor/client/AzureConfig.kt | 9 -- .../main/no/nav/aap/ktor/client/Token.kt | 57 ----------- ktor-auth-maskinporten/README.md | 3 - ktor-auth-maskinporten/build.gradle.kts | 19 ---- .../HttpClientMaskinportenTokenProvider.kt | 52 ---------- .../maskinporten/client/JwtGrantFactory.kt | 28 ------ .../maskinporten/client/MaskinportenConfig.kt | 17 ---- .../ktor/client/maskinporten/client/Token.kt | 51 ---------- .../ktor/MaskinportenAuthProvider.kt | 24 ----- .../client/maskinporten/MaskinportenTest.kt | 48 ---------- ktor-auth-tokenx/build.gradle.kts | 15 --- .../main/no/nav/aap/ktor/client/Token.kt | 57 ----------- .../aap/ktor/client/TokenXProviderConfig.kt | 11 --- .../aap/ktor/client/TokenXTokenProvider.kt | 95 ------------------- ktor-utils/build.gradle.kts | 7 -- .../main/no/nav/aap/ktor/config/Config.kt | 19 ---- ktor-utils/test/application.yml | 1 - .../test/no/nav/aap/ktor/config/ConfigTest.kt | 24 ----- settings.gradle.kts | 4 - 21 files changed, 622 deletions(-) delete mode 100644 ktor-auth-azuread/build.gradle.kts delete mode 100644 ktor-auth-azuread/main/no/nav/aap/ktor/client/AzureAdTokenProvider.kt delete mode 100644 ktor-auth-azuread/main/no/nav/aap/ktor/client/AzureConfig.kt delete mode 100644 ktor-auth-azuread/main/no/nav/aap/ktor/client/Token.kt delete mode 100644 ktor-auth-maskinporten/README.md delete mode 100644 ktor-auth-maskinporten/build.gradle.kts delete mode 100644 ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/client/HttpClientMaskinportenTokenProvider.kt delete mode 100644 ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/client/JwtGrantFactory.kt delete mode 100644 ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/client/MaskinportenConfig.kt delete mode 100644 ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/client/Token.kt delete mode 100644 ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/ktor/MaskinportenAuthProvider.kt delete mode 100644 ktor-auth-maskinporten/test/no/nav/aap/ktor/client/maskinporten/MaskinportenTest.kt delete mode 100644 ktor-auth-tokenx/build.gradle.kts delete mode 100644 ktor-auth-tokenx/main/no/nav/aap/ktor/client/Token.kt delete mode 100644 ktor-auth-tokenx/main/no/nav/aap/ktor/client/TokenXProviderConfig.kt delete mode 100644 ktor-auth-tokenx/main/no/nav/aap/ktor/client/TokenXTokenProvider.kt delete mode 100644 ktor-utils/build.gradle.kts delete mode 100644 ktor-utils/main/no/nav/aap/ktor/config/Config.kt delete mode 100644 ktor-utils/test/application.yml delete mode 100644 ktor-utils/test/no/nav/aap/ktor/config/ConfigTest.kt diff --git a/ktor-auth-azuread/build.gradle.kts b/ktor-auth-azuread/build.gradle.kts deleted file mode 100644 index 9cd59c63..00000000 --- a/ktor-auth-azuread/build.gradle.kts +++ /dev/null @@ -1,17 +0,0 @@ -val ktorVersion = "2.3.8" - -dependencies { -// implementation(project(":cache")) - - implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion") - implementation("io.ktor:ktor-client-cio:$ktorVersion") - implementation("io.ktor:ktor-client-auth:$ktorVersion") - - implementation("io.ktor:ktor-serialization-jackson:$ktorVersion") - - implementation("com.fasterxml.jackson.core:jackson-databind:2.16.1") - implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.16.1") - - runtimeOnly("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.7.3") - runtimeOnly("org.slf4j:slf4j-api:2.0.12") -} diff --git a/ktor-auth-azuread/main/no/nav/aap/ktor/client/AzureAdTokenProvider.kt b/ktor-auth-azuread/main/no/nav/aap/ktor/client/AzureAdTokenProvider.kt deleted file mode 100644 index e57189e9..00000000 --- a/ktor-auth-azuread/main/no/nav/aap/ktor/client/AzureAdTokenProvider.kt +++ /dev/null @@ -1,64 +0,0 @@ -package no.nav.aap.ktor.client - -import com.fasterxml.jackson.databind.DeserializationFeature -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule -import io.ktor.client.* -import io.ktor.client.call.* -import io.ktor.client.engine.cio.* -import io.ktor.client.plugins.contentnegotiation.* -import io.ktor.client.request.* -import io.ktor.client.statement.* -import io.ktor.http.* -import io.ktor.serialization.jackson.* -import org.slf4j.LoggerFactory - -private val secureLog = LoggerFactory.getLogger("secureLog") - -class AzureAdTokenProvider( - private val config: AzureConfig, - private val scope: String, - private val client: HttpClient = defaultHttpClient, -) { - suspend fun getUsernamePasswordToken(username: String, password: String) = getAccessToken(username) { - "client_id=${config.clientId}&client_secret=${config.clientSecret}&scope=$scope&username=$username&password=$password&grant_type=password" - } - - suspend fun getClientCredentialToken() = getAccessToken(scope) { - "client_id=${config.clientId}&client_secret=${config.clientSecret}&scope=$scope&grant_type=client_credentials" - } - - suspend fun getOnBehalfOfToken(accessToken: String) = getAccessToken(scope) { - "client_id=${config.clientId}&client_secret=${config.clientSecret}&assertion=$accessToken&scope=$scope&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&requested_token_use=on_behalf_of" - } - - private val cache = TokenCache() - - private suspend fun getAccessToken(cacheKey: String, body: () -> String): String { - cache.logg(secureLog) - val token = cache.get(cacheKey) - ?: client.post(config.tokenEndpoint) { - accept(ContentType.Application.Json) - contentType(ContentType.Application.FormUrlEncoded) - setBody(body()) - }.also { - if (!it.status.isSuccess()) { - secureLog.warn("Feilet token-kall {}: {}", it.status.value, it.bodyAsText()) - } - }.body().also { - cache.add(cacheKey, it) - } - - return token.access_token - } - - private companion object { - private val defaultHttpClient = HttpClient(CIO) { - install(ContentNegotiation) { - jackson { - registerModule(JavaTimeModule()) - disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) - } - } - } - } -} diff --git a/ktor-auth-azuread/main/no/nav/aap/ktor/client/AzureConfig.kt b/ktor-auth-azuread/main/no/nav/aap/ktor/client/AzureConfig.kt deleted file mode 100644 index 4554c1d3..00000000 --- a/ktor-auth-azuread/main/no/nav/aap/ktor/client/AzureConfig.kt +++ /dev/null @@ -1,9 +0,0 @@ -package no.nav.aap.ktor.client - -import java.net.URL - -data class AzureConfig( - val tokenEndpoint: URL, - val clientId: String, - val clientSecret: String -) diff --git a/ktor-auth-azuread/main/no/nav/aap/ktor/client/Token.kt b/ktor-auth-azuread/main/no/nav/aap/ktor/client/Token.kt deleted file mode 100644 index e2f825a4..00000000 --- a/ktor-auth-azuread/main/no/nav/aap/ktor/client/Token.kt +++ /dev/null @@ -1,57 +0,0 @@ -package no.nav.aap.ktor.client - -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import org.slf4j.Logger -import java.time.Instant - -internal data class Token(val expires_in: Long, val access_token: String) { - private val expiry: Instant = Instant.now().plusSeconds(expires_in - LEEWAY_SECONDS) - - internal fun expired() = Instant.now().isAfter(expiry) - - private companion object { - const val LEEWAY_SECONDS = 60 - } - - override fun toString(): String { - return "($expires_in, $access_token)" - } -} - -internal class TokenCache { - private val tokens: HashMap = hashMapOf() - private val mutex = Mutex() - - internal fun logg(logger: Logger) { - tokens.forEach { (key, value) -> - logger.info("Key: $key, Value: $value") - } - } - - internal suspend fun add(key: String, token: Token) { - mutex.withLock { - tokens[key] = token - } - } - - internal suspend fun get(key: String): Token? { - mutex.withLock { - tokens[key] - }?.let { - if (it.expired()) { - rm(key) - } - } - - return mutex.withLock { - tokens[key] - } - } - - private suspend fun rm(key: String) { - mutex.withLock { - tokens.remove(key) - } - } -} diff --git a/ktor-auth-maskinporten/README.md b/ktor-auth-maskinporten/README.md deleted file mode 100644 index 0e6a686d..00000000 --- a/ktor-auth-maskinporten/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# ktor-auth-maskinporten - -If you need to generate a maskinporten token for test purposes in dev. diff --git a/ktor-auth-maskinporten/build.gradle.kts b/ktor-auth-maskinporten/build.gradle.kts deleted file mode 100644 index aee18714..00000000 --- a/ktor-auth-maskinporten/build.gradle.kts +++ /dev/null @@ -1,19 +0,0 @@ -val ktorVersion = "2.3.8" - -dependencies { - implementation("io.ktor:ktor-client-auth:$ktorVersion") - implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion") - implementation("io.ktor:ktor-client-core:$ktorVersion") - implementation("io.ktor:ktor-client-cio:$ktorVersion") - - implementation("io.ktor:ktor-serialization-jackson:$ktorVersion") - - implementation("com.nimbusds:nimbus-jose-jwt:9.37.3") - implementation("com.fasterxml.jackson.core:jackson-databind:2.16.1") - implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.16.1") - - testImplementation("io.ktor:ktor-server-test-host:$ktorVersion") - testImplementation("io.ktor:ktor-server-content-negotiation:$ktorVersion") - - testImplementation(kotlin("test")) -} \ No newline at end of file diff --git a/ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/client/HttpClientMaskinportenTokenProvider.kt b/ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/client/HttpClientMaskinportenTokenProvider.kt deleted file mode 100644 index dfd9fd1f..00000000 --- a/ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/client/HttpClientMaskinportenTokenProvider.kt +++ /dev/null @@ -1,52 +0,0 @@ -package no.nav.aap.ktor.client.maskinporten.client - -import com.fasterxml.jackson.databind.DeserializationFeature -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule -import com.nimbusds.jwt.SignedJWT -import io.ktor.client.* -import io.ktor.client.call.* -import io.ktor.client.engine.cio.* -import io.ktor.client.plugins.contentnegotiation.* -import io.ktor.client.request.* -import io.ktor.http.* -import io.ktor.http.ContentType.Application.FormUrlEncoded -import io.ktor.serialization.jackson.* - -const val GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer" -const val LEEWAY_SECONDS: Long = 20 - -interface Oauth2JwtProvider { - suspend fun getToken(): String -} - -class HttpClientMaskinportenTokenProvider( - private val config: MaskinportenConfig, - private val client: HttpClient = defaultHttpClient -) : Oauth2JwtProvider { - private val grants: JwtGrantFactory = JwtGrantFactory(config) - private val cache = TokenCache() - - override suspend fun getToken(): String { - val token = cache.get(config.scope)?.takeUnless(Token::hasExpired) ?: fetchToken() - return token.access_token.let(SignedJWT::parse).parsedString - } - - private suspend fun fetchToken(): Token = - client.post(config.tokenEndpointUrl) { - contentType(FormUrlEncoded) - setBody("grant_type=$GRANT_TYPE&assertion=${grants.jwt}") - }.body().also { token -> - cache.add(config.scope, token) - } - - private companion object { - private val defaultHttpClient = HttpClient(CIO) { - install(ContentNegotiation) { - jackson { - registerModule(JavaTimeModule()) - disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) - } - } - } - } -} diff --git a/ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/client/JwtGrantFactory.kt b/ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/client/JwtGrantFactory.kt deleted file mode 100644 index 7832c864..00000000 --- a/ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/client/JwtGrantFactory.kt +++ /dev/null @@ -1,28 +0,0 @@ -package no.nav.aap.ktor.client.maskinporten.client - -import com.nimbusds.jose.JWSAlgorithm -import com.nimbusds.jose.JWSHeader -import com.nimbusds.jose.crypto.RSASSASigner -import com.nimbusds.jwt.JWTClaimsSet -import com.nimbusds.jwt.SignedJWT -import java.time.Instant -import java.util.* - -internal class JwtGrantFactory(private val config: MaskinportenConfig) { - internal val jwt: String get() = signedJwt.serialize() - - private val signedJwt get() = SignedJWT(jwsHeader, jwtClaimSet).apply { sign(RSASSASigner(config.privateKey)) } - private val jwsHeader get() = JWSHeader.Builder(JWSAlgorithm.RS256).keyID(config.privateKey.keyID).build() - - private val jwtClaimSet: JWTClaimsSet - get() = JWTClaimsSet.Builder().apply { - audience(config.issuer) // maskinporten is aud - issuer(config.clientId) // this app is issuer - issueTime(Date()) - expirationTime(Instant.now() + config.expireAfterSec) - claim("scope", config.scope) - claim("resource", config.resource) - }.build() -} - -private infix operator fun Instant.plus(seconds: Long): Date = Date.from(plusSeconds(seconds)) diff --git a/ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/client/MaskinportenConfig.kt b/ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/client/MaskinportenConfig.kt deleted file mode 100644 index 77b1a6d5..00000000 --- a/ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/client/MaskinportenConfig.kt +++ /dev/null @@ -1,17 +0,0 @@ -package no.nav.aap.ktor.client.maskinporten.client - -import com.nimbusds.jose.jwk.RSAKey - -data class MaskinportenConfig( - val tokenEndpointUrl: String, - val clientId: String, - val privateKey: RSAKey, - val scope: String, - val resource: String, - val issuer: String, - val expireAfterSec: Long = 120 -) { - init { - require(expireAfterSec <= 120) { "Maskinporten allows a maximum of 120 seconds expiry" } - } -} diff --git a/ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/client/Token.kt b/ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/client/Token.kt deleted file mode 100644 index 3fbd2186..00000000 --- a/ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/client/Token.kt +++ /dev/null @@ -1,51 +0,0 @@ -package no.nav.aap.ktor.client.maskinporten.client - -import com.nimbusds.jwt.SignedJWT -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import org.slf4j.Logger -import java.time.Instant - -internal data class Token(val access_token: String) { - private val signedJwt = SignedJWT.parse(access_token) - private val expiry = signedJwt.jwtClaimsSet.expirationTime.toInstant().minusSeconds(LEEWAY_SECONDS) - - fun hasExpired() = expiry < Instant.now() -} - -internal class TokenCache { - private val tokens: HashMap = hashMapOf() - private val mutex = Mutex() - - internal fun logg(logger: Logger) { - tokens.forEach { (key, value) -> - logger.info("Key: $key, Value: $value") - } - } - - internal suspend fun add(key: String, token: Token) { - mutex.withLock { - tokens[key] = token - } - } - - internal suspend fun get(key: String): Token? { - mutex.withLock { - tokens[key] - }?.let { - if (it.hasExpired()) { - rm(key) - } - } - - return mutex.withLock { - tokens[key] - } - } - - private suspend fun rm(key: String) { - mutex.withLock { - tokens.remove(key) - } - } -} \ No newline at end of file diff --git a/ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/ktor/MaskinportenAuthProvider.kt b/ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/ktor/MaskinportenAuthProvider.kt deleted file mode 100644 index bf634e5f..00000000 --- a/ktor-auth-maskinporten/main/no/nav/aap/ktor/client/maskinporten/ktor/MaskinportenAuthProvider.kt +++ /dev/null @@ -1,24 +0,0 @@ -package no.nav.aap.ktor.client.maskinporten.ktor - -import io.ktor.client.plugins.auth.* -import io.ktor.client.request.* -import io.ktor.http.* -import io.ktor.http.auth.* -import no.nav.aap.ktor.client.maskinporten.client.HttpClientMaskinportenTokenProvider -import no.nav.aap.ktor.client.maskinporten.client.MaskinportenConfig - -class MaskinportenAuthProvider( - config: MaskinportenConfig, -) : AuthProvider { - private val tokenClient = HttpClientMaskinportenTokenProvider(config) - - @Suppress("OVERRIDE_DEPRECATION") - override val sendWithoutRequest: Boolean = error("Please use sendWithoutRequest function instead") - - override fun sendWithoutRequest(request: HttpRequestBuilder) = true - override fun isApplicable(auth: HttpAuthHeader): Boolean = true - - override suspend fun addRequestHeaders(request: HttpRequestBuilder, authHeader: HttpAuthHeader?) { - request.header(HttpHeaders.Authorization, "Bearer ${tokenClient.getToken()}") - } -} diff --git a/ktor-auth-maskinporten/test/no/nav/aap/ktor/client/maskinporten/MaskinportenTest.kt b/ktor-auth-maskinporten/test/no/nav/aap/ktor/client/maskinporten/MaskinportenTest.kt deleted file mode 100644 index 22b34745..00000000 --- a/ktor-auth-maskinporten/test/no/nav/aap/ktor/client/maskinporten/MaskinportenTest.kt +++ /dev/null @@ -1,48 +0,0 @@ -package no.nav.aap.ktor.client.maskinporten - -//class MaskinportenTest { - -// @Test -// @Ignore -// fun `maskinporten auth provider will add maskinporten token to requests`() { -// val config = MaskinportenConfig( -// tokenEndpointUrl = "MASKINPORTEN_TOKEN_ENDPOINT", -// clientId = "MASKINPORTEN_CLIENT_ID", -// privateKey = RSAKey.parse("MASKINPORTEN_CLIENT_JWK"), -// scope = "MASKINPORTEN_SCOPES", -// resource = "https://aap-api.dev.intern.nav.no", // hvordan appen identifiseres av issuer, f.eks ingress eller clientId -// issuer = "MASKINPORTEN_ISSUER", -// expireAfterSec = 120, -// ) -// -// testApplication { -// application { -// val eksternTjeneste = HttpClient(CIO) { -// install(Auth) { -// val provider = MaskinportenAuthProvider(config) -// providers.add(provider) -// } -// } -// } -// } -// -// } - -//} - -//internal fun Application.maskinportenMock(config: MaskinportenConfig) { - /** - maskinporten: - enabled: true - scopes: - consumes: - - name: "nav:aap:vedtak" - - name: "nav:aap:meldepliktshendelser" - */ -// install(ContentNegotiation) { jackson {} } -// routing { -// post(config.tokenEndpointUrl) { -// call.respond(HttpStatusCode.OK, RSAKey.parse("a.b.c")) -// } -// } -//} diff --git a/ktor-auth-tokenx/build.gradle.kts b/ktor-auth-tokenx/build.gradle.kts deleted file mode 100644 index 6433067a..00000000 --- a/ktor-auth-tokenx/build.gradle.kts +++ /dev/null @@ -1,15 +0,0 @@ -val ktorVersion = "2.3.8" - -dependencies { -// implementation(project(":cache")) - - implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion") - implementation("io.ktor:ktor-client-cio:$ktorVersion") - implementation("io.ktor:ktor-client-auth:$ktorVersion") - - implementation("io.ktor:ktor-serialization-jackson:$ktorVersion") - - implementation("com.fasterxml.jackson.core:jackson-databind:2.16.1") - implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.16.1") - implementation("com.nimbusds:nimbus-jose-jwt:9.37.3") -} diff --git a/ktor-auth-tokenx/main/no/nav/aap/ktor/client/Token.kt b/ktor-auth-tokenx/main/no/nav/aap/ktor/client/Token.kt deleted file mode 100644 index e2f825a4..00000000 --- a/ktor-auth-tokenx/main/no/nav/aap/ktor/client/Token.kt +++ /dev/null @@ -1,57 +0,0 @@ -package no.nav.aap.ktor.client - -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import org.slf4j.Logger -import java.time.Instant - -internal data class Token(val expires_in: Long, val access_token: String) { - private val expiry: Instant = Instant.now().plusSeconds(expires_in - LEEWAY_SECONDS) - - internal fun expired() = Instant.now().isAfter(expiry) - - private companion object { - const val LEEWAY_SECONDS = 60 - } - - override fun toString(): String { - return "($expires_in, $access_token)" - } -} - -internal class TokenCache { - private val tokens: HashMap = hashMapOf() - private val mutex = Mutex() - - internal fun logg(logger: Logger) { - tokens.forEach { (key, value) -> - logger.info("Key: $key, Value: $value") - } - } - - internal suspend fun add(key: String, token: Token) { - mutex.withLock { - tokens[key] = token - } - } - - internal suspend fun get(key: String): Token? { - mutex.withLock { - tokens[key] - }?.let { - if (it.expired()) { - rm(key) - } - } - - return mutex.withLock { - tokens[key] - } - } - - private suspend fun rm(key: String) { - mutex.withLock { - tokens.remove(key) - } - } -} diff --git a/ktor-auth-tokenx/main/no/nav/aap/ktor/client/TokenXProviderConfig.kt b/ktor-auth-tokenx/main/no/nav/aap/ktor/client/TokenXProviderConfig.kt deleted file mode 100644 index 413918dc..00000000 --- a/ktor-auth-tokenx/main/no/nav/aap/ktor/client/TokenXProviderConfig.kt +++ /dev/null @@ -1,11 +0,0 @@ -package no.nav.aap.ktor.client - -import java.net.URL - -data class TokenXProviderConfig( - val clientId: String, - val privateKey: String, - val tokenEndpoint: String, - val jwksUrl: URL, - val issuer: String, -) diff --git a/ktor-auth-tokenx/main/no/nav/aap/ktor/client/TokenXTokenProvider.kt b/ktor-auth-tokenx/main/no/nav/aap/ktor/client/TokenXTokenProvider.kt deleted file mode 100644 index 5c30cf09..00000000 --- a/ktor-auth-tokenx/main/no/nav/aap/ktor/client/TokenXTokenProvider.kt +++ /dev/null @@ -1,95 +0,0 @@ -package no.nav.aap.ktor.client - -import com.nimbusds.jose.JOSEObjectType -import com.nimbusds.jose.JWSAlgorithm -import com.nimbusds.jose.JWSHeader -import com.nimbusds.jose.crypto.RSASSASigner -import com.nimbusds.jose.jwk.RSAKey -import com.nimbusds.jwt.JWTClaimsSet -import com.nimbusds.jwt.SignedJWT -import io.ktor.client.call.body -import io.ktor.client.request.accept -import io.ktor.client.request.post -import io.ktor.client.request.setBody -import io.ktor.client.statement.bodyAsText -import io.ktor.http.contentType -import io.ktor.http.isSuccess -import io.ktor.serialization.jackson.jackson -import org.slf4j.LoggerFactory -import java.time.Instant -import java.util.* - -private val secureLog = LoggerFactory.getLogger("secureLog") -class TokenXTokenProvider( - private val config: TokenXProviderConfig, - private val audience: String, - private val client: io.ktor.client.HttpClient = defaultHttpClient, -) { - - private val jwtFactory = JwtGrantFactory(config) - suspend fun getOnBehalfOfToken(tokenx_token: String) = getAccessToken(tokenx_token+audience) { - """ - grant_type=urn:ietf:params:oauth:grant-type:token-exchange - &client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer - &subject_token_type=urn:ietf:params:oauth:token-type:jwt - &client_assertion=${jwtFactory.jwt} - &audience=$audience - &subject_token=$tokenx_token - """.trimIndent() - .replace("\n", "") - } - - private val cache = TokenCache() - - private suspend fun getAccessToken(cacheKey: String, body: () -> String): String { - cache.logg(secureLog) - val token = cache.get(cacheKey) - ?: client.post(config.tokenEndpoint) { - accept(io.ktor.http.ContentType.Application.Json) - contentType(io.ktor.http.ContentType.Application.FormUrlEncoded) - setBody(body()) - }.also { - if (!it.status.isSuccess()) { - secureLog.warn("Feilet token-kall {}: {}", it.status.value, it.bodyAsText()) - } - }.body().also { - cache.add(cacheKey, it) - } - - return token.access_token - } - - private companion object { - private val defaultHttpClient = io.ktor.client.HttpClient(io.ktor.client.engine.cio.CIO) { - install(io.ktor.client.plugins.contentnegotiation.ContentNegotiation) { - jackson { - registerModule(com.fasterxml.jackson.datatype.jsr310.JavaTimeModule()) - disable(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) - } - } - } - } -} - -internal class JwtGrantFactory(private val config: TokenXProviderConfig) { - internal val jwt: String get() = signedJwt.serialize() - - private val privateKey = RSAKey.parse(config.privateKey) - private val signedJwt get() = SignedJWT(jwsHeader, jwtClaimSet).apply { sign(RSASSASigner(privateKey)) } - private val jwsHeader - get() = JWSHeader.Builder(JWSAlgorithm.RS256) - .keyID(privateKey.keyID) - .type(JOSEObjectType.JWT) - .build() - - private val jwtClaimSet: JWTClaimsSet - get() = JWTClaimsSet.Builder().apply { - subject(config.clientId) - issuer(config.clientId) - audience(config.tokenEndpoint) - jwtID(UUID.randomUUID().toString()) - notBeforeTime(Date()) - issueTime(Date()) - expirationTime(Date.from(Instant.now().plusSeconds(120))) - }.build() -} \ No newline at end of file diff --git a/ktor-utils/build.gradle.kts b/ktor-utils/build.gradle.kts deleted file mode 100644 index 82c85c05..00000000 --- a/ktor-utils/build.gradle.kts +++ /dev/null @@ -1,7 +0,0 @@ -dependencies { - implementation("io.ktor:ktor-server-core:2.3.8") - implementation("com.sksamuel.hoplite:hoplite-yaml:2.7.5") - - testImplementation(kotlin("test")) - testImplementation("io.ktor:ktor-server-test-host:2.3.8") -} diff --git a/ktor-utils/main/no/nav/aap/ktor/config/Config.kt b/ktor-utils/main/no/nav/aap/ktor/config/Config.kt deleted file mode 100644 index 24f9d064..00000000 --- a/ktor-utils/main/no/nav/aap/ktor/config/Config.kt +++ /dev/null @@ -1,19 +0,0 @@ -package no.nav.aap.ktor.config - -import com.sksamuel.hoplite.ConfigLoader -import com.sksamuel.hoplite.ConfigLoaderBuilder -import com.sksamuel.hoplite.sources.MapPropertySource -import com.sksamuel.hoplite.yaml.YamlParser -import io.ktor.server.application.* -import io.ktor.server.config.* - -inline fun Application.loadConfig(resource: String = "/application.yml"): T = - ConfigLoader.builder() - .addFileExtensionMapping("yml", YamlParser()) - .addKtorConfig(environment.config) - .build() - .loadConfigOrThrow(resource) - -fun ConfigLoaderBuilder.addKtorConfig(config: ApplicationConfig) = apply { - if (config is MapApplicationConfig) addPropertySource(MapPropertySource(config.toMap())) -} diff --git a/ktor-utils/test/application.yml b/ktor-utils/test/application.yml deleted file mode 100644 index 33de66c2..00000000 --- a/ktor-utils/test/application.yml +++ /dev/null @@ -1 +0,0 @@ -value: ${TEST_VALUE} diff --git a/ktor-utils/test/no/nav/aap/ktor/config/ConfigTest.kt b/ktor-utils/test/no/nav/aap/ktor/config/ConfigTest.kt deleted file mode 100644 index 2fa21223..00000000 --- a/ktor-utils/test/no/nav/aap/ktor/config/ConfigTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package no.nav.aap.ktor.config - -import io.ktor.server.config.* -import io.ktor.server.testing.* -import org.junit.jupiter.api.Test -import kotlin.test.assertEquals - -class ConfigTest { - - data class TestConfig(val value: String) - - @Test - fun test() { - testApplication { - environment { - config = MapApplicationConfig("TEST_VALUE" to "hello") - } - application { - val config = loadConfig() - assertEquals("hello", config.value) - } - } - } -} diff --git a/settings.gradle.kts b/settings.gradle.kts index a51ab730..eb1f89bf 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -8,8 +8,4 @@ include( "kafka-avroserde", "kafka-test-2", "ktor-auth", - "ktor-auth-azuread", - "ktor-auth-maskinporten", - "ktor-auth-tokenx", - "ktor-utils", )