Part 2- Step by Step Migration to Spring Security 6.2.x

Serdar A.
3 min readApr 1, 2024

--

Hello everyone

https://miro.medium.com/v2/resize:fit:1400/1*_28dQ7oXKXf9PSLkUirzgQ.png

In the previous part, I talked about my experiences with updating to Spring 3.x. (https://medium.com/@lastjavabuilder/step-by-step-migration-to-spring-3-x-jakarta-security-hibernate-6-openapi-cache-925401fa7b2c)

In this article, I will share my experiences with the configurations that were updated and deprecated with Spring Security 6.2.x while updating the project with Spring boot 3.2.x.

Lets start :)

While I updated the Spring Boot project to 3.2.4, I also updated the spring security-related dependencies to 6.2.3. I also updated the jsonwebtoken related dependencies (jjwt-api, jjwt-impl, jjwt-jackson) to version 0.12.5.

When I maven update-clean-installed the project, many methods were deprecated and error on both the spring security side and the JWT lib side.

In this article, I will share code blocks on how I solved these problems.

  1. Let’s start by updating the project to spring boot 3.2.4.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.4</version>
<relativePath/>
</parent>

2. Let’s update the dependencies related to spring security to 6.2.3, either externally or with the security library of spring boot.

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

<!-- or external definitation -->

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>6.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>6.2.3</version>
</dependency>

<!-- etc definitation -->

3. Let’s update the version of jjwt-api, jjwt-impl, jjwt-jackson dependencies of the io.jsonwebtoken library to 0.12.5.

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.12.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.12.5</version>
<scope>runtime</scope>
</dependency>

When you do a maven update on the project, you will first see that there is an error in the libraries belonging to jsonwebtoken. Let’s start by solving this first.

  • create token with Jwts (example)

Old definition

Jwts
.builder()
.setClaims(extraClaims)
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(new Date(System.currentTimeMillis() + 1000 * 60 * 24)))
.signWith(yourKey, SignatureAlgorithm.HS256) // SignatureAlgorithm.HS256 or etc SignatureAlgorithm enum
.compact();

New definition

Jwts
.builder()
.claims(extraClaims)
.subject(userDetails.getUsername())
.issuedAt(new Date(System.currentTimeMillis()))
.expiration(new Date(System.currentTimeMillis() + 1000 * 60 * 24))
.signWith(yourPrivateKey)
.compact();
  • get Claims (example)

Old definition

 Jwts
.parserBuilder()
.setSigningKey(yourKey)
.build()
.parseClaimsJws(yourToken)
.getBody();

New definition

Jwts
.parser()
.verifyWith(yourSecretKey)
.build()
.parseSignedClaims(yourToken)
.getPayload();
  • get userId from token (example)

Old definition

Claims claims = Jwts
.parserBuilder()
.setSigningKey(yourPublicKey)
.build()
.parseClaimsJws(yourToken)
.getBody();

Long userId = Long.parseLong(claims.getSubject());

New definition

Claims claims = Jwts
.parser()
.verifyWith(yourPublicKey)
.build()
.parseSignedClaims(yourToken)
.getPayload();

Long userId = Long.parseLong(claimsJws.getSubject());
  • validate token (example)

Old definition

Jwts
.parserBuilder()
.setSigningKey(yourPublicKey)
.build()
.parseClaimsJws(yourToken);

New definition

 Jwts
.parser()
.verifyWith(yourPublicKey)
.build()
.parseSignedClaims(yourToken);

After solving the jsonwebtoken side, the main point is to configure spring security.After updating to Spring security version 6.2.x, you will see that many methods are deprecated.

Let’s start solving this situation

Old definition (example)

private static final String[] AUTH_WHITELIST = {
"/v3/api-docs/**",
"/swagger-resources/**",
"/swagger-ui/**",
"/swagger-ui.html",
"/actuator/**",
"/login",
"/logout",
"/auth/**",
"/oauth2/**",
"/error",
"/favicon.ico",
"/**/*.png",
"/**/*.gif",
"/**/*.svg",
"/**/*.jpg",
"/**/*.html",
"/**/*.css",
"/**/*.js"
};



