-
-
Notifications
You must be signed in to change notification settings - Fork 600
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support JWK #32
Comments
+1 |
Sure! I'm just fixing the issue #30 and will plan the best way to support it. |
I'm starting this effort on lcobucci/jwk#1 and I'll change this lib to use JWK to sign this. Any help is welcome! |
Can I use this library in PHP 5.3.3? |
@EugeneHan no, this lib can just be used with PHP 5.5+ (since there's no support for earlier versions http://php.net/supported-versions.php). Our next major release will only support PHP 7. |
@lcobucci would you support previous version after migrating on php7 |
@scaytrase the plan is that we'll keep the new features on v4.x+ and security/bug fixes on both v3.x and v4.x+. |
This would be handy, AWS Cognito provides a RSA JWK and to verify them you need to convert to PEM first. |
Is there any more news on this feature? Currently, this appears to best PHP library for features and small size but it is a pain to write my own code to convert JWKs to PEM. I'm happy to help if there are specific jobs to do, I don't believe it is hard to convert Base64 JWK into a raw public key. |
https://github.com/acodercat/php-jwk-to-pem might be helpful until JWK support lands. |
@shadowhand the problem with this library is that it only supports RSA keys, not EC ones. May I suggest you to have a look at PHP console app? curl -OL https://github.com/web-token/jwt-app/raw/gh-pages/jose.phar
curl -OL https://github.com/web-token/jwt-app/raw/gh-pages/jose.phar.pubkey
chmod +x jose.phar
./jose.phar key:convert:pkcs1 '{"kty":"EC","crv":"P-256","d":"kiNCxSbRjlAbHrEbrwVKS8vIXUh6URChrmw","x":"-wdLWDWCZP6oFYl8aGVfU0MsFlckjaSVrO7hEsc8lgk","y":"rt8XDTalLMCRB5Tu9WQc2d0TOVwXXHkVDbI7cIig6r4"}'
# Will return:
# -----BEGIN EC PRIVATE KEY-----
# MHcCAQEEIJIjQsUm0Y5QGx6xG68N4GrprVrFSkvLyF1IelEQoa5soAoGCCqGSM49
# AwEHoUQDQgAE+wdLWDWCZP6oFYl8aGVfU0MsFlckjaSVrO7hEsc8lgmu3xcNNqUs
# wJEHlO71ZBzZ3RM5XBdceRUNsjtwiKDqvg==
# -----END EC PRIVATE KEY----- It also offers a lot of useful commands (key creation, analyze, keyset features...). |
@Spomky We only need support for PEM keys during a HTTP request lifecycle, so the package I linked is better fit for our needs. As a side node about: jwt-framework (and jose.phar) is an impressive project. Unfortunately it seems more concerned with being academically correct than useful. The docs took a long time to digest, and in our case, the |
Any details about the implementation, are you still waiting or is there already a branch to support? |
Just wanted to register my +1 for this feature. I've implemented @lcobucci If you're interested I could put together a PR for you based on using this library? Let me know if this is an approach you'd be happy with, or if you'd rather go another way. |
+1 from my side as well. JSON web key document should be the part of this library. |
@lcobucci Would this be eligible for a move to 4.0.0 milestone from 5.0.0 with sponsored development? |
@bradjones1 thanks for the offer. My plan is to redesign the key so that we can implement jwk without breaking BC but wanted to make it part of v4.1. v4 requires PHP 7.4+, does that meet your needs? |
@lcobucci Modern PHP at 7.4+ is no blocker on our side. Thanks very much for your work on the module and I look forward to helping. |
Not a solution to JWK-to-PEM problem nor any help for JWK support, but just a mention that #605 got merged and now EdDSA signature can be used too for asymmetric signing: EdDSA keys don't need PEM conversion so they can be a nice workaround, considering also they are more secure. |
Dear @lcobucci, What's the status of this? Thanks! |
+1 |
If you want to verify that a JWT has been signed using someone's private key, you can do: composer req web-token/jwt-core use Jose\Component\Core\JWK;
use Jose\Component\Core\Util\RSAKey;
use Lcobucci\JWT\Signer;
use Lcobucci\JWT\Validation;
$key = <<<'KEY'
{
"kty": "RSA",
"e": "AQAB",
"kid": "rsa1",
"alg": "RS256",
"n": "yKqGRQyJtqxRm_Mo2YTCCAkPS..."
}
KEY;
// web-token/jwt-core
$jwk = JWK::createFromJson($key);
$pem = RSAKey::createFromJWK($jwk)->toPEM();
// lcobucci/jwt
$token = '...';
$constraints = [
new Validation\Constraint\SignedWith(
new Signer\Rsa\Sha256(),
Signer\Key\InMemory::plainText($pem)
),
];
$validator = new Validation\Validator();
$validator->assert($token, ...$constraints);
... 🤝 |
As I understand @Spomky, From https://web-token.spomky-labs.com/introduction/pre-requisite:
But presumably this will be no slower than a library that avoids either of those deps, right? |
@lcobucci I've been having a look at this after the discussion on #mezzio slack. From what I can see, the shortest path would be a Does that make sense to you? If there's a better approach let me know... I sort of feel like the existing |
For those wondering how to achieve something like @hallboav showcased, but with phpseclib instead. |
This helped me https://www.tuxed.net/fkooman/blog/json_web_key_set.html |
This feature seem not to be planned anymore? I tested the solution @hallboav provided, it works good, thank you for that. Unfortunately it has yet two flaws which makes it not really an acceptable solution (to me).
I picked |
???????????? What? |
Where exactly is your big question mark? I was talking about the two libraries the solution is using which increases the likelihood one could be unmaintained. Surely not JWT if that was the issue here. 😆 |
Hello @simonberger, thanks for sharing your thoughts. It's very unlikely that this library will get unmaintained in the future. You see, I've implemented this library to satisfy the needs I had. Opening it up as OSS was mainly to share that with the rest of the world. All the features we ended up having were either centred around my needs or the community's (who valiantly pushed change requests over years). I've never missed JWK support, therefore it was never logical to spend my time implementing it. Especially after I became a father and started having less and less time for myself. I see four possibilities here:
Feel free to send us a PR or an email if you decide to follow paths 1 or 2 👍 |
@lcobucci Thank you very much for your answer. Understandable from your perspective and a good conclusion comment why it won't come for now without contribution in any way. To contribute from my side I have unfortunately too low knowledge of the topic and underlying technology as well as lack of time to grow that. |
Just a note to say I'm using this library to build PEM public keys for verification of signatures. It's quite small and has no dependencies. Sample code that extracts an EC-based JWK, converts it to PEM, and verifies the JWT was signed by it. <?php
use FreeDSx\Asn1\Asn1;
use FreeDSx\Asn1\Encoders;
use Lcobucci\JWT\Encoding\JoseEncoder;
use Lcobucci\JWT\Signer\Ecdsa;
use Lcobucci\JWT\Signer\Eddsa;
use Lcobucci\JWT\Signer\Key\InMemory;
use Lcobucci\JWT\Signer\Rsa;
use Lcobucci\JWT\Token\Parser;
use Lcobucci\JWT\Validation\Constraint\SignedWith;
use Lcobucci\JWT\Validation\Validator;
use RadiusOne\AcmeServer\Enums\ErrorType;
use RadiusOne\AcmeServer\Exceptions\AcmeException;
use Symfony\Component\HttpFoundation\Response;
$protected = 'eyJub25jZSI6ICI2d3JsT0owVDlJOTFLVUhXVzJNZTV5ZldnYWRuSXNSRnpZUHI5el9PYnY1WENiTU1ZVEEiLCAidXJsIjogImh0dHBzOi8vYWNtZS1zdGFnaW5nLXYwMi5hcGkubGV0c2VuY3J5cHQub3JnL2FjbWUvbmV3LWFjY3QiLCAiYWxnIjogIkVTMjU2IiwgImp3ayI6IHsiY3J2IjogIlAtMjU2IiwgImt0eSI6ICJFQyIsICJ4IjogIllfamdiYUlzV1hRTkFtSzlMYVhJY3FuZ3Jsc2VrbFdGbkRWRFc1TF9kWEEiLCAieSI6ICJoV3RVczlpRnZEMm1iNHZ1X2VLYkxJazgycHZnQWVxbG1PVmk0VVRiUFljIn19';
$payload = 'eyJ0ZXJtc09mU2VydmljZUFncmVlZCI6IHRydWV9';
$signature = 'mywGCQ9jHEWMJWAQUrLQ_rbSpQMYsroy-donI3lfkBKYdzpNLo8wjOgGPOhWa-SGQoIuRD-6RdI1tRbN3olFKA';
$jwt = implode('.', [$protected, $payload, $signature]);
$parser = new Parser(new JoseEncoder());
$validator = new Validator();
$token = $parser->parse($jwt);
$jwk = $token->headers()->get('jwk');
// convert JWK to PEM
$key_oid = match($jwk['crv']) {
'P-256' => '1.2.840.10045.3.1.7',
'secp256k1' => '1.3.132.0.10',
'P-384' => '1.3.132.0.34',
'P-521' => '1.3.132.0.35',
};
$x = sodium_base642bin($jwk['x'], SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING);
$y = sodium_base642bin($jwk['y'], SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING);
$key = Asn1::sequence(
Asn1::sequence(Asn1::oid('1.2.840.10045.2.1'), Asn1::oid($key_oid)),
// 04 indicates an uncompressed public key follows
Asn1::bitStringFromBinary(chr(4) . $x . $y),
);
$der = Encoders::der()->encode($key);
$pem = sprintf(
'-----BEGIN PUBLIC KEY-----%s%s%s-----END PUBLIC KEY-----',
PHP_EOL,
trim(chunk_split(base64_encode($der), 64, PHP_EOL)),
PHP_EOL
);
// validate signature using PEM cert
$alg = match($token->headers()->get('alg')) {
'ES256' => new Ecdsa\Sha256(),
'ES384' => new Ecdsa\Sha384(),
'ES512' => new Ecdsa\Sha512(),
'EdDSA' => new Eddsa(),
'RS256' => new Rsa\Sha256(),
'RS384' => new Rsa\Sha384(),
'RS512' => new Rsa\Sha512(),
default => throw new AcmeException(ErrorType::badSignatureAlgorithm, Response::HTTP_BAD_REQUEST),
};
$validator->assert(
$token,
new SignedWith($alg, InMemory::plainText($pem))
); I'm in way over my head here, so not sure how robust or reliable the code is. But it's working well for me and parsing the JWK for conversion to PEM is only a handful of lines; RSA shouldn't add much. |
Your code has at least the issue that you trust the algorithm named in the token to be the correct one. That is one flaw within the JWT standard, as an attacker can decide which algorithm you should use for validation, and they will name the one they have broken or know the key or can inject the key or can abuse in a key confusion attack.
If you know (and you should), which algorithms the issuer of a token uses, limit token validation to only allow these algorithms, and nothing else.
Happy to see you didn't implement algorithm "none", as that was a serious problem in the early days of JWT for the same reason: Attacker would say alg=none and skip signature validation entirely.
|
Could you add support for JWK?
http://tools.ietf.org/html/draft-ietf-jose-json-web-key-02
The text was updated successfully, but these errors were encountered: