A simple Yii2 component to work with JSON Web Token and JSON Web Signature
A simple Yii2 component to work with JSON Web Token and JSON Web Signature
This extension provides the JWT integration for the Yii framework 2.0 (requires PHP 5.6+). It includes basic HTTP authentication support.
Package is available on Packagist, you can install it using Composer.
composer require sizeg/yii2-jwt
Add jwt component to your configuration file,
'components' => [
'jwt' => [
'class' => \sizeg\jwt\Jwt::class,
'key' => 'secret',
],
],
Configure the authenticator behavior as follows.
namespace app\controllers;
class ExampleController extends \yii\rest\Controller
{
/**
* @inheritdoc
*/
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => \sizeg\jwt\JwtHttpBearerAuth::class,
];
return $behaviors;
}
}
Also you can use it with CompositeAuth reffer to a doc.
Some methods marked as deprecated and will soon backport things from lcobucci/jwt 4.x to create an upgrade path.
Just use the builder to create a new JWT/JWS tokens:
…
Use the parser to create a new token from a JWT string (using the previous token as example):
$token = Yii::$app->jwt->getParser()->parse((string) $token); // Parses from a string
$token->getHeaders(); // Retrieves the token header
$token->getClaims(); // Retrieves the token claims
echo $token->getHeader('jti'); // will print "4f1g23a12aa"
echo $token->getClaim('iss'); // will print "http://example.com"
echo $token->getClaim('uid'); // will print "1"
We can easily validate if the token is valid (using the previous token as example):
…
We can also use the $leeway parameter to deal with clock skew (see notes below). If token's claimed time is invalid but the difference between that and the validation time is less than $leeway, then token is still considered valid
'components' => [
'jwt' => [
'class' => \sizeg\jwt\Jwt:class,
'key' => 'secret',
'jwtValidationData' => [
'class' => \sizeg\jwt\JwtValidationData::class,
// configure leeway
'leeway' => 20,
],
],
],
…
ValidationData informing all claims you want to validate the token.ValidationData contains claims that are not being used in token or token has claims that are not configured in ValidationData they will be ignored by Token::validate().exp, nbf and iat claims are configured by default in ValidationData::__construct() with the current UNIX time (time()).$leeway parameter of ValidationData will cause us to use that number of seconds of leeway when validating the time-based claims,
pretending we are further in the future for the "Issued At" (iat) and "Not Before" (nbf) claims and pretending we are further in the past
for the "Expiration Time" (exp) claim. This allows for situations where the clock of the issuing server has a different time than the clock
of the verifying server, as mentioned in section 4.1 of RFC 7519.We can use signatures to be able to verify if the token was not modified after its generation. This extension implements Hmac, RSA and ECDSA signatures (using 256, 384 and 512).
Do not allow the string sent to the Parser to dictate which signature algorithm to use, or else your application will be vulnerable to a critical JWT security vulnerability.
The examples below are safe because the choice in Signer is hard-coded and cannot be influenced by malicious users.
Hmac signatures are really simple to be used:
…
RSA and ECDSA signatures are based on public and private keys so you have to generate using the private key and verify using the public key:
…
It's important to say that if you're using RSA keys you shouldn't invoke ECDSA signers (and vice-versa), otherwise sign() and verify() will raise an exception!
Create Yii2 application
In this example we will use basic template, but you can use advanced template in the same way.
composer create-project --prefer-dist --stability=dev yiisoft/yii2-app-basic yii2-jwt-test
Install component
composer require sizeg/yii2-jwt
Add to config/web.php into components section
$config = [
'components' => [
// other default components here..
'jwt' => [
'class' => \sizeg\jwt\Jwt::class,
'key' => 'secret',
// You have to configure ValidationData informing all claims you want to validate the token.
'jwtValidationData' => \app\components\JwtValidationData::class,
],
],
];
Create JwtValidationData class. Where you have to configure ValidationData informing all claims you want to validate the token.
validationData->setIssuer('http://example.com');
$this->validationData->setAudience('http://example.org');
$this->validationData->setId('4f1g23a12aa');
parent::init();
}
}
Change method app\models\User::findIdentityByAccessToken()
/**
* {@inheritdoc}
* @param \Lcobucci\JWT\Token $token
*/
public static function findIdentityByAccessToken($token, $type = null)
{
foreach (self::$users as $user) {
if ($user['id'] === (string) $token->getClaim('uid')) {
return new static($user);
}
}
return null;
}
Create controller
…
Send simple login request to get token. Here we does not send any credentials to simplify example. As we specify in authenticator behavior action login as optional the authenticator skip auth check for that action.
First of all we try to send request to rest/data without token and getting error Unauthorized
Then we retry request but already adding Authorization header with our token
No open issues yet, or sync has not completed.