Skip to content

Commit 5c8fb25

Browse files
nmck257eleftherias
authored andcommitted
Add AuthenticationDetailsSource to OAuth2 Login Kotlin DSL
Closes gh-9838
1 parent b1612b1 commit 5c8fb25

File tree

2 files changed

+66
-0
lines changed

2 files changed

+66
-0
lines changed

config/src/main/kotlin/org/springframework/security/config/web/servlet/OAuth2LoginDsl.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.security.config.web.servlet
1818

19+
import org.springframework.security.authentication.AuthenticationDetailsSource
1920
import org.springframework.security.config.annotation.web.HttpSecurityBuilder
2021
import org.springframework.security.config.annotation.web.builders.HttpSecurity
2122
import org.springframework.security.config.web.servlet.oauth2.login.AuthorizationEndpointDsl
@@ -28,6 +29,7 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio
2829
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository
2930
import org.springframework.security.web.authentication.AuthenticationFailureHandler
3031
import org.springframework.security.web.authentication.AuthenticationSuccessHandler
32+
import javax.servlet.http.HttpServletRequest
3133

3234
/**
3335
* A Kotlin DSL to configure [HttpSecurity] OAuth 2.0 login using idiomatic Kotlin code.
@@ -59,6 +61,7 @@ class OAuth2LoginDsl {
5961
var failureUrl: String? = null
6062
var loginProcessingUrl: String? = null
6163
var permitAll: Boolean? = null
64+
var authenticationDetailsSource: AuthenticationDetailsSource<HttpServletRequest, *>? = null
6265

6366
private var defaultSuccessUrlOption: Pair<String, Boolean>? = null
6467
private var authorizationEndpoint: ((OAuth2LoginConfigurer<HttpSecurity>.AuthorizationEndpointConfig) -> Unit)? = null
@@ -221,6 +224,7 @@ class OAuth2LoginDsl {
221224
tokenEndpoint?.also { oauth2Login.tokenEndpoint(tokenEndpoint) }
222225
redirectionEndpoint?.also { oauth2Login.redirectionEndpoint(redirectionEndpoint) }
223226
userInfoEndpoint?.also { oauth2Login.userInfoEndpoint(userInfoEndpoint) }
227+
authenticationDetailsSource?.also { oauth2Login.authenticationDetailsSource(authenticationDetailsSource) }
224228
}
225229
}
226230
}

config/src/test/kotlin/org/springframework/security/config/web/servlet/OAuth2LoginDslTests.kt

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,15 @@
1616

1717
package org.springframework.security.config.web.servlet
1818

19+
import io.mockk.every
20+
import io.mockk.mockkObject
21+
import io.mockk.verify
1922
import org.junit.jupiter.api.Test
2023
import org.junit.jupiter.api.extension.ExtendWith
2124
import org.springframework.beans.factory.annotation.Autowired
2225
import org.springframework.context.annotation.Bean
2326
import org.springframework.context.annotation.Configuration
27+
import org.springframework.security.authentication.AuthenticationDetailsSource
2428
import org.springframework.security.config.annotation.web.builders.HttpSecurity
2529
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
2630
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
@@ -29,10 +33,16 @@ import org.springframework.security.config.test.SpringTestContext
2933
import org.springframework.security.config.test.SpringTestContextExtension
3034
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository
3135
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository
36+
import org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository
37+
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest
38+
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames
39+
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf
3240
import org.springframework.test.web.servlet.MockMvc
3341
import org.springframework.test.web.servlet.get
42+
import org.springframework.test.web.servlet.post
3443
import org.springframework.web.bind.annotation.GetMapping
3544
import org.springframework.web.bind.annotation.RestController
45+
import javax.servlet.http.HttpServletRequest
3646

3747
/**
3848
* Tests for [OAuth2LoginDsl]
@@ -113,6 +123,58 @@ class OAuth2LoginDslTests {
113123
}
114124
}
115125

126+
@Test
127+
fun `oauth2Login when custom authentication details source then used`() {
128+
this.spring
129+
.register(CustomAuthenticationDetailsSourceConfig::class.java, ClientConfig::class.java)
130+
.autowire()
131+
mockkObject(CustomAuthenticationDetailsSourceConfig.AUTHENTICATION_DETAILS_SOURCE)
132+
every {
133+
CustomAuthenticationDetailsSourceConfig.AUTHENTICATION_DETAILS_SOURCE.buildDetails(any())
134+
} returns Any()
135+
mockkObject(CustomAuthenticationDetailsSourceConfig.AUTHORIZATION_REQUEST_REPOSITORY)
136+
every {
137+
CustomAuthenticationDetailsSourceConfig.AUTHORIZATION_REQUEST_REPOSITORY.removeAuthorizationRequest(any(), any())
138+
} returns OAuth2AuthorizationRequest.authorizationCode()
139+
.authorizationUri("/")
140+
.clientId("clientId")
141+
.redirectUri("/")
142+
.attributes { attributes -> attributes[OAuth2ParameterNames.REGISTRATION_ID] = "google" }
143+
.build()
144+
145+
this.mockMvc.post("/login/oauth2/code/google") {
146+
param(OAuth2ParameterNames.CODE, "code")
147+
param(OAuth2ParameterNames.STATE, "state")
148+
with(csrf())
149+
}
150+
.andExpect {
151+
status { is3xxRedirection() }
152+
}
153+
154+
verify(exactly = 1) { CustomAuthenticationDetailsSourceConfig.AUTHENTICATION_DETAILS_SOURCE.buildDetails(any()) }
155+
}
156+
157+
@EnableWebSecurity
158+
open class CustomAuthenticationDetailsSourceConfig : WebSecurityConfigurerAdapter() {
159+
160+
companion object {
161+
val AUTHENTICATION_DETAILS_SOURCE: AuthenticationDetailsSource<HttpServletRequest, *> =
162+
AuthenticationDetailsSource<HttpServletRequest, Any> { Any() }
163+
val AUTHORIZATION_REQUEST_REPOSITORY = HttpSessionOAuth2AuthorizationRequestRepository()
164+
}
165+
166+
override fun configure(http: HttpSecurity) {
167+
http {
168+
oauth2Login {
169+
authenticationDetailsSource = AUTHENTICATION_DETAILS_SOURCE
170+
authorizationEndpoint {
171+
authorizationRequestRepository = AUTHORIZATION_REQUEST_REPOSITORY
172+
}
173+
}
174+
}
175+
}
176+
}
177+
116178
@Configuration
117179
open class ClientConfig {
118180
@Bean

0 commit comments

Comments
 (0)