Skip to content

Commit

Permalink
Token for payload client
Browse files Browse the repository at this point in the history
  • Loading branch information
thburnett committed May 13, 2024
1 parent 45cc2ab commit a4b653f
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 100 deletions.
107 changes: 7 additions & 100 deletions ebms-provider/src/main/kotlin/no/nav/emottak/ebms/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,15 @@
*/
package no.nav.emottak.ebms

import com.nimbusds.jwt.SignedJWT
import dev.reformator.stacktracedecoroutinator.runtime.DecoroutinatorRuntime
import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO
import io.ktor.client.plugins.auth.Auth
import io.ktor.client.plugins.auth.providers.BearerTokens
import io.ktor.client.plugins.auth.providers.bearer
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.request.forms.MultiPartFormDataContent
import io.ktor.client.request.header
import io.ktor.client.request.headers
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.Headers
import io.ktor.http.HeadersBuilder
import io.ktor.http.HttpStatusCode
import io.ktor.http.content.PartData
import io.ktor.http.content.forEachPart
import io.ktor.http.content.streamProvider
import io.ktor.serialization.kotlinx.json.json
import io.ktor.server.application.Application
import io.ktor.server.application.ApplicationCall
import io.ktor.server.application.call
Expand All @@ -47,7 +34,6 @@ import io.micrometer.prometheus.PrometheusConfig
import io.micrometer.prometheus.PrometheusMeterRegistry
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.json.Json
import net.logstash.logback.marker.Markers
import no.nav.emottak.constants.SMTPHeaders
import no.nav.emottak.ebms.model.DokumentType
Expand All @@ -66,12 +52,10 @@ import no.nav.emottak.util.createUniqueMimeMessageId
import no.nav.emottak.util.getEnvVar
import org.slf4j.LoggerFactory
import java.io.ByteArrayInputStream
import java.net.InetSocketAddress
import java.net.Proxy
import java.net.URL
import java.time.Duration
import java.time.Instant
import java.util.*
import java.util.Base64
import java.util.UUID
import kotlin.time.toKotlinDuration

val log = LoggerFactory.getLogger("no.nav.emottak.ebms.App")
Expand All @@ -89,83 +73,6 @@ fun main() {
}).start(wait = true)
}

fun defaultHttpClient(): () -> HttpClient {
return {
HttpClient(CIO) {
expectSuccess = true
install(io.ktor.client.plugins.contentnegotiation.ContentNegotiation) {
json()
}
}
}
}

val EBMS_SEND_IN_SCOPE = getEnvVar(
"EBMS_SEND_IN_SCOPE",
"api://" + getEnvVar("NAIS_CLUSTER_NAME", "dev-fss") + ".team-emottak.ebms-send-in/.default"
)
const val AZURE_AD_AUTH = "AZURE_AD"
val LENIENT_JSON_PARSER = Json {
isLenient = true
}
fun sendInAuthHttpClient(): () -> HttpClient {
return {
HttpClient(CIO) {
install(ContentNegotiation) {
json()
}
install(Auth) {
bearer {
refreshTokens {
val clientId = getEnvVar("AZURE_APP_CLIENT_ID", "ebms-send-in")
val azureEndpoint = getEnvVar(
"AZURE_OPENID_CONFIG_TOKEN_ENDPOINT",
"http://localhost:3344/$AZURE_AD_AUTH/token"
)
val requestBody =
"client_id=" + clientId +
"&client_secret=" + getEnvVar("AZURE_APP_CLIENT_SECRET", "dummysecret") +
"&scope=" + EBMS_SEND_IN_SCOPE +
"&grant_type=client_credentials"
// log.info("sendInAuthHttpClient() -> refreshTokens: client_id: $clientId, scope: $EBMS_SEND_IN_SCOPE, doing a post request to $azureEndpoint")
HttpClient(CIO) {
engine {
val httpProxyUrl = getEnvVar("HTTP_PROXY", "")
if (httpProxyUrl.isNotBlank()) {
proxy = Proxy(
Proxy.Type.HTTP,
InetSocketAddress(URL(httpProxyUrl).host, URL(httpProxyUrl).port)
)
}
}
}.post(
azureEndpoint
) {
headers {
header("Content-Type", "application/x-www-form-urlencoded")
}
setBody(requestBody)
}.bodyAsText()
.let { tokenResponseString ->
// log.info("The token response string we received was: $tokenResponseString")
SignedJWT.parse(
LENIENT_JSON_PARSER.decodeFromString<Map<String, String>>(tokenResponseString)["access_token"] as String
)
}
.let { parsedJwt ->
// log.info("After parsing it, we got: $parsedJwt")
BearerTokens(parsedJwt.serialize(), "refresh token is unused")
}
}
sendWithoutRequest {
true
}
}
}
}
}
}

