When trying to decode the JWT Tokens to extract the information from the token getting the Error like
Illegal base64url character: ' '
This is my service class, when trying to execute the claims there is no output and error is thrown
I am trying to validate the user for that i have generated jwt token while loggin and when I am trying to use different services where user need to be verified I want to extract user information from JWT token and match it with database
package com.example.RentCar.Services;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import com.example.RentCar.DTOS.UserRequestDTO;
import com.example.RentCar.Models.User;
import com.example.RentCar.Repository.UserRepository;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
@Service
public class JwtServicesImpl implements JwtServices {
private UserRequestDTO userRequestDTO;
//private final UserRepository userRepository;
// @Value("${token.signing.key}")
private String jwtSigningKey = "413F4428472B4B6250655368566D5970337336763979244226452948404D6351";
@Override
public String extractUserName(String token) {
return extractClaim(token, Claims::getSubject);
}
@Override
public String generateToken(User user) {
return generateToken(new HashMap<>(), user);
}
@Override
public boolean isTokenValid(String token, UserServicesImpl userServices) {
final String email = extractUserName(token);
UserDetails user = (userServices.loadUserByUsername(email));
String email2 = user.getUsername();
return (email.equals(email2) && !isTokenExpired(token));
}
private <T> T extractClaim(String token, Function<Claims, T> claimsResolvers) {
final Claims claims = extractAllClaims(token);
System.out.println(claims); //not printing
return claimsResolvers.apply(claims);
}
private String generateToken(Map<String, Object> extraClaims, User user) {
return Jwts.builder().setClaims(extraClaims).setSubject(user.getUserEmail())
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 24))
.signWith(getSigningKey(), SignatureAlgorithm.HS256).compact();
}
private boolean isTokenExpired(String token) {
return extractExpiration(token).before(new Date());
}
private Date extractExpiration(String token) {
return extractClaim(token, Claims::getExpiration);
}
private Claims extractAllClaims(String token) {
return Jwts.parserBuilder().setSigningKey(getSigningKey()).build().parseClaimsJws(token)
.getBody();
}
private Key getSigningKey() {
// System.out.println(jwtSigningKey);
byte[] keyBytes = Decoders.BASE64.decode(jwtSigningKey);
return Keys.hmacShaKeyFor(keyBytes);
}
}
```
below is the error
io.jsonwebtoken.io.DecodingException: Illegal base64url character: ' '
at io.jsonwebtoken.io.Base64.ctoi(Base64.java:221)
at io.jsonwebtoken.io.Base64.decodeFast(Base64.java:270)
at io.jsonwebtoken.io.Base64Decoder.decode(Base64Decoder.java:36)
at io.jsonwebtoken.io.Base64Decoder.decode(Base64Decoder.java:23)
at io.jsonwebtoken.io.ExceptionPropagatingDecoder.decode(ExceptionPropagatingDecoder.java:36)
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:288)
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:529)
at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJws(DefaultJwtParser.java:589)
at io.jsonwebtoken.impl.ImmutableJwtParser.parseClaimsJws(ImmutableJwtParser.java:173)
at com.example.RentCar.Services.JwtServicesImpl.extractAllClaims(JwtServicesImpl.java:76)
at com.example.RentCar.Services.JwtServicesImpl.extractClaim(JwtServicesImpl.java:55)
at com.example.RentCar.Services.JwtServicesImpl.extractUserName(JwtServicesImpl.java:34)
at com.example.RentCar.Controllers.UserController.ModifyAddress(UserController.java:36)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1081)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011)
Expecting should be like can claims or extract information from token
As Jon Skeet said, your jwtSigningKey is encoded in Hex and in getSigningKey() you're telling Java to decode it with Base64.
Either have the key encoded with Base64 or decode with Hex.
See https://stackoverflow.com/a/140861/21538342