简体   繁体   中英

Why is my JWT only verifying with the private key and not the public key?

So I have a very strange issue currently where I can generate tokens perfectly fine and send them out to my API client (currently using Insomnia for testing) however on the server the tokens only seem to validate when doing so against the private key and not the public key. From my research I understand that verifying against the private key, apart from not being the best idea, shouldn't actually be possible!

For context my server is running PHP and I'm using Lcobucci's JWT library

openssl genrsa -out ./keys/private.key 2048
openssl rsa -in ./keys/private.key -pubout -out ./keys/public.key
use Lcobucci\JWT\Token\Builder;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Encoding\{ChainedFormatter,JoseEncoder};
use Lcobucci\JWT\UnencryptedToken;
use Lcobucci\JWT\Validation\Validator as JWTValidator;
use Lcobucci\JWT\Validation\Constraint\SignedWith;

$this->private_key = InMemory::file($private_key_path);
$this->public_key = InMemory::file($public_key_path);

// Logging these to the terminal presents them both fine

$token_builder = new Builder(new JoseEncoder(), ChainedFormatter::default());
$algorithm = new Sha256();
$signing_key = $this->private_key;
$now = new \DateTimeImmutable();
$exp = $now->modify('+1 hour');

$access_token = $token_builder
    ->issuedBy('my-system')
    ->permittedFor('my-frontend-system')
    ->identifiedBy(uniqid())
    ->issuedAt($now)
    ->canOnlyBeUsedAfter($now)
    ->expiresAt($exp)
    ->withClaim('user_id', $authentication['user_id'])
    ->withClaim('user_roles', $roles)
    ->getToken($algorithm, $signing_key);
$validator = new JWTValidator();
if (!$validator->validate($access_token, new SignedWith($algorithm, $this->public_key))) {
  throw new AuthenticationException("The generated token was invalid");
}

As you'll see above, I've condensed my code so that it attempts to validate the key immediately after generation. And it still throws the exception! Changing $this->public_key to $this->private_key in the validator then doesn't.

Usually when I type out a question on here and am about to post, I then spot what the issue is or think "hmm, what if I try doing this?" and it works, however that hasn't happened this time so I submit to you, good people of SO: what am I doing wrong?!

Edit in response to a comment: the algorithm in the header is HS256:

{
  "typ": "JWT",
  "alg": "HS256" // Here's the problem, it should be RS256!
}

I'll self-answer this as thanks to jps's answers I now know what I was doing wrong. As is usually the case with these, I've overlooked something really simple and been a bit silly!

Here's the culprit:

use Lcobucci\JWT\Signer\Hmac\Sha256;

Which should have in fact been:

use Lcobucci\JWT\Signer\RSA\Sha256;

Needless to say, swapping the symmetrical HMAC for the asymmetrical RSA worked!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM