Too many arguments for public open fun http() - spring-boot

I'm following this tutorial to implement a authentication system in Kotlin using Spring Boot
The code works nicely until this part:
#Configuration
#EnableWebSecurity
class MultiHttpSecurityConfig {
#Bean
public fun userDetailsService(): UserDetailsService {
val users: User.UserBuilder = User.withDefaultPasswordEncoder()
val manager = InMemoryUserDetailsManager()
manager.createUser(users.username("user").password("password").roles("USER").build())
manager.createUser(users.username("admin").password("password").roles("USER","ADMIN").build())
return manager
but in the next part i receive the following error and cant import anything:
#Order(1)
#Bean
open fun apiFilterChain(http: HttpSecurity): SecurityFilterChain {
http {
securityMatcher("/api/**")
authorizeRequests {
authorize(anyRequest, hasRole("ADMIN"))
}
httpBasic { }
}
return http.build()
}
#Bean
open fun formLoginFilterChain(http: HttpSecurity): SecurityFilterChain {
http {
authorizeRequests {
authorize(anyRequest, authenticated)
}
formLogin { }
}
return http.build()
}
}
Am I missing something? Is something necessary besides Spring Security dependency?

Try to add import :
import org.springframework.security.config.web.server.invoke

Related

What is the replacement for TokenStore, TokenServices and JwtAccessTokenConverter in Spring Security 5

I am upgrading Spring Boot from 2.3.12.RELEASE to 2.7.7 in my Kotlin project and found out that I have to change the code for Spring Security because Spring Security OAuth that was used in this project is no longer supported and has to be migrated to Spring Security 5+. I have this configuration that I want to migrate (some business data omitted):
#Configuration
#EnableResourceServer
#EnableGlobalMethodSecurity(prePostEnabled = true)
class ResourceServerConfig : ResourceServerConfigurerAdapter() {
#Value("...")
private val claimAud: String? = null
#Value("...")
private val urlJwk: String? = null
override fun configure(resources: ResourceServerSecurityConfigurer) {
resources.tokenStore(tokenStore())
resources.resourceId(claimAud)
}
#Bean
fun tokenStore(): TokenStore {
logger.info("JWK settings resource config: $urlJwk")
return JwkTokenStore(urlJwk, createJwtAccessTokenConverter())
}
#Throws(Exception::class)
override fun configure(http: HttpSecurity) {
http.anonymous().and().cors(withDefaults())
.authorizeRequests()
.mvcMatchers(BASE_PATH_PATTERN).permitAll()
.mvcMatchers(API_PATH_PATTERN).permitAll()
.mvcMatchers(ADMIN_PATH_PATTERN).authenticated()
}
#Bean
fun securityEvaluationContextExtension(): SecurityEvaluationContextExtension {
return SecurityEvaluationContextExtension()
}
#Bean
#Primary
fun tokenServices(): DefaultTokenServices {
val defaultTokenServices = DefaultTokenServices()
defaultTokenServices.setTokenStore(tokenStore())
return defaultTokenServices
}
#Bean
fun createJwtAccessTokenConverter(): JwtAccessTokenConverter? {
val converter = JwtAccessTokenConverter()
converter.accessTokenConverter = MyTokenConverter()
return converter
}
#Component
class MyTokenConverter : DefaultAccessTokenConverter(), JwtAccessTokenConverterConfigurer {
override fun extractAuthentication(claims: Map<String?, *>?): OAuth2Authentication {
val authentication = super.extractAuthentication(claims)
authentication.details = claims
return authentication
}
override fun configure(converter: JwtAccessTokenConverter) {
converter.accessTokenConverter = this
}
}
I don't know what to do with those methods related to TokenStore, TokenServices or TokenConverter, how to replace them.
I consulted the migrtation guide https://github.com/spring-projects/spring-security/wiki/OAuth-2.0-Migration-Guide but it seems that it lacks a lot of information, there is no specific guide anywhere actually for how to replace those components that I mentioned in my question.

Can not get user info with Spring Security SAML WITHOUT Spring Boot

I´m working on SAML integration in an older project but I can´t get the user information.
I've guided me with the response of this question:
https://stackoverflow.com/questions/70275050/spring-security-saml-identity-metadata-without-spring-boot
The project has these versions:
spring framework 5.3.24
spring security 5.6.10
opensaml 3.4.6
This is my code:
#Configuration
public class SAMLSecurityConfig {
private static final String URL_METADATA = "https://auth-dev.mycompany.com/app/id/sso/saml/metadata";
#Bean("samlRegistration")
public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() {
RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistrations.fromMetadataLocation(URL_METADATA)
.registrationId("id")
.build();
return new InMemoryRelyingPartyRegistrationRepository(relyingPartyRegistration);
}
}
#EnableWebSecurity
public class WebSecurity {
#Configuration
#Order(2)
public static class SAMLSecurityFilter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.saml2Login(Customizer.withDefaults())
.antMatcher("/login/assertion")
.authorizeRequests()
.anyRequest()
.authenticated();
}
}
}
#Controller("loginController")
public class BoCRLoginController {
#RequestMapping(value = "/login/assertion", method = {RequestMethod.POST},
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<String> assertLoginData(#AuthenticationPrincipal Saml2AuthenticatedPrincipal principal) {
System.out.println(principal); //here I get a null
return new ResponseEntity<>(HttpStatus.OK);
}
}
Once I did the login on okta the class: Saml2AuthenticatedPrincipal comes null value.
Could you help me to know why I received null value on the object Saml2AuthenticatedPrincipal where suppose have to receive the user information?

