title: Illegal base64url character: ' ' when getting claims/decode from token Java JWT Spring Boot
body: <p>When I get some claims from a JWT Token to validate user authentication I get the following error:</p>
  <pre><code>Illegal base64url character: ' '
  </code></pre>
  <p>Creating a JWT goes completely fine but &quot;decoding&quot; seems to have some issues...
  I also tried a base64url decoder to decode the token before getting the claims but then the token is unvalid.</p>
  <p>My JWToken class where I encode and &quot;decode&quot; the token:</p>
  <pre><code>@Component
  public class JWToken {
  
      private static final String JWT_USERNAME_CLAIM = &quot;sub&quot;;
      private static final String JWT_ADMIN_CLAIM = &quot;admin&quot;;
  
      @Value(&quot;${jwt.issuer}&quot;)
      private String issuer;
  
      @Value(&quot;${jwt.passPhrase}&quot;)
      private String passPhrase;
  
      @Value(&quot;${jwt.duration-of-validity}&quot;)
      private int expiration;
  
  
     public String encode(String name, boolean admin) {
         String token = Jwts.builder()
                 .claim(JWT_USERNAME_CLAIM, name)
                 .claim(JWT_ADMIN_CLAIM, admin)
                 .setSubject(name)
                 .setIssuer(issuer)
                 .setIssuedAt(new Date(System.currentTimeMillis()))
                 .setExpiration(new Date(System.currentTimeMillis() + expiration * 1000))
                 .signWith(SignatureAlgorithm.HS512, passPhrase).compact();
  
         return token;
     }
  
  
      //for retrieving any information from token we will need the secret key
      private Claims getAllClaimsFromToken(String token) {
          return Jwts.parser().setSigningKey(passPhrase).parseClaimsJws(token).getBody();
      }
  
      public &lt;T&gt; T getClaimFromToken(String token, Function&lt;Claims, T&gt; claimsResolver) {
          final Claims claims = getAllClaimsFromToken(token);
          return claimsResolver.apply(claims);
      }
  
      //retrieve username from jwt token
      public String getUsernameFromToken(String token) {
          return getClaimFromToken(token, Claims::getSubject);
      }
  
      //retrieve expiration date from jwt token
      public Date getExpirationDateFromToken(String token) {
          return getClaimFromToken(token, Claims::getExpiration);
      }
  
      //check if the token has expired
      private Boolean isTokenExpired(String token) {
          final Date expiration = getExpirationDateFromToken(token);
          return expiration.before(new Date());
      }
  
      //validate token
      public Boolean validateToken(String token, String name) {
          final String username = getUsernameFromToken(token);
          return (username.equals(name) &amp;&amp; !isTokenExpired(token));
      }
      
  
  
  }
  </code></pre>
  <p>My request filter:</p>
  <pre><code>@Component
  public class JWTRequestFilter extends OncePerRequestFilter {
      private static final Set&lt;String&gt; SECURED_PATHS =
              Set.of(&quot;/api/offers&quot;, &quot;/api/bids&quot;);
  
      private final JWToken jwToken;
  
      @Autowired
      public JWTRequestFilter(JWToken jwToken) {
          this.jwToken = jwToken;
      }
  
      @Override
      protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
  
  
  
          final String requestTokenHeader = request.getHeader(&quot;Authorization&quot;);
          String username = null;
          String jwtToken = null;
  
          String servletPath = request.getServletPath();
  
          if (HttpMethod.OPTIONS.matches(request.getMethod()) || SECURED_PATHS.stream().noneMatch(servletPath::startsWith)) {
  
              filterChain.doFilter(request, response);
              return;
          }
  
          // JWT Token is in the form &quot;Bearer token&quot;. Remove Bearer word and get
          // only the Token
          if (requestTokenHeader != null &amp;&amp; requestTokenHeader.startsWith(&quot;Bearer &quot;)) {
              jwtToken = requestTokenHeader.substring(7);
              try {
                  System.out.println(jwtToken);
                  username = jwToken.getUsernameFromToken(jwtToken);
              } catch (IllegalArgumentException e) {
                  System.out.println(&quot;Unable to get JWT Token&quot;);
                  throw new AuthenticationException(&quot;authentication problem&quot;);
              } catch (ExpiredJwtException e) {
                  throw new AuthenticationException(&quot;authentication problem&quot;);
              }
          } else {
              System.out.println(requestTokenHeader);
              logger.warn(&quot;JWT Token does not begin with Bearer String&quot;);
              //throw new AuthenticationException(&quot;authentication problem&quot;);
          }
  
          if(jwToken.validateToken(jwtToken, username)){
              filterChain.doFilter(request, response);
          }
  
          // Once we get the token validate it.
  
          }
  
  }
  </code></pre>
  <p>The error in my console when I do a get request for <code>/api/offers</code> with the generated JWT token in the header:</p>
  <pre><code>io.jsonwebtoken.io.DecodingException: Illegal base64url character: ' '
      at io.jsonwebtoken.io.Base64.ctoi(Base64.java:221) ~[jjwt-api-0.11.2.jar:0.11.2]
      at io.jsonwebtoken.io.Base64.decodeFast(Base64.java:270) ~[jjwt-api-0.11.2.jar:0.11.2]
      at io.jsonwebtoken.io.Base64Decoder.decode(Base64Decoder.java:36) ~[jjwt-api-0.11.2.jar:0.11.2]
      at io.jsonwebtoken.io.Base64Decoder.decode(Base64Decoder.java:23) ~[jjwt-api-0.11.2.jar:0.11.2]
      at io.jsonwebtoken.io.ExceptionPropagatingDecoder.decode(ExceptionPropagatingDecoder.java:36) ~[jjwt-api-0.11.2.jar:0.11.2]
      at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:309) ~[jjwt-impl-0.11.2.jar:0.11.2]
      at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:550) ~[jjwt-impl-0.11.2.jar:0.11.2]
      at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJws(DefaultJwtParser.java:610) ~[jjwt-impl-0.11.2.jar:0.11.2]
      at team10.server.aucserver.security.JWToken.getAllClaimsFromToken(JWToken.java:47) ~[classes/:na]
      at team10.server.aucserver.security.JWToken.getClaimFromToken(JWToken.java:51) ~[classes/:na]
      at team10.server.aucserver.security.JWToken.getUsernameFromToken(JWToken.java:57) ~[classes/:na]
      at team10.server.aucserver.security.JWTRequestFilter.doFilterInternal(JWTRequestFilter.java:52) ~[classes/:na]
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar:5.3.1]
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.1.jar:5.3.1]
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar:5.3.1]
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.1.jar:5.3.1]
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar:5.3.1]
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.1.jar:5.3.1]
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar:5.3.1]
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) ~[na:na]
      at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) ~[na:na]
      at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.39.jar:9.0.39]
      at java.base/java.lang.Thread.run(Thread.java:832) ~[na:na]
  </code></pre>
  <p>And line 47 is the <code>getAllClaimsFromToken</code> method in the JWToken class.</p>
  <p>For an extra example this is one of the tokens the encode genrated:</p>
  <pre><code>Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJyb25ueSIsImFkbWluIjpmYWxzZSwiaXNzIjoicHJpdmF0ZSBjb21wYW55IiwiaWF0IjoxNjExMDA1NTc4LCJleHAiOjE2MTEwMDY3Nzh9.dQwEVfSNa6EIx-U-bgHN50hmrN0wYkj-8jXRoFLTx6JB53ERBWuGUeiXLqtiJ_jTGxEISB-Lv7E9KAyPk8nV3g
  </code></pre>