@Bean
public SecurityFilterChain filterChain( HttpSecurity http) throws Exception {
http.
cors().configurationSource(yourCorsConfiguration())
.and()
.headers().xssProtection().disable().and()
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.formLogin().disable()
.httpBasic().disable()
.exceptionHandling()
.authenticationEntryPoint(yourAuthenticationEntryPoint())
.and()
.authorizeHttpRequests(auth -> auth
.requestMatchers(AUTH_WHITELIST)
.permitAll()
.anyRequest()
.authenticated())
.oauth2Login()
.clientRegistrationRepository(yourClientRegistrationRepository())
.authorizationEndpoint()
.authorizationRequestResolver(yourAuthorizationRequestResolver())
.baseUri("yourBaseUri")
.authorizationRequestRepository(yourAuthorizationRequestRepository())
.and()
.redirectionEndpoint()
.baseUri("yourRedirectBaseUri")
.and()
.tokenEndpoint()
.accessTokenResponseClient(yourAccessTokenResponseClient())
.and()
.userInfoEndpoint()
.userService(yourUserService())
.and()
.successHandler(yourAuthSuccessHandler)
.failureHandler(yourAuthFailureHandler)
.and()
.logout()
.disable()
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(yourJwtAuthConverter)
.and()
.and()

.addFilterBefore(yourJwtAuthFilter, UsernamePasswordAuthenticationFilter.class);

return http.build();

}

New definition

private static final String[] AUTH_WHITELIST = {
"/v3/api-docs/**",
"/swagger-resources/**",
"/swagger-ui/**",
"/swagger-ui.html",
"/actuator/**",
"/jwtcheck",
"/login",
"/logout",
"/auth/**",
"/oauth2/**",
"/error",
"/favicon.ico",
"/**/*.png",
"/**/*.gif",
"/**/*.svg",
"/**/*.jpg",
"/**/*.html",
"/**/*.css",
"/**/*.js"
};

@Bean
public SecurityFilterChain filterChain( HttpSecurity http) throws Exception {

http
.csrf(AbstractHttpConfigurer::disable)
.cors(httpSecurityCorsConfigurer -> httpSecurityCorsConfigurer.configurationSource(yourCorsConfiguration()))
.headers(httpSecurityHeadersConfigurer -> httpSecurityHeadersConfigurer.xssProtection(xXssConfig -> xXssConfig.disable()))
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.formLogin(httpSecurityFormLoginConfigurer -> httpSecurityFormLoginConfigurer.disable())
.httpBasic(httpSecurityHttpBasicConfigurer -> httpSecurityHttpBasicConfigurer.disable())
.exceptionHandling((exception) -> exception.authenticationEntryPoint(yourAuthenticationEntryPoint))
.authorizeHttpRequests(
authorizationManagerRequestMatcherRegistry ->
authorizationManagerRequestMatcherRegistry
.requestMatchers(AUTH_WHITELIST)
.permitAll().anyRequest().authenticated())
.oauth2Login(httpSecurityOAuth2LoginConfigurer ->
httpSecurityOAuth2LoginConfigurer
.clientRegistrationRepository(yourClientRegistrationRepository())
.authorizationEndpoint(authorizationEndpointConfig ->
authorizationEndpointConfig
.authorizationRequestResolver(yourAuthorizationRequestResolver())
.baseUri("yourBaseUri")
.authorizationRequestRepository(yourAuthorizationRequestRepository()))
.redirectionEndpoint(redirectionEndpointConfig -> redirectionEndpointConfig.baseUri("yourRedirectBaseUri"))
.tokenEndpoint(tokenEndpointConfig -> tokenEndpointConfig.accessTokenResponseClient(yourAccessTokenResponseClient()))
.userInfoEndpoint(userInfoEndpointConfig -> userInfoEndpointConfig.userService(yourUserService()))
.successHandler(yourAuthSuccessHandler)
.failureHandler(yourAuthFailureHandler)
)
.logout(httpSecurityLogoutConfigurer -> httpSecurityLogoutConfigurer.disable())
.oauth2ResourceServer(httpSecurityOAuth2ResourceServerConfigurer ->
httpSecurityOAuth2ResourceServerConfigurer.jwt(jwtConfigurer ->
jwtConfigurer.jwtAuthenticationConverter(yourJwtAuthConverter())))
.addFilterBefore(yourJwtAuthFilter,UsernamePasswordAuthenticationFilter.class);

return http.build();

}

The .and() definitions between config elements in the old configuration have been removed. It has been replaced with lambda expressions.

Frankly, it was difficult at first for those who were used to the old structure, but switching between config structures with .and() was also more complicated.

Thank you for reading.

--

--

Serdar A.

Senior Software Developer & Architect at Havelsan Github: https://github.com/serdaralkancode #Java & #Spring & #BigData & #React & #Microservice