docs: @Override
  	protected Map<String, Object> decode(String token) {
  		Map<String, String> headers = this.jwtHeaderConverter.convert(token);
  
  		// Validate "kid" header
  		String keyIdHeader = headers.get(KEY_ID);
  		if (keyIdHeader == null) {
  			throw new InvalidTokenException("Invalid JWT/JWS: " + KEY_ID + " is a required JOSE Header");
  		}
  		JwkDefinitionSource.JwkDefinitionHolder jwkDefinitionHolder = this.jwkDefinitionSource.getDefinitionLoadIfNecessary(keyIdHeader);
  		if (jwkDefinitionHolder == null) {
  			throw new InvalidTokenException("Invalid JOSE Header " + KEY_ID + " (" + keyIdHeader + ")");
  		}
  
  		JwkDefinition jwkDefinition = jwkDefinitionHolder.getJwkDefinition();
  		// Validate "alg" header
  		String algorithmHeader = headers.get(ALGORITHM);
  		if (algorithmHeader == null) {
  			throw new InvalidTokenException("Invalid JWT/JWS: " + ALGORITHM + " is a required JOSE Header");
  		}
  		if (jwkDefinition.getAlgorithm() != null && !algorithmHeader.equals(jwkDefinition.getAlgorithm().headerParamValue())) {
  			throw new InvalidTokenException("Invalid JOSE Header " + ALGORITHM + " (" + algorithmHeader + ")" +
  					" does not match algorithm associated to JWK with " + KEY_ID + " (" + keyIdHeader + ")");
  		}
  
  		// Verify signature
  		SignatureVerifier verifier = jwkDefinitionHolder.getSignatureVerifier();
  		Jwt jwt = JwtHelper.decode(token);
  		jwt.verifySignature(verifier);
  
  		Map<String, Object> claims = this.jsonParser.parseMap(jwt.getClaims());
  		if (claims.containsKey(EXP) && claims.get(EXP) instanceof Integer) {
  			Integer expiryInt = (Integer) claims.get(EXP);
  			claims.put(EXP, new Long(expiryInt));
  		}
  		this.getJwtClaimsSetVerifier().verify(claims);
  
  		return claims;
  	}