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!