Skip to content

Commit

Permalink
Justert libs til ny versjon av token-support
Browse files Browse the repository at this point in the history
Fjernet retry på 502 då det ikke er rett frem og enligt loggene er det kun timeouts siste 3 mnd
  • Loading branch information
blommish committed Feb 12, 2024
1 parent 48ce38a commit 72d9d28
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ import org.springframework.web.client.RestClientResponseException
class ProblemDetailException(
val detail: ProblemDetail,
val responseException: RestClientResponseException,
val httpStatus: HttpStatus = HttpStatus.valueOf(responseException.rawStatusCode),
val httpStatus: HttpStatus = HttpStatus.valueOf(responseException.statusCode.value()),
) : RuntimeException(responseException)
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import no.nav.security.token.support.client.core.http.OAuth2HttpRequest
import no.nav.security.token.support.client.core.oauth2.OAuth2AccessTokenResponse
import no.nav.security.token.support.client.spring.oauth2.DefaultOAuth2HttpClient
import org.slf4j.LoggerFactory
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.core.NestedExceptionUtils
import org.springframework.web.client.HttpServerErrorException
import org.springframework.web.client.RestClient
import java.net.SocketException
import java.net.SocketTimeoutException

class RetryOAuth2HttpClient(
restTemplateBuilder: RestTemplateBuilder,
restClient: RestClient,
private val maxRetries: Int = 2,
) : DefaultOAuth2HttpClient(restTemplateBuilder) {
) : DefaultOAuth2HttpClient(restClient) {

private val logger = LoggerFactory.getLogger(javaClass)
private val secureLogger = LoggerFactory.getLogger("secureLogger")
Expand All @@ -23,10 +23,9 @@ class RetryOAuth2HttpClient(
SocketException::class,
SocketTimeoutException::class,
HttpServerErrorException.GatewayTimeout::class,
HttpServerErrorException.BadGateway::class,
)

override fun post(req: OAuth2HttpRequest): OAuth2AccessTokenResponse? {
override fun post(req: OAuth2HttpRequest): OAuth2AccessTokenResponse {
var retries = 0

while (true) {
Expand All @@ -44,6 +43,7 @@ class RetryOAuth2HttpClient(
retries: Int,
oAuth2HttpRequest: OAuth2HttpRequest,
) {
e.printStackTrace()
if (shouldRetry(e) && retries < maxRetries) {
logger.warn(
"Kall mot url=${oAuth2HttpRequest.tokenEndpointUrl} feilet, cause=${
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ import no.nav.tilleggsstonader.libs.http.interceptor.BearerTokenExchangeClientIn
import no.nav.tilleggsstonader.libs.http.interceptor.BearerTokenOnBehalfOfClientInterceptor
import no.nav.tilleggsstonader.libs.http.interceptor.ConsumerIdClientInterceptor
import no.nav.tilleggsstonader.libs.http.interceptor.MdcValuesPropagatingClientInterceptor
import org.springframework.boot.web.client.ClientHttpRequestFactories
import org.springframework.boot.web.client.ClientHttpRequestFactorySettings
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Import
import org.springframework.context.annotation.Primary
import org.springframework.web.client.RestClient
import org.springframework.web.client.RestTemplate
import java.time.Duration
import java.time.temporal.ChronoUnit
Expand All @@ -34,19 +37,19 @@ class RestTemplateConfiguration(
@Primary
@Bean
fun oAuth2HttpClient(
restTemplateBuilder: RestTemplateBuilder,
restClientBuilder: RestClient.Builder,
consumerIdClientInterceptor: ConsumerIdClientInterceptor,
mdcValuesPropagatingClientInterceptor: MdcValuesPropagatingClientInterceptor,
): RetryOAuth2HttpClient {
return RetryOAuth2HttpClient(
restTemplateBuilder
.setConnectTimeout(Duration.of(2, ChronoUnit.SECONDS))
.setReadTimeout(Duration.of(4, ChronoUnit.SECONDS))
.additionalInterceptors(
consumerIdClientInterceptor,
mdcValuesPropagatingClientInterceptor,
),
)
val clientHttpRequestFactorySettings = ClientHttpRequestFactorySettings.DEFAULTS
.withConnectTimeout(Duration.of(1, ChronoUnit.SECONDS))
.withReadTimeout(Duration.of(1, ChronoUnit.SECONDS))
val restClient = restClientBuilder
.requestFactory(ClientHttpRequestFactories.get(clientHttpRequestFactorySettings))
.requestInterceptor(consumerIdClientInterceptor)
.requestInterceptor(mdcValuesPropagatingClientInterceptor)
.build()
return RetryOAuth2HttpClient(restClient)
}

@Bean("utenAuth")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package no.nav.tilleggsstonader.libs.http.interceptor

import com.nimbusds.oauth2.sdk.GrantType
import no.nav.security.token.support.client.core.ClientProperties
import no.nav.security.token.support.client.core.OAuth2GrantType
import no.nav.security.token.support.client.core.oauth2.OAuth2AccessTokenService
import no.nav.security.token.support.client.spring.ClientConfigurationProperties
import no.nav.security.token.support.core.exceptions.JwtTokenMissingException
import no.nav.security.token.support.spring.SpringTokenValidationContextHolder
import org.springframework.http.HttpRequest
import org.springframework.http.client.ClientHttpRequestExecution
Expand Down Expand Up @@ -50,7 +51,7 @@ class BearerTokenClientCredentialsClientInterceptor(
request,
clientConfigurationProperties,
oAuth2AccessTokenService,
OAuth2GrantType.CLIENT_CREDENTIALS,
GrantType.CLIENT_CREDENTIALS,
),
)
return execution.execute(request, body)
Expand All @@ -73,7 +74,7 @@ class BearerTokenExchangeClientInterceptor(
request,
clientConfigurationProperties,
oAuth2AccessTokenService,
OAuth2GrantType.TOKEN_EXCHANGE,
GrantType.TOKEN_EXCHANGE,
),
)
return execution.execute(request, body)
Expand All @@ -96,7 +97,7 @@ class BearerTokenOnBehalfOfClientInterceptor(
request,
clientConfigurationProperties,
oAuth2AccessTokenService,
OAuth2GrantType.JWT_BEARER,
GrantType.JWT_BEARER,
),
)
return execution.execute(request, body)
Expand All @@ -107,14 +108,15 @@ private fun genererAccessToken(
request: HttpRequest,
clientConfigurationProperties: ClientConfigurationProperties,
oAuth2AccessTokenService: OAuth2AccessTokenService,
grantType: OAuth2GrantType? = null,
grantType: GrantType? = null,
): String {
val clientProperties = clientPropertiesFor(
request.uri,
clientConfigurationProperties,
grantType,
)
return oAuth2AccessTokenService.getAccessToken(clientProperties).accessToken
?: throw JwtTokenMissingException()
}

/**
Expand All @@ -127,7 +129,7 @@ private fun genererAccessToken(
private fun clientPropertiesFor(
uri: URI,
clientConfigurationProperties: ClientConfigurationProperties,
grantType: OAuth2GrantType?,
grantType: GrantType?,
): ClientProperties {
val clientProperties = filterClientProperties(clientConfigurationProperties, uri)
return if (grantType == null) {
Expand All @@ -151,20 +153,20 @@ private fun filterClientProperties(

private fun clientPropertiesForGrantType(
values: List<ClientProperties>,
grantType: OAuth2GrantType,
grantType: GrantType,
uri: URI,
): ClientProperties {
return values.firstOrNull { grantType == it.grantType }
?: error("could not find oauth2 client config for uri=$uri and grant type=$grantType")
}

private fun clientCredentialOrJwtBearer() =
if (erSystembruker()) OAuth2GrantType.CLIENT_CREDENTIALS else OAuth2GrantType.JWT_BEARER
if (erSystembruker()) GrantType.CLIENT_CREDENTIALS else GrantType.JWT_BEARER

private fun erSystembruker(): Boolean {
return try {
val preferred_username =
SpringTokenValidationContextHolder().tokenValidationContext.getClaims("azuread")["preferred_username"]
val tokenValidationContext = SpringTokenValidationContextHolder().getTokenValidationContext()
val preferred_username = tokenValidationContext.getClaims("azuread").get("preferred_username")
return preferred_username == null
} catch (e: Throwable) {
// Ingen request context. Skjer ved kall som har opphav i kjørende applikasjon. Ping etc.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,24 @@ import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.boot.web.client.ClientHttpRequestFactories
import org.springframework.boot.web.client.ClientHttpRequestFactorySettings
import org.springframework.web.client.RestClient
import java.net.URI
import java.time.Duration
import java.time.temporal.ChronoUnit

internal class RetryOAuth2HttpClientTest {

private val restTemplateBuilder = RestTemplateBuilder()
.setConnectTimeout(Duration.of(1, ChronoUnit.SECONDS))
.setReadTimeout(Duration.of(1, ChronoUnit.SECONDS))
val clientHttpRequestFactorySettings = ClientHttpRequestFactorySettings.DEFAULTS
.withConnectTimeout(Duration.of(1, ChronoUnit.SECONDS))
.withReadTimeout(Duration.of(1, ChronoUnit.SECONDS))

private val client = RetryOAuth2HttpClient(restTemplateBuilder)
val requestFactory = ClientHttpRequestFactories.get(clientHttpRequestFactorySettings)
val restClient = RestClient.builder()
.requestFactory(requestFactory)
.build()
val client = RetryOAuth2HttpClient(restClient)

@BeforeEach
internal fun setUp() {
Expand Down Expand Up @@ -51,13 +57,6 @@ internal class RetryOAuth2HttpClientTest {
wireMockServer.verify(2, RequestPatternBuilder.allRequests())
}

@Test
internal fun `502 - skal prøve på nytt`() {
stub(WireMock.serverError().withStatus(502))
post()
wireMockServer.verify(3, RequestPatternBuilder.allRequests())
}

@Test
internal fun `socketException - skal prøve på nytt`() {
stub(WireMock.serverError().withFault(Fault.CONNECTION_RESET_BY_PEER))
Expand All @@ -82,8 +81,7 @@ internal class RetryOAuth2HttpClientTest {
private fun post(): Exception? {
return try {
client.post(
OAuth2HttpRequest.builder()
.tokenEndpointUrl(URI.create(wireMockServer.baseUrl()))
OAuth2HttpRequest.builder(URI.create(wireMockServer.baseUrl()))
.oAuth2HttpHeaders(OAuth2HttpHeaders.builder().build())
.build(),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ internal class BearerTokenClientCredentialsClientInterceptorTest {

bearerTokenClientInterceptor.intercept(req, ByteArray(0), execution)

verify { oAuth2AccessTokenService.getAccessToken(clientConfigurationProperties.registration["1"]) }
verify { oAuth2AccessTokenService.getAccessToken(clientConfigurationProperties.registration["1"]!!) }
}

@Test
Expand All @@ -43,6 +43,6 @@ internal class BearerTokenClientCredentialsClientInterceptorTest {
every { req.uri } returns (URI("http://jwtResource.no"))
val execution = mockk<ClientHttpRequestExecution>(relaxed = true)
assertThat(catchThrowable { bearerTokenClientInterceptor.intercept(req, ByteArray(0), execution) })
.hasMessage("could not find oauth2 client config for uri=http://jwtResource.no and grant type=OAuth2GrantType[value=client_credentials]")
.hasMessage("could not find oauth2 client config for uri=http://jwtResource.no and grant type=client_credentials")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class BearerTokenClientInterceptorTest {

bearerTokenClientInterceptor.intercept(req, ByteArray(0), execution)

verify { oAuth2AccessTokenService.getAccessToken(clientConfigurationProperties.registration["1"]) }
verify { oAuth2AccessTokenService.getAccessToken(clientConfigurationProperties.registration["1"]!!) }
}

@Test
Expand All @@ -56,7 +56,7 @@ class BearerTokenClientInterceptorTest {

bearerTokenClientInterceptor.intercept(req, ByteArray(0), execution)

verify { oAuth2AccessTokenService.getAccessToken(clientConfigurationProperties.registration["2"]) }
verify { oAuth2AccessTokenService.getAccessToken(clientConfigurationProperties.registration["2"]!!) }
}

fun mockBrukerContext(preferredUsername: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ internal class BearerTokenOnBehalfOfClientInterceptorTest {

bearerTokenClientInterceptor.intercept(req, ByteArray(0), execution)

verify { oAuth2AccessTokenService.getAccessToken(clientConfigurationProperties.registration["2"]) }
verify { oAuth2AccessTokenService.getAccessToken(clientConfigurationProperties.registration["2"]!!) }
}

@Test
Expand All @@ -50,6 +50,6 @@ internal class BearerTokenOnBehalfOfClientInterceptorTest {
)
},
)
.hasMessage("could not find oauth2 client config for uri=http://clientResource.no and grant type=OAuth2GrantType[value=urn:ietf:params:oauth:grant-type:jwt-bearer]")
.hasMessage("could not find oauth2 client config for uri=http://clientResource.no and grant type=urn:ietf:params:oauth:grant-type:jwt-bearer")
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package no.nav.tilleggsstonader.libs.http.interceptor

import com.nimbusds.oauth2.sdk.GrantType
import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod
import no.nav.security.token.support.client.core.ClientAuthenticationProperties
import no.nav.security.token.support.client.core.ClientProperties
import no.nav.security.token.support.client.core.OAuth2GrantType
import no.nav.security.token.support.client.spring.ClientConfigurationProperties
import java.net.URI

Expand All @@ -20,7 +20,7 @@ val clientConfigurationProperties =
"1" to ClientProperties(
URI(tokenEndpoint),
URI(tokenEndpoint),
OAuth2GrantType.CLIENT_CREDENTIALS,
GrantType.CLIENT_CREDENTIALS,
listOf("z", "y", "x"),
authentication,
URI("http://firstResource.no"),
Expand All @@ -29,7 +29,7 @@ val clientConfigurationProperties =
"2" to ClientProperties(
URI(tokenEndpoint),
URI(tokenEndpoint),
OAuth2GrantType.JWT_BEARER,
GrantType.JWT_BEARER,
listOf("c", "b", "a"),
authentication,
URI("http://firstResource.no"),
Expand All @@ -38,7 +38,7 @@ val clientConfigurationProperties =
"3" to ClientProperties(
URI(tokenEndpoint),
URI(tokenEndpoint),
OAuth2GrantType.JWT_BEARER,
GrantType.JWT_BEARER,
listOf("z", "y", "x"),
authentication,
URI("http://jwtResource.no"),
Expand All @@ -47,7 +47,7 @@ val clientConfigurationProperties =
"4" to ClientProperties(
URI(tokenEndpoint),
URI(tokenEndpoint),
OAuth2GrantType.CLIENT_CREDENTIALS,
GrantType.CLIENT_CREDENTIALS,
listOf("z", "y", "x"),
authentication,
URI("http://clientResource.no"),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package no.nav.tilleggsstonader.libs.sikkerhet

import no.nav.security.token.support.core.context.TokenValidationContext
import no.nav.security.token.support.core.exceptions.JwtTokenMissingException
import no.nav.security.token.support.core.exceptions.JwtTokenValidatorException
import no.nav.security.token.support.core.jwt.JwtTokenClaims
import no.nav.security.token.support.spring.SpringTokenValidationContextHolder
Expand Down Expand Up @@ -29,7 +30,7 @@ object EksternBrukerUtils {

fun getBearerTokenForLoggedInUser(): String {
return getFromContext { validationContext, issuer ->
validationContext.getJwtToken(issuer).tokenAsString
validationContext.getJwtToken(issuer)?.encodedToken ?: throw JwtTokenMissingException()
}
}

Expand Down

0 comments on commit 72d9d28

Please sign in to comment.