September 3, 2026

Json Web Token – How to Secure REST API Using JWT in Spring Boot

Learn how to Secure REST API Using JWT in Spring Boot with SecurityFilterChain, public/private keys, JwtDecoder, JwtEncoder, and a token endpoint.

TL;DR

  • Configure Spring Security to require authentication for REST API requests.

  • Use an OAuth2 Resource Server with JWT authentication.

  • Generate a public/private RSA key pair for signing and validating JWTs.

  • Configure JwtDecoder and JwtEncoder using the RSA keys.

  • Create a TokenService and /token endpoint to generate JWTs for authenticated users.

This is a tutorial on how to implement Json Web Token authentication for a REST API in Spring Boot using public and private keys. In this approach, we would be using the SecurityFilterChain bean rather than extending the WebSecurityConfigurerAdapter.

Then we would be creating a self-signed JWT.

  1. Getting Started With Json Web Token( JWT)
  2. Create and Configure the SecurityFilterChain Bean
  3. Create a Test UserManager Bean
  4. Configure the ResourceServer
  5. Create a Public/Private Key Pair
  6. Create some Configuration to Externalize the Keys
  7. Create the JwtDecoder and JwtEncoder
  8. Create the TokenService
  9. Implement the “/token” Endpoint

Video Tutorial – The New JWT – How to Secure REST API Using Json Web Token in Spring Boot

1. Getting Started With JWT

We would start with a basic REST API. Then we would see how to secure an endpoint using Json Web Token.

You will need the following dependencies:

  • spring-boot-starter-oauth2-resource-server
  • spring-boot-starter-web
  • spring-boot-configuration-processor

How it works

  • For the first time, the user logs in with his username and password.
  • At successful authentication (login), the server generates and returns back a token (jwt) to the user
  • For subsequent requests, the token must be included in the request header

 

2. Create and Configure the SecurityFilterChain Bean

1. Create the security configuration file (name it SecurityConfig.java) in the config directory.

2. Annotate this class with @Configuration and @EnableWebSecurity

3. Create the SecurityFilterChain bin. It takes HttpSecurity as parameter, builds and returns the SecurityFilterChain.  The code below shows what is returned:

return httpSecurity
        .csrf(AbstractHttpConfigurer::disable)
        .authorizeHttpRequests(auth -> auth
                .anyRequest().authenticated()
        )
        .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
        .httpBasic(Customizer.withDefaults())
        .build();

 

3. Create a Test User Bean

For this tutorial, we would create a user in memory. In the following tutorial, we would implemented UserDetailsService.

1. Create the InMemoryUserDetailsManager bean as shown below:

@Bean
public InMemoryUserDetailsManager manager(){
    return new InMemoryUserDetailsManager(
            User.withUsername("kindson")
                    .password("{noop}password")
                    .authorities("read")
                    .build()
    );
}

 

4. Configure the ResourceServer

An OAuth2 resource server in Spring is a server that protects resources (e.g., APIs) and ensures that requests are authenticated using access tokens, typically issued by an OAuth2 authorization server.

We would have to tell Spring that our service is an OAuth2 resource server.

1. Add this line just before the sessionManagement line in the SecurityFilterChain bean

.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults())) 

 

2. Run the application. Note that you will have the exception below:

Parameter 0 of method setFilterChains in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration required a bean of type 'org.springframework.security.oauth2.jwt.JwtDecoder' that could not be found.

To create a JwtDecoder, we would need to create a public/private key pair.

 

5. Create a Public/Private Key Pair

We would use the openssl tool in Mac to create the keys

1. Create a folder called certs in the resources folder

2. Navigate to this certs directory in the terminal and run the following command

openssl genrsa -out keypair.pem 2048

 

3. Run the following command to extract the public key.

openssl rsa -in keypair.pem -pubout -out public.pem

 

4. Run the following command to create a private key in the required format: pkcs8

openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair.pem -out private.pem

 

5. Delete the keypair.pem

 

6. Create Some Configuration to Externalize the Keys

1. Create a  record and call it RsaKeyProperties. This would have two fields as shown below:

@ConfigurationProperties(prefix = "rsa")
public record RsaKeyProperties(RSAPublicKey publicKey, RSAPrivateKey privateKey) {
}

 

2. Set the values in the application.properties file

rsa.private-key=classpath:certs/private.pem
rsa.public-key=classpath:certs/public.pem

 

