yiisoft / yii2-authclient

Yii 2 authclient extension.
http://www.yiiframework.com
BSD 3-Clause "New" or "Revised" License
464 stars 246 forks source link

Replace spomky-labs/jose suggestion #217

Closed lukos closed 4 years ago

lukos commented 6 years ago

Looking to install yii2-authclient plugin, it suggests installing spomky-labs/jose

BUT

if you visit https://github.com/Spomky-Labs/jose, it says to instead use https://github.com/web-token/jwt-framework and that support for jose is only until end of 2018.

Has anyone seen this yet or done any work on it? Otherwise I am happy to attempt to use the new library and give you a PR for the changes.

samdark commented 6 years ago

Feel free to send us a pull request. Thanks.

lukos commented 6 years ago

Sure. There is a fair amount more code unfortunately and it requires a symfony php-http package as well. Just trying to finish the login journey before I create the PR. What other files will I need to change as well as the code?

samdark commented 6 years ago

composer.json, composer.lock

lukos commented 6 years ago

The suggested replacement from Spomky Labs is a lot of dependency for a single signature validation. I am looking at smaller alternatives such as https://github.com/gamegos/php-jws

lukos commented 6 years ago

Not many great options. gree/jose is very small but it only verifies the JWS signature, not any of the claims and it is not very active as a project. lcobucci/jwt is more active but does not support json web keys so they would need converting to PEM before using the library. Other libraries do not support full verification. spomky labs is good but no longer supported and web-token/jwt-framework, as mentioned is very large for what we need.

I have done the code for gree/jose but I don't know that the project is active enough to be a good replacement for spomky-labs, which is supported for maybe 1 more year.

Any other suggestions from anyone? It's a shame that PHP does not have native support. I could write our own code in the client but that doesn't seem great either!

CheckeredFlag commented 6 years ago

I really don't understand the requirements and nor how dependencies work, but it appears appears that web-token/jwt-framework is modular and that it may not be necessary to require the entire bundle.

The web-token docs appear to indicate that the web-token/jwt-signature component may be all that's needed to verify signatures, which only appears to require web-token/jwt-core.

I may be way off base as my understanding of all this is limited.

hableel commented 5 years ago

What about https://github.com/paragonie/paseto

smcyr commented 5 years ago

I used web-token/jwt-signature and web-token/jwt-checker for my project (because Spomky-Labs/jose doesn't work on PHP 7.3) and it worked great!

I extended OpendIdConnect and used GuzzleHttp. Here are the changes I did:

<?php

use Exception;
use GuzzleHttp\Client;
use Jose\Component\Checker\AlgorithmChecker;
use Jose\Component\Core\AlgorithmManager;
use Jose\Component\Core\JWK;
use Jose\Component\Signature\Algorithm\ES256;
use Jose\Component\Signature\Algorithm\ES384;
use Jose\Component\Signature\Algorithm\ES512;
use Jose\Component\Signature\Algorithm\HS256;
use Jose\Component\Signature\Algorithm\HS384;
use Jose\Component\Signature\Algorithm\HS512;
use Jose\Component\Signature\Algorithm\PS256;
use Jose\Component\Signature\Algorithm\PS384;
use Jose\Component\Signature\Algorithm\PS512;
use Jose\Component\Signature\Algorithm\RS256;
use Jose\Component\Signature\Algorithm\RS384;
use Jose\Component\Signature\Algorithm\RS512;
use Jose\Component\Signature\JWSLoader;
use Jose\Component\Signature\JWSTokenSupport;
use Jose\Component\Signature\JWSVerifier;
use Jose\Component\Signature\Serializer\CompactSerializer;
use Jose\Component\Signature\Serializer\JWSSerializerManager;
use Jose\Component\Checker\HeaderCheckerManager;
use yii\authclient\OpenIdConnect;
use yii\web\HttpException;

class IdentityServer extends OpenIdConnect
{
    protected function loadJws($token)
    {
        try {
            $client = new Client();
            $responseBody = $client->request('GET', $this->getConfigParam('jwks_uri'))->getBody();
            $json_keys = json_decode($responseBody, true);

            $key = reset($json_keys['keys']);

            $jwk = JWK::createFromJson(json_encode($key));

            $algorithmManager = AlgorithmManager::create([
                new HS256(), new HS384(), new HS512(), new ES256(), new ES384(), new ES512(),
                new RS256(), new RS384(), new RS512(), new PS256(), new PS384(), new PS512(),
            ]);

            $serializerManager = JWSSerializerManager::create([
                new CompactSerializer(),
            ]);

            $jwsVerifier = new JWSVerifier(
                $algorithmManager
            );

            $headerCheckerManager = HeaderCheckerManager::create(
                [new AlgorithmChecker($this->allowedJwsAlgorithms)],
                [new JWSTokenSupport()]
            );

            $jwsLoader = new JWSLoader(
                $serializerManager,
                $jwsVerifier,
                $headerCheckerManager
            );

            $jwsVerified = $jwsLoader->loadAndVerifyWithKey($token, $jwk, $signature);

            return json_decode($jwsVerified->getPayload(), true);
        } catch (Exception $e) {
            $message = YII_DEBUG ? 'Unable to verify JWS: ' . $e->getMessage() : 'Invalid JWS';
            throw new HttpException(400, $message, $e->getCode(), $e);
        }
    }
}