问题
I need to add a PHP application in a SSO built using a CAS in Java. After authentication of the user, the SSO sends the credintials to the PHP App and the token is built using the code below:
public function getToken(Signer $signer = null, Key $key = null)
{
$signer = $signer ?: $this->signer;
$key = $key ?: $this->key;
if ($signer instanceof Signer) {
$signer->modifyHeader($this->headers);
}
$payload = [
$this->encoder->base64UrlEncode($this->encoder->jsonEncode($this->headers)),
$this->encoder->base64UrlEncode($this->encoder->jsonEncode($this->claims))
];
$signature = $this->createSignature($payload, $signer, $key);
if ($signature !== null) {
$payload[] = $this->encoder->base64UrlEncode($signature);
}
return new Token($this->headers, $this->claims, $signature , $payload);
}
private function createSignature(array $payload, Signer $signer = null, Key $key = null)
{
if ($signer === null || $key === null) {
return null;
}
return $signer->sign(implode('.', $payload), $key);
}
So I try to validate the generated token using java, as bellow:
public boolean validateToken(String authToken) {
try {
Jwts.parser().setSigningKey(secretKey).parseClaimsJws(authToken);
return true;
} catch (SignatureException e) {
log.info("Invalid JWT signature.");
log.trace("Invalid JWT signature trace: {}", e);
e.printStackTrace();
}
....
}
To validade the signature, the jjwt splits the 3 parts of the token and tries to sign the 2 firsts parts using the algorithm provided in the header of the token. This step is the same used to create the signature of the token when the token is created. Theoretically, using the same algorithm, paylod and secret in both steps, creation and valitadion, the signature shoud be the same. But it does not happen. The following excpetion is thrown:
io.jsonwebtoken.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.
回答1:
I will respond my own question. jjwt expects a base64 enconded secret. But in my java code I was not encoding the secret before set it in the parser.
This is how jjwt validate the token signature:
public boolean isValid(String jwtWithoutSignature, String base64UrlEncodedSignature) {
byte[] data = jwtWithoutSignature.getBytes(US_ASCII);
byte[] signature = TextCodec.BASE64URL.decode(base64UrlEncodedSignature);
return this.signatureValidator.isValid(data, signature);
}
The change I made in my java code:
secretKey = TextCodec.BASE64URL.encode(secret);
Jwts.parser().setSigningKey(secretKey).parseClaimsJws(authToken)
来源:https://stackoverflow.com/questions/57297249/jjwt-throws-signature-error-when-validates-a-jwt-token-generated-from-php