0

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.

jps
  • 20,041
  • 15
  • 75
  • 79
leo valeriano
  • 810
  • 8
  • 8
  • did you try to validate your token on https://jwt.io/ ? – jps Jul 31 '19 at 19:43
  • @jps, thanks for revision. Yes, I validated the token on jwt.io. At first I was informed it was "invalid signature", so I put the secret in the field "verify signature" and clicked at the checkbox "secret". Then the token was mofied in the part of signature. I tried to validate the token modified using jjwt and the error persists – leo valeriano Aug 01 '19 at 12:21
  • the checkbox on jwt.io that you clicked means that the secret is base64 encoded, but I think it is not. So first put your secret into that field, then paste your token on the left side. You should see now "signature verified", without any change of the signature. – jps Aug 01 '19 at 12:28
  • Yes! the signature was verified on jwt.io. But in java code, when I try to validate de token I still have the first error. If I encode the secret in java to Base64, it works. But i cannot do this in java because there are other applications using this functionality this way. I suppose I have to change the way to create the token in PHP. – leo valeriano Aug 01 '19 at 13:05

1 Answers1

2

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)
leo valeriano
  • 810
  • 8
  • 8