11package no.nav.security.mock.oauth2.grant
22
3+ import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
34import com.nimbusds.jwt.SignedJWT
45import com.nimbusds.oauth2.sdk.ResponseMode
56import com.nimbusds.openid.connect.sdk.AuthenticationRequest
67import io.kotest.assertions.asClue
78import io.kotest.matchers.shouldBe
9+ import io.kotest.matchers.shouldNotBe
810import no.nav.security.mock.oauth2.http.OAuth2HttpRequest
911import no.nav.security.mock.oauth2.login.Login
1012import no.nav.security.mock.oauth2.testutils.authenticationRequest
13+ import no.nav.security.mock.oauth2.testutils.claims
1114import no.nav.security.mock.oauth2.testutils.subject
1215import no.nav.security.mock.oauth2.token.DefaultOAuth2TokenCallback
1316import no.nav.security.mock.oauth2.token.OAuth2TokenProvider
1417import okhttp3.Headers
1518import okhttp3.HttpUrl
1619import okhttp3.HttpUrl.Companion.toHttpUrl
1720import org.junit.jupiter.api.Test
21+ import org.junit.jupiter.params.ParameterizedTest
22+ import org.junit.jupiter.params.provider.Arguments
23+ import org.junit.jupiter.params.provider.MethodSource
24+ import org.junit.jupiter.params.provider.ValueSource
25+ import java.util.stream.Stream
1826
1927internal class AuthorizationCodeHandlerTest {
2028 private val handler = AuthorizationCodeHandler (OAuth2TokenProvider (), RefreshTokenManager ())
@@ -39,16 +47,60 @@ internal class AuthorizationCodeHandlerTest {
3947
4048 @Test
4149 fun `token response with login should return id_token and access_token containing username from login as sub` () {
42- val code: String = handler.authorizationCodeResponse(
43- authenticationRequest = " http://authorizationendpoint" .toHttpUrl().authenticationRequest().asNimbusAuthRequest(),
44- login = Login (" foo" )
45- ).authorizationCode.value
50+ val code: String = handler.retrieveAuthorizationCode(Login (" foo" ))
4651
4752 handler.tokenResponse(tokenRequest(code = code), " http://myissuer" .toHttpUrl(), DefaultOAuth2TokenCallback ()).asClue {
4853 SignedJWT .parse(it.idToken).subject shouldBe " foo"
4954 }
5055 }
5156
57+ @ParameterizedTest
58+ @MethodSource(" jsonClaimsProvider" )
59+ fun `token response with login including claims should return access_token containing claims from login` (claims : String , expectedClaimKey : String , expectedClaimValue : String ) {
60+ val code: String = handler.retrieveAuthorizationCode(Login (" foo" , claims))
61+
62+ handler.tokenResponse(tokenRequest(code = code), " http://myissuer" .toHttpUrl(), DefaultOAuth2TokenCallback ()).asClue {
63+ val claim = SignedJWT .parse(it.idToken).claims[expectedClaimKey]
64+ claim shouldNotBe null
65+ jacksonObjectMapper().writeValueAsString(claim) shouldBe expectedClaimValue
66+ }
67+ }
68+
69+ companion object {
70+ @JvmStatic
71+ fun jsonClaimsProvider (): Stream <Arguments > = Stream .of(
72+ Arguments .of(" { \" acr\" : \" value\" }" , " acr" , " \" value\" " ),
73+ Arguments .of(" { \" acr\" : { \" reference\" : { \" id\" : \" value\" } } }" , " acr" , " {\" reference\" :{\" id\" :\" value\" }}" )
74+ )
75+ }
76+
77+ @Test
78+ fun `token response with login including multiple claims should return access_token containing all claims from login` () {
79+ val code: String = handler.retrieveAuthorizationCode(Login (" foo" , " { \" acr\" : \" value1\" , \" abc\" : \" value2\" }" ))
80+
81+ handler.tokenResponse(tokenRequest(code = code), " http://myissuer" .toHttpUrl(), DefaultOAuth2TokenCallback ()).asClue {
82+ val claims = SignedJWT .parse(it.idToken).claims
83+ claims[" acr" ] shouldBe " value1"
84+ claims[" abc" ] shouldBe " value2"
85+ }
86+ }
87+
88+ @ParameterizedTest
89+ @ValueSource(strings = [" {" , " []" , " [\" claim\" ]" , " {}" ])
90+ fun `token response with login including invalid JSON for claims parsing should return access_token containing no additional claims` (claimsValue : String ) {
91+ val code: String = handler.retrieveAuthorizationCode(Login (" foo" , claimsValue))
92+
93+ handler.tokenResponse(tokenRequest(code = code), " http://myissuer" .toHttpUrl(), DefaultOAuth2TokenCallback ()).asClue {
94+ SignedJWT .parse(it.idToken).claims.count() shouldBe 10
95+ }
96+ }
97+
98+ private fun AuthorizationCodeHandler.retrieveAuthorizationCode (login : Login ): String =
99+ authorizationCodeResponse(
100+ authenticationRequest = " http://authorizationendpoint" .toHttpUrl().authenticationRequest().asNimbusAuthRequest(),
101+ login = login
102+ ).authorizationCode.value
103+
52104 private fun HttpUrl.asNimbusAuthRequest (): AuthenticationRequest = AuthenticationRequest .parse(this .toUri())
53105
54106 private fun tokenRequest (
0 commit comments