Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: replace custom TokenExchangeGrant with Nimbus SDK grant #732

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -241,11 +241,12 @@ open class MockOAuth2Server(
val uri = tokenEndpointUrl(issuerId)
val issuerUrl = issuerUrl(issuerId)
val tokenRequest =
TokenRequest(
uri.toUri(),
ClientSecretBasic(ClientID(clientId), Secret("secret")),
AuthorizationCodeGrant(AuthorizationCode("123"), URI.create("http://localhost")),
)
TokenRequest
.Builder(
uri.toUri(),
ClientSecretBasic(ClientID(clientId), Secret("secret")),
AuthorizationCodeGrant(AuthorizationCode("123"), URI.create("http://localhost")),
).build()
return config.tokenProvider.accessToken(tokenRequest, issuerUrl, tokenCallback, null)
}

Expand Down Expand Up @@ -291,7 +292,7 @@ open class MockOAuth2Server(
override fun toParameters(): MutableMap<String, MutableList<String>> = mutableMapOf()
}
return this.config.tokenProvider.exchangeAccessToken(
TokenRequest(URI.create("http://mockgrant"), ClientID("mockclientid"), mockGrant),
TokenRequest.Builder(URI.create("http://mockgrant"), ClientSecretBasic(ClientID("mockclientid"), Secret("secret")), mockGrant).build(),
issuerUrl,
jwtClaimsSet,
DefaultOAuth2TokenCallback(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import com.nimbusds.openid.connect.sdk.OIDCScopeValue
import com.nimbusds.openid.connect.sdk.Prompt
import mu.KotlinLogging
import no.nav.security.mock.oauth2.OAuth2Exception
import no.nav.security.mock.oauth2.grant.TokenExchangeGrant
import no.nav.security.mock.oauth2.invalidRequest
import java.time.Duration
import java.time.Instant
Expand Down Expand Up @@ -63,7 +62,7 @@ fun TokenRequest.scopesWithoutOidcScopes() =
OIDCScopeValue.values().map { it.toString() }.contains(value)
} ?: emptyList()

fun TokenRequest.tokenExchangeGrantOrNull(): TokenExchangeGrant? = authorizationGrant as? TokenExchangeGrant
fun TokenRequest.tokenExchangeGrantOrNull() = authorizationGrant as? com.nimbusds.oauth2.sdk.tokenexchange.TokenExchangeGrant

fun TokenRequest.authorizationCode(): AuthorizationCode =
this.authorizationGrant
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package no.nav.security.mock.oauth2.grant

import com.nimbusds.jwt.SignedJWT
import com.nimbusds.oauth2.sdk.TokenRequest
import com.nimbusds.oauth2.sdk.tokenexchange.TokenExchangeGrant
import no.nav.security.mock.oauth2.extensions.expiresIn
import no.nav.security.mock.oauth2.http.OAuth2HttpRequest
import no.nav.security.mock.oauth2.http.OAuth2TokenResponse
Expand Down Expand Up @@ -36,6 +37,8 @@ internal class TokenExchangeGrantHandler(
}
}

fun TokenRequest.subjectToken(): SignedJWT = SignedJWT.parse(this.tokenExchangeGrant().subjectToken)
fun TokenRequest.subjectToken(): SignedJWT = SignedJWT.parse(this.tokenExchangeGrant().subjectToken.value)

fun TokenRequest.audienceOrEmpty(): List<String> = (this.authorizationGrant as? TokenExchangeGrant)?.audience?.map { it.value } ?: emptyList()