3. Annotate the main class with @EnableConfigurationProperties like so

@EnableConfigurationProperties(RsaKeyProperties.class)

 

7. Create the JwtDecoder and JwtEncoder Bean

We would need the keys to be able to create a JwtDecoder. This would be used to decipher the token

1. Inject the RsaKeyProperties into the SecurityConfig as shown:

private final RsaKeyProperties properties;

public SecurityConfig(RsaKeyProperties properties) {
    this.properties = properties;
}

 

2. Defined the decoder using the keys:

@Bean
JwtDecoder jwtDecoder() {
    return NimbusJwtDecoder.withPublicKey(properties.publicKey()).build();
}

 

3. Create the JwtEncoder Bean

@Bean
JwtEncoder jwtEncoder(){
    JWK jwk = new RSAKey.Builder(rsaKeyProperties.publicKey()).privateKey(rsaKeyProperties.privateKey()).build();
    JWKSource<SecurityContext> jwkSource = new ImmutableJWKSet<>(new JWKSet(jwk));
    return new NimbusJwtEncoder(jwkSource);
}

 

8. Create the TokenService

We would need a service that contains the generateToken method. The method would create a token and encode it using the JwtEncoder.

1. Create the TokenService inside the service package

2. Get a reference to the JwtEncoder bean

3. Create the method as shown below:

public String generateToken(Authentication authentication){
    Instant now = Instant.now();
    String scope = authentication.getAuthorities().stream()
            .map(GrantedAuthority::getAuthority)
            .collect(Collectors.joining(" "));
    JwtClaimsSet claimsSet = JwtClaimsSet.builder()
            .issuer("self")
            .issuedAt(now)
            .expiresAt(now.plus(1, ChronoUnit.HOURS))
            .claim("scope", scope)
            .build();
    return this.jwtEncoder.encode(JwtEncoderParameters.from(claimsSet)).getTokenValue();
}

Note: See the video tutorial to understand each section of the code

 

9. Create the AuthController

We would need the controller that exposes an endpoint of “/token”. This would call the createToken service and return the created token.

1. Create the AuthController.java file in the controller package

2. Inject the TokenService.

3. Optionally create a Logger to log debug messages.

4. Write the getToken controller method as shown below:

@PostMapping("/token")
public String getToken(Authentication authentication){
    LOGGER.debug("Token requested form user: {}", authentication.getName());
    String token = tokenService.generateToken(authentication);
    LOGGER.debug("Token granted {}", token);
    return token;    }
}

 

Video Tutorial – The New JWT – How to Secure REST API Using Json Web Token in Spring Boot

FAQs

What is JWT used for in a Spring Boot REST API?

JWT allows a REST API to authenticate users using a signed token that can be included in subsequent requests.

How do I Secure REST API Using JWT in Spring Boot?

Configure the SecurityFilterChain, enable the OAuth2 Resource Server with JWT support, configure a JwtDecoder, and create a service for generating tokens.

Why does Spring Boot require a JwtDecoder?

The JwtDecoder validates and decodes incoming JWTs so Spring Security can determine whether the token is valid.

Why are public and private keys used for JWT?

The private key is used to sign the JWT, while the public key is used to verify that the token was signed by the trusted private key.

What is the purpose of the /token endpoint?

The /token endpoint authenticates the user and returns a newly generated JWT that can be used to access protected API resources.

Final Thoughts

JWT provides a practical way to secure a Spring Boot REST API without relying on server-side sessions. By combining Spring Security, an OAuth2 Resource Server, RSA public/private keys, and JwtEncoder and JwtDecoder, you can create and validate signed tokens.

The implementation can then be extended beyond the in-memory test user used in this tutorial by connecting authentication to a database and implementing UserDetailsService. This provides a foundation for building more complete and secure Spring Boot applications.

Kindson Munonye

Kindson Munonye is a software engineer and technical author covering machine learning, statistics, REST APIs, Python, and software engineering. He publishes free tutorials on The Genius Blog and live classes on Alkademy. GitHub · LinkedIn · About · Alkademy

View all posts by Kindson Munonye →
0 0 votes
Article Rating
Subscribe
Notify of
guest

1 Comment
Oldest
Newest Most Voted
trackback

[…] Secure REST APIs with JWT · Spring Boot RAG tutorial · Deploy Spring Boot to […]