Role of SecretKeySpec in NimbusJwtDecoder: Spring Security and JWT

590 views Asked by At

I was going through Symmetric and Assymetric Signatures for JWT in Spring Security. I came accross this video by Dan Vega- https://www.youtube.com/watchv=66DtzkhBlSA&list=PLZV0a2jwt22s5NCKOwSmHVagoDW8nflaC&index=6&ab_channel=DanVega
Here, in the SecurityConfig.java, Jwt Encoder and Jwt Decoder are created.

 @Bean
    public JwtEncoder jwtEncoder() {
        return new NimbusJwtEncoder(new ImmutableSecret<>(jwtKey.getBytes()));
    }
    //Decoder
    @Bean
    public JwtDecoder jwtDecoder() {
        byte[] bytes = jwtKey.getBytes();
        SecretKeySpec originalKey = new SecretKeySpec(bytes, 0, bytes.length, "RSA");
        logger.info("Original Key: {}", originalKey.getEncoded());
        return NimbusJwtDecoder.withSecretKey(originalKey).macAlgorithm(MacAlgorithm.HS512).build();
    }

Generating token-

package com.ayushsingh.jwtsymmetric_keydemo.service;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.jose.jws.MacAlgorithm;
import org.springframework.security.oauth2.jwt.JwsHeader;
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.JwtEncoderParameters;
import org.springframework.stereotype.Service;

@Service
public class TokenService {

    @Autowired
    private JwtEncoder jwtEncoder;

    // Method to generate the token
    public String generateToken(Authentication authentication) {
        Instant now = Instant.now(); 
        String scope = authentication.getAuthorities().stream()
     
                .map(GrantedAuthority::getAuthority)
              
                .filter(authority -> !authority.startsWith("ROLE"))
                .collect(Collectors.joining(" "));
        JwtClaimsSet claims = JwtClaimsSet.builder()
                .issuer("self") 
                .issuedAt(now) 
                .expiresAt(now.plus(1, ChronoUnit.HOURS))
                .subject(authentication.getName())
                .claim("scope", scope)
                .build();
        var encodedParameters = JwtEncoderParameters.from(JwsHeader.with(MacAlgorithm.HS512).build(), claims); 
        return this.jwtEncoder.encode(encodedParameters).getTokenValue(); 

    }
}

My queries-
I understand that we are using the same symmetric key for encryption here as explained in the video and here- https://www.pingidentity.com/en/resources/blog/post/jwt-security-nobody-talks-about.html#:~:text=using%20asymmetric%20signatures.-,Asymmetric%20JWT%20Signatures,verified%20with%20the%20public%20key.
But, I am not able to understand why we require a SecretKeySpec in the decoder-

 @Bean
    public JwtDecoder jwtDecoder() {
        byte[] bytes = jwtKey.getBytes();
        SecretKeySpec originalKey = new SecretKeySpec(bytes, 0, bytes.length, "RSA");
        logger.info("Original Key: {}", originalKey.getEncoded());
        return NimbusJwtDecoder.withSecretKey(originalKey).macAlgorithm(MacAlgorithm.HS512).build();
    }

What does SecretKeySpec exactly do and why we use RSA here? Here, jwtKey 9faa372517ac1d389758d3750fc07acf00f542277f26fec1ce4593e93f64e338. The output for

logger.info("Original Key: {}", originalKey.getEncoded());

is-

 Original Key: [57, 102, 97, 97, 51, 55, 50, 53, 49, 55, 97, 99, 49, 100, 51, 56, 57, 55, 53, 56, 100, 51, 55, 53, 48, 102, 99, 48, 55, 97, 99, 102, 48, 48, 102, 53, 52, 50, 50, 55, 55, 102, 50, 54, 102, 101, 99, 49, 99, 101, 52, 53, 57, 51, 101, 57, 51, 102, 54, 52, 101, 51, 51, 56]

Why are we using RSA in the decoder! It is not used anywhere else in the implementation. Please help me understand!

0

There are 0 answers