fun TokenRequest.tokenExchangeGrant() = this.authorizationGrant as? TokenExchangeGrant ?: invalidRequest("missing token exchange grant")
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import no.nav.security.mock.oauth2.extensions.toJwksUrl
import no.nav.security.mock.oauth2.extensions.toRevocationEndpointUrl
import no.nav.security.mock.oauth2.extensions.toTokenEndpointUrl
import no.nav.security.mock.oauth2.extensions.toUserInfoUrl
import no.nav.security.mock.oauth2.grant.TokenExchangeGrant
import no.nav.security.mock.oauth2.missingParameter
import okhttp3.Headers
import okhttp3.HttpUrl
Expand All @@ -33,20 +32,13 @@ data class OAuth2HttpRequest(

fun asTokenExchangeRequest(): TokenRequest {
val httpRequest: HTTPRequest = this.asNimbusHTTPRequest()
var clientAuthentication = httpRequest.clientAuthentication()
val clientAuthentication = httpRequest.clientAuthentication()
if (clientAuthentication.method == ClientAuthenticationMethod.PRIVATE_KEY_JWT) {
clientAuthentication = clientAuthentication.requirePrivateKeyJwt(this.url.toString(), 120)
clientAuthentication.requirePrivateKeyJwt(this.url.toString(), 120)
}
val tokenExchangeGrant = TokenExchangeGrant.parse(formParameters.map)

// TODO: add scope if present in request
return TokenRequest(
this.url.toUri(),
clientAuthentication,
tokenExchangeGrant,
null,
emptyList(),
formParameters.map.mapValues { mutableListOf(it.value) },

return TokenRequest.parse(
this.asNimbusHTTPRequest(),
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.nimbusds.oauth2.sdk.GrantType.CLIENT_CREDENTIALS
import com.nimbusds.oauth2.sdk.GrantType.JWT_BEARER
import com.nimbusds.oauth2.sdk.GrantType.PASSWORD
import com.nimbusds.oauth2.sdk.GrantType.REFRESH_TOKEN
import com.nimbusds.oauth2.sdk.GrantType.TOKEN_EXCHANGE
import com.nimbusds.oauth2.sdk.OAuth2Error
import com.nimbusds.oauth2.sdk.ParseException
import com.nimbusds.openid.connect.sdk.AuthenticationRequest
Expand All @@ -33,7 +34,6 @@ import no.nav.security.mock.oauth2.grant.PasswordGrantHandler
import no.nav.security.mock.oauth2.grant.RefreshToken
import no.nav.security.mock.oauth2.grant.RefreshTokenGrantHandler
import no.nav.security.mock.oauth2.grant.RefreshTokenManager
import no.nav.security.mock.oauth2.grant.TOKEN_EXCHANGE
import no.nav.security.mock.oauth2.grant.TokenExchangeGrantHandler
import no.nav.security.mock.oauth2.introspect.introspect
import no.nav.security.mock.oauth2.invalidGrant
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,4 @@ open class KeyProvider
jwkSelector: JWKSelector?,
context: SecurityContext?,
): MutableList<JWK> = jwkSelector?.select(JWKSet(signingKeys.values.toList()).toPublicJWKSet()) ?: mutableListOf()

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import no.nav.security.mock.oauth2.extensions.clientIdAsString
import no.nav.security.mock.oauth2.extensions.grantType
import no.nav.security.mock.oauth2.extensions.replaceValues
import no.nav.security.mock.oauth2.extensions.scopesWithoutOidcScopes
import no.nav.security.mock.oauth2.extensions.tokenExchangeGrantOrNull
import no.nav.security.mock.oauth2.grant.audienceOrEmpty
import java.time.Duration
import java.util.UUID

Expand Down Expand Up @@ -48,10 +48,10 @@ open class DefaultOAuth2TokenCallback
override fun typeHeader(tokenRequest: TokenRequest): String = typeHeader

override fun audience(tokenRequest: TokenRequest): List<String> {
val audienceParam = tokenRequest.tokenExchangeGrantOrNull()?.audience
val audienceParam = tokenRequest.audienceOrEmpty()
return when {
audience != null -> audience
audienceParam != null -> audienceParam
audienceParam.isNotEmpty() -> audienceParam
tokenRequest.scope != null -> tokenRequest.scopesWithoutOidcScopes()
else -> listOf("default")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package no.nav.security.mock.oauth2.e2e

import com.nimbusds.jwt.JWTClaimsSet
import com.nimbusds.oauth2.sdk.GrantType.TOKEN_EXCHANGE
import io.kotest.matchers.collections.shouldContainExactly
import io.kotest.matchers.should
import io.kotest.matchers.shouldBe
import no.nav.security.mock.oauth2.grant.TOKEN_EXCHANGE
import no.nav.security.mock.oauth2.testutils.ClientAssertionType
import no.nav.security.mock.oauth2.testutils.ParsedTokenResponse
import no.nav.security.mock.oauth2.testutils.SubjectTokenType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import com.nimbusds.oauth2.sdk.GrantType.CLIENT_CREDENTIALS
import com.nimbusds.oauth2.sdk.GrantType.JWT_BEARER
import com.nimbusds.oauth2.sdk.GrantType.PASSWORD
import com.nimbusds.oauth2.sdk.GrantType.REFRESH_TOKEN
import com.nimbusds.oauth2.sdk.GrantType.TOKEN_EXCHANGE
import com.nimbusds.oauth2.sdk.TokenRequest
import io.kotest.assertions.assertSoftly
import io.kotest.matchers.Matcher
Expand All @@ -29,7 +30,6 @@ import io.kotest.matchers.ints.shouldBeGreaterThan
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import no.nav.security.mock.oauth2.MockOAuth2Server
import no.nav.security.mock.oauth2.grant.TOKEN_EXCHANGE
import no.nav.security.mock.oauth2.http.OAuth2HttpRequest
import no.nav.security.mock.oauth2.http.OAuth2TokenResponse
import okhttp3.Headers
Expand Down