fun PartData.payload(clearText: Boolean = false): ByteArray {
return when (this) {
is PartData.FormItem -> if (clearText) {
Expand All @@ -185,13 +92,13 @@ fun PartData.payload(clearText: Boolean = false): ByteArray {
}

fun Application.ebmsProviderModule() {
val client = defaultHttpClient()
val cpaClient = CpaRepoClient(client)
val processingClient = PayloadProcessingClient(client)
val sendInHttpClient = sendInAuthHttpClient()
val sendInClient = SendInClient(sendInHttpClient)
val cpaClient = CpaRepoClient(defaultHttpClient())
val validator = DokumentValidator(cpaClient)

val processingClient = PayloadProcessingClient(scopedAuthHttpClient(EBMS_PAYLOAD_SCOPE))
val processing = ProcessingService(processingClient)

val sendInClient = SendInClient(scopedAuthHttpClient(EBMS_SEND_IN_SCOPE))
val sendInService = SendInService(sendInClient)

val appMicrometerRegistry = PrometheusMeterRegistry(PrometheusConfig.DEFAULT)
Expand Down
98 changes: 98 additions & 0 deletions ebms-provider/src/main/kotlin/no/nav/emottak/ebms/HttpClients.kt
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
package no.nav.emottak.ebms

import com.nimbusds.jwt.SignedJWT
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.engine.cio.CIO
import io.ktor.client.plugins.auth.Auth
import io.ktor.client.plugins.auth.providers.BearerTokens
import io.ktor.client.plugins.auth.providers.bearer
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.request.header
import io.ktor.client.request.headers
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.contentType
import io.ktor.serialization.kotlinx.json.json
import kotlinx.serialization.json.Json
import no.nav.emottak.melding.model.PayloadRequest
import no.nav.emottak.melding.model.PayloadResponse
import no.nav.emottak.melding.model.SendInRequest
import no.nav.emottak.melding.model.SendInResponse
import no.nav.emottak.melding.model.ValidationRequest
import no.nav.emottak.melding.model.ValidationResult
import no.nav.emottak.util.getEnvVar
import java.net.InetSocketAddress
import java.net.Proxy
import java.net.URI

class CpaRepoClient(clientProvider: () -> HttpClient) {
private var httpClient = clientProvider.invoke()
Expand Down Expand Up @@ -50,3 +64,87 @@ class SendInClient(clientProvider: () -> HttpClient) {
}.body()
}
}

val EBMS_SEND_IN_SCOPE = getEnvVar(
"EBMS_SEND_IN_SCOPE",
"api://" + getEnvVar("NAIS_CLUSTER_NAME", "dev-fss") + ".team-emottak.ebms-send-in/.default"
)
val EBMS_PAYLOAD_SCOPE = getEnvVar(
"EBMS_PAYLOAD_SCOPE",
"api://" + getEnvVar("NAIS_CLUSTER_NAME", "dev-fss") + ".team-emottak.ebms-payload/.default"
)

fun defaultHttpClient(): () -> HttpClient {
return {
HttpClient(CIO) {
expectSuccess = true
install(ContentNegotiation) {
json()
}
}
}
}

const val AZURE_AD_AUTH = "AZURE_AD"
val LENIENT_JSON_PARSER = Json {
isLenient = true
}

fun scopedAuthHttpClient(
scope: String
): () -> HttpClient {
return {
HttpClient(CIO) {
install(ContentNegotiation) {
json()
}
install(Auth) {
bearer {
refreshTokens {
proxiedHttpClient().post(
getEnvVar(
"AZURE_OPENID_CONFIG_TOKEN_ENDPOINT",
"http://localhost:3344/$AZURE_AD_AUTH/token"
)
) {
headers {
header("Content-Type", "application/x-www-form-urlencoded")
}
setBody(
"client_id=" + getEnvVar("AZURE_APP_CLIENT_ID", "dummyclient") +
"&client_secret=" + getEnvVar("AZURE_APP_CLIENT_SECRET", "dummysecret") +
"&scope=" + scope +
"&grant_type=client_credentials"
)
}.bodyAsText()
.let { tokenResponseString ->
// log.info("The token response string we received was: $tokenResponseString")
SignedJWT.parse(
LENIENT_JSON_PARSER.decodeFromString<Map<String, String>>(tokenResponseString)["access_token"] as String
)
}
.let { parsedJwt ->
// log.info("After parsing it, we got: $parsedJwt")
BearerTokens(parsedJwt.serialize(), "refresh token is unused")
}
}
sendWithoutRequest {
true
}
}
}
}
}
}

private fun proxiedHttpClient() = HttpClient(CIO) {
engine {
val httpProxyUrl = getEnvVar("HTTP_PROXY", "")
if (httpProxyUrl.isNotBlank()) {
proxy = Proxy(
Proxy.Type.HTTP,
InetSocketAddress(URI(httpProxyUrl).toURL().host, URI(httpProxyUrl).toURL().port)
)
}
}
}

0 comments on commit a4b653f

Please sign in to comment.