Spring in Kotlin: from 5.3 to 6.0 security Configuration

I'm facing lots of issues in doing Spring security configurations that I used to have in v5.3 applied in v6.
This is the file I had
#Configuration
#EnableWebSecurity
class WebSecurityConfiguration : WebSecurityConfigurerAdapter() {
#Autowired
lateinit var service: UserService
/**
* Will be resolved into: WebSecurityEntryPoint injected instance.
*/
#Autowired
lateinit var unauthorizedHandler: AuthenticationEntryPoint
#Autowired
lateinit var successHandler: WebSecurityAuthSuccessHandler
#Autowired
override fun configure(auth: AuthenticationManagerBuilder) {
auth.authenticationProvider(authenticationProvider())
}
override fun configure(http: HttpSecurity?) {
http
?.csrf()?.disable()
?.exceptionHandling()
?.authenticationEntryPoint(unauthorizedHandler)
?.and()
?.authorizeRequests()
/**
* Access to Notes and Todos API calls is given to any authenticated system user.
*/
?.antMatchers("/notes")?.authenticated()
?.antMatchers("/notes/**")?.authenticated()
?.antMatchers("/todos")?.authenticated()
?.antMatchers("/todos/**")?.authenticated()
/**
* Access to User API calls is given only to Admin user.
*/
?.antMatchers("/users")?.hasAnyAuthority("ADMIN")
?.antMatchers("/users/**")?.hasAnyAuthority("ADMIN")
?.and()
?.formLogin()
?.successHandler(successHandler)
?.failureHandler(SimpleUrlAuthenticationFailureHandler())
?.and()
?.logout()
}
#Bean
fun authenticationProvider(): DaoAuthenticationProvider {
val authProvider = DaoAuthenticationProvider()
authProvider.setUserDetailsService(service)
authProvider.setPasswordEncoder(encoder())
return authProvider
}
#Bean
fun encoder(): PasswordEncoder = BCryptPasswordEncoder(11)
#Bean
fun accessDecisionManager(): AccessDecisionManager {
val decisionVoters = Arrays.asList(
WebExpressionVoter(),
RoleVoter(),
AuthenticatedVoter()
)
return UnanimousBased(decisionVoters)
}
}
I used the documentation in Spring.io
https://spring.io/blog/2022/02/21/spring-security-without-the-websecurityconfigureradapter
and I'm just hitting the wall since then. their documentation is not helpful and the new dependencies aren't working the same.
how can this be done now?
P.S: I often keep getting this error:
Caused by: java.lang.ClassNotFoundException: org.springframework.security.core.context.DeferredSecurityContext
which i couldn't find anywhere
Okey... I managed to solve it this way
first I had to add the security dependency for v6
implementation("org.springframework.security:spring-security-core:6.0.1")
and I made the Security Configuration this way
#Configuration
#EnableWebSecurity
class SecurityConfiguration(
private val userService: UserService,
private val unauthorizedHandler: AuthenticationEntryPoint,
private val successHandler: WebSecurityAuthSuccessHandler
) {
/**
* Will be resolved into: WebSecurityEntryPoint injected instance.
*/
#Bean
fun myPasswordEncoder(): PasswordEncoder {
return BCryptPasswordEncoder(11)
}
#Primary
fun configureAuthentication(auth: AuthenticationManagerBuilder): AuthenticationManagerBuilder {
return auth.authenticationProvider(authenticationProvider())
}
#Bean
fun authenticationProvider(): DaoAuthenticationProvider {
val authProvider = DaoAuthenticationProvider()
authProvider.setUserDetailsService(userService)
authProvider.setPasswordEncoder(myPasswordEncoder())
return authProvider
}
#Bean
fun accessDecisionManager(): AccessDecisionManager {
val decisionVoter = listOf(
WebExpressionVoter(),
RoleVoter(),
AuthenticatedVoter()
)
return UnanimousBased(decisionVoter)
}
#Bean
fun configureHttpSecurity(httpSecurity: HttpSecurity): SecurityFilterChain {
httpSecurity
.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.authorizeHttpRequests()
/**
* Access to Notes and Todos API calls is given to any authenticated system user.
*/
.requestMatchers("/notes").authenticated()
.requestMatchers("/notes/**").authenticated()
.requestMatchers("/todos").authenticated()
.requestMatchers("/todos/**").authenticated()
/**
* Access to User API calls is given only to Admin user.
*/
.requestMatchers("/users").hasAnyAuthority("ADMIN")
.requestMatchers("/users/**").hasAnyAuthority("ADMIN")
.and()
.formLogin()
.successHandler(successHandler)
.failureHandler(SimpleUrlAuthenticationFailureHandler())
.and()
.logout()
return httpSecurity.build()
}
}

Spring Security without WebSecurityConfiguererAdapter, register two AuthenticationProvider

Since the deprication of WebSecurityConfiguererAdapter, I am not sure on how to implement my two custom AuthenticationProvider classes. Everything works in case I only use one of the AuthenticationProviders, but having two prevents both of them to function. I tried giving them #Order annotations but that doesn't work either. How would I register my custom AuthenticationProviders to make them work along each other and being called when the class defined in its support method matches. By the way, I'am a SpringBoot noob ;)
#Component
class AuthenticationService(
private val authenticationManager: AuthenticationManager,
) {
fun login(loginDto: LoginDto): Boolean {
authenticationManager.authenticate(
Token2(
loginDto.username, loginDto.password
)
)
return true
}
}
#Configuration
class ProdSecurityConfiguration {
#Bean
fun passwordEncoder(): PasswordEncoder {
return BCryptPasswordEncoder()
}
#Bean
fun authenticationManager(authenticationConfiguration: AuthenticationConfiguration): AuthenticationManager {
return authenticationConfiguration.authenticationManager
}
#Bean
fun filterChain(http: HttpSecurity): SecurityFilterChain {
http.csrf().disable().cors().disable()
http.authorizeRequests()
.antMatchers("/login", "/register").permitAll().anyRequest().authenticated().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
return http.build()
}
}
#Component
class CredentialsAuthProvider : AuthenticationProvider {
override fun authenticate(authentication: Authentication): Authentication {
return UsernamePasswordAuthenticationToken(
"myUser#mailbox.org", "password"
)
}
override fun supports(authentication: Class<*>?): Boolean {
return authentication == Token1::class.java
}
}
#Component
class CredentialsAuthProvider2 : AuthenticationProvider {
override fun authenticate(authentication: Authentication): Authentication {
return UsernamePasswordAuthenticationToken(
"myUser#mailbox.org", "password"
)
}
override fun supports(authentication: Class<*>?): Boolean {
return authentication == Token2::class.java
}
}
I removed the #Component annotation from my custom AuthenticationProviders, I created #Beans in my SecurityConfiguration class for each custom AuthenticationProvider where I directly call their constructor instead of using springs DI. Then used them within my AthenticationManager Bean where I return a ProviderManager.
Code snippets for explanation:
#Configuration
class ProdSecurityConfiguration {
#Bean
fun credentialsAuthProvider(): AuthenticationProvider {
return CredentialsAuthProvider()
}
#Bean
fun credentialsAuthProvider2(): AuthenticationProvider {
return CredentialsAuthProvider2()
}
#Bean
fun authenticationManager(): AuthenticationManager {
return ProviderManager(listOf(credentialsAuthProvider(), credentialsAuthProvider2()))
}
#Bean
fun filterChain(http: HttpSecurity): SecurityFilterChain {
http.csrf().disable().cors().disable()
http.authorizeRequests()
.antMatchers("/login", "/register").permitAll().anyRequest().authenticated().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
return http.build()
}
}

Spring Security Google OAuth2 authorizationUri became domain after deployed on aws

So I am current testing with spring securtiy with google oauth.
it works fine, when trying to login with google through
/oauth2/authorization/google
on localhost
but when i deployed the application on tomcat on aws ec2 instance,
the authorizationuri became sometime like below
when running on localhost:
https://accounts.google.com/o/oauth2/v2/auth/oauthchooseaccount? ............
when running on aws ec2 domain:
http://{domain}:{port}/o/oauth2/v2/auth? ..........
but when i manually replace the http domain and port with https://accounts.google.com/
it directs me to google login page and are able to complete the login successfully.
So i wonder if there is any part of the setting ive being missing or did wrong that cause it to happen.
Thanks in advance.
the complete code for spring security setting is like below
#Configuration
#EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
#Autowired
private lateinit var oidUserSer:OidUserService
#Bean
fun clientRegistrationRepository(): ClientRegistrationRepository {
return InMemoryClientRegistrationRepository(googleClientRegistration())
}
private fun googleClientRegistration(): ClientRegistration {
return ClientRegistration.withRegistrationId("google")
.clientId("clientId")
.clientSecret("secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("https://{domain:port}/login/oauth2/code/{registrationId}")
.scope("openid", "profile", "email", "address", "phone")
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.userNameAttributeName(IdTokenClaimNames.SUB)
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
.clientName("Google")
.build()
}
#Bean
fun customAuthorizationRequestResolver(): CustomAuthorizationRequestResolver {
val repo = InMemoryClientRegistrationRepository(
CommonOAuth2Provider.GOOGLE.getBuilder("google")
.clientName("Google")
.clientId("61770666483-dj64uabnia7tq2g0kri2ajrb7sl21r3t.apps.googleusercontent.com")
.clientSecret("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")
.redirectUri("https://{domain:port}/login/oauth2/code/{registrationId}")
.build()
)
val baseUri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI
val customizeAuthorizationRequest= CustomAuthorizationRequestResolver(repo,baseUri)
return customizeAuthorizationRequest
}
/**
* セキュリティの有効範囲設定
*/
#Override
override fun configure(web: WebSecurity) {
// org.springframework.security.web.firewall.RequestRejectedException:
// The request was rejected because the URL contained a potentially malicious String ";"
// というエラーログがコンソールに出力されるため、下記を追加
val firewall = DefaultHttpFirewall()
web.httpFirewall(firewall)
web.ignoring().antMatchers(
"/img/**",
"/css/**",
"/js/**",
"/libs/**"
)
}
#Override
#Throws(Exception::class)
override fun configure(http: HttpSecurity) {
http.exceptionHandling()
.authenticationEntryPoint(LoginUrlAuthenticationEntryPoint("/login"));
http.oauth2Login()
.loginPage("/login")
.defaultSuccessUrl("/login-success", true)
.userInfoEndpoint().oidcUserService(oidUserSer).
and()
.failureUrl("/login?error")
.authorizationEndpoint()
.authorizationRequestResolver(customAuthorizationRequestResolver())
http.logout()
//.logoutRequestMatcher(AntPathRequestMatcher("/logout**"))
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout")
.logoutSuccessHandler(CustomLogoutSuccessHandler())
//.invalidateHttpSession(true)
//セッション設定
http.sessionManagement().
invalidSessionUrl("/login?timeout=true")
}
}
class CustomAuthorizationRequestResolver(repo: ClientRegistrationRepository?,
authorizationRequestBaseUri: String?):OAuth2AuthorizationRequestResolver{
private var defaultResolver:DefaultOAuth2AuthorizationRequestResolver? = DefaultOAuth2AuthorizationRequestResolver(repo, authorizationRequestBaseUri)
override fun resolve(request: HttpServletRequest): OAuth2AuthorizationRequest? {
val authorizationRequest:OAuth2AuthorizationRequest? =
this.defaultResolver?.resolve(request)
return customAuthorizationRequest(authorizationRequest)
}
override fun resolve(request: HttpServletRequest?, clientRegistrationId: String?): OAuth2AuthorizationRequest? {
val authorizationRequest = this.defaultResolver?.resolve(
request, clientRegistrationId);
return authorizationRequest?.let { customAuthorizationRequest(it) }
}
private fun customAuthorizationRequest(authorizationRequest: OAuth2AuthorizationRequest?): OAuth2AuthorizationRequest? {
var param:OAuth2AuthorizationRequest? = null
if(authorizationRequest!=null){
val additionalParameter: LinkedHashMap<String,Any> = LinkedHashMap(authorizationRequest!!.additionalParameters)
additionalParameter.put("prompt","select_account+consent")
param = OAuth2AuthorizationRequest.from(authorizationRequest).additionalParameters(additionalParameter).build()
}
return param
}
}

Resources