Illegal base64url character: ' ' while extracting the information from JWT token

306 views Asked by At

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

1

There are 1 answers

3
Patrick On

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