Browse Source

Fix JWK Set URI precedence over decoder in Kotlin

Fixes: gh-7877
Eleftheria Stein 5 years ago
parent
commit
1fed688f05

+ 15 - 2
config/src/main/kotlin/org/springframework/security/config/web/servlet/oauth2/resourceserver/JwtDsl.kt

@@ -35,9 +35,22 @@ import org.springframework.security.oauth2.jwt.JwtDecoder
  * <a target="_blank" href="https://tools.ietf.org/html/rfc7517">JSON Web Key (JWK)</a> URL
  */
 class JwtDsl {
+    private var _jwtDecoder: JwtDecoder? = null
+    private var _jwkSetUri: String? = null
+
     var jwtAuthenticationConverter: Converter<Jwt, out AbstractAuthenticationToken>? = null
-    var jwtDecoder: JwtDecoder? = null
-    var jwkSetUri: String? = null
+    var jwtDecoder: JwtDecoder?
+        get() = _jwtDecoder
+        set(value) {
+            _jwtDecoder = value
+            _jwkSetUri = null
+        }
+    var jwkSetUri: String?
+        get() = _jwkSetUri
+        set(value) {
+            _jwkSetUri = value
+            _jwtDecoder = null
+        }
 
     internal fun get(): (OAuth2ResourceServerConfigurer<HttpSecurity>.JwtConfigurer) -> Unit {
         return { jwt ->

+ 39 - 2
config/src/test/kotlin/org/springframework/security/config/web/servlet/oauth2/resourceserver/JwtDslTests.kt

@@ -25,10 +25,10 @@ import org.springframework.core.convert.converter.Converter
 import org.springframework.security.authentication.AbstractAuthenticationToken
 import org.springframework.security.authentication.TestingAuthenticationToken
 import org.springframework.security.config.annotation.web.builders.HttpSecurity
-import org.springframework.security.config.web.servlet.invoke
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
 import org.springframework.security.config.test.SpringTestRule
+import org.springframework.security.config.web.servlet.invoke
 import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames
 import org.springframework.security.oauth2.jwt.Jwt
 import org.springframework.security.oauth2.jwt.JwtDecoder
@@ -85,7 +85,7 @@ class JwtDslTests {
     }
 
     @Test
-    fun `opaque token when custom JWT authentication converter then converter used`() {
+    fun `JWT when custom JWT authentication converter then converter used`() {
         this.spring.register(CustomJwtAuthenticationConverterConfig::class.java).autowire()
         `when`(CustomJwtAuthenticationConverterConfig.DECODER.decode(anyString())).thenReturn(
                 Jwt.withTokenValue("token")
@@ -126,4 +126,41 @@ class JwtDslTests {
             return DECODER
         }
     }
+
+    @Test
+    fun `JWT when custom JWT decoder set after jwkSetUri then decoder used`() {
+        this.spring.register(JwtDecoderAfterJwkSetUriConfig::class.java).autowire()
+        `when`(JwtDecoderAfterJwkSetUriConfig.DECODER.decode(anyString())).thenReturn(
+                Jwt.withTokenValue("token")
+                        .header("alg", "none")
+                        .claim(IdTokenClaimNames.SUB, "user")
+                        .build())
+
+        this.mockMvc.get("/") {
+            header("Authorization", "Bearer token")
+        }
+
+        verify(JwtDecoderAfterJwkSetUriConfig.DECODER).decode(any())
+    }
+
+    @EnableWebSecurity
+    open class JwtDecoderAfterJwkSetUriConfig : WebSecurityConfigurerAdapter() {
+        companion object {
+            var DECODER: JwtDecoder = mock(JwtDecoder::class.java)
+        }
+
+        override fun configure(http: HttpSecurity) {
+            http {
+                authorizeRequests {
+                    authorize(anyRequest, authenticated)
+                }
+                oauth2ResourceServer {
+                    jwt {
+                        jwkSetUri = "https://jwk-uri"
+                        jwtDecoder = DECODER
+                    }
+                }
+            }
+        }
+    }
 }