agielks / yii2-jwt
JWT based on Icobucci version 4.1
Installs: 1 439
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
Type:yii2-extension
Requires
- php: >=8.0
- lcobucci/jwt: ~4.1.0
- yiisoft/yii2: ~2.0.0
Requires (Dev)
- phpunit/phpunit: ~9.5.0
This package is auto-updated.
Last update: 2024-10-19 11:05:35 UTC
README
This extension provides the JWT integration for the Yii framework 2.0 (requires PHP 8.0+). It includes basic HTTP authentication support.
Table of contents
Instalation
Package is available on Packagist, you can install it using Composer.
composer require agielks/yii2-jwt ~1.0
or add to the require section of your composer.json
file.
"agielks/yii2-jwt": "~1.0"
Dependencies
- PHP 8.0+
- OpenSSL Extension
- Sodium Extension
- lcobucci/jwt 4.1
Basic Usage
Add jwt
component to your configuration file,
'components' => [ 'jwt' => [ 'class' => \agielks\yii2\jwt\Jwt::class, // 'singer' => new \Lcobucci\JWT\Signer\Hmac\Sha256(), 'signer' => 'HS256', // 'key' => \Lcobucci\JWT\Signer\Key\InMemory::plainText('my-key'), 'key' => 'my-key', , ], ],
Important: If you don't provide the signer and the key it will use unsecured signer
Configure the authenticator
behavior as follows.
namespace app\controllers; class SiteController extends \yii\rest\Controller { /** * @inheritdoc */ public function behaviors() { $behaviors = parent::behaviors(); $behaviors['authenticator'] = [ 'class' => \agielks\yii2\jwt\JwtBearerAuth::class, ]; return $behaviors; } }
Also you can use it with CompositeAuth
reffer to a doc.
Create Token
/* @var $jwt \agielks\yii2\jwt\Jwt */ $now = new DateTimeImmutable(); $jwt = Yii::$app->get('jwt'); $token = $jwt ->builder() // Configures the issuer (iss claim) ->issuedBy('http://example.com') // Configures the audience (aud claim) ->permittedFor('http://example.org') // Configures the id (jti claim) ->identifiedBy('62cbfaca6bf7e') // Configures the time that the token was issue (iat claim) ->issuedAt($now) // Configures the time that the token can be used (nbf claim) required for StrictValidAt constraint ->canOnlyBeUsedAfter($now) // Configures the expiration time of the token (exp claim) ->expiresAt($now->modify('+1 hour')) // Configures a new claim, called "uid" ->withClaim('uid', '62cbfaca6bf7e') // Configures a new header, called "foo" ->withHeader('foo', 'bar') // Builds a new token ->getToken($jwt->signer(), $jwt->key()); // Retrieves all headers $token->headers()->all(); // Retrives typ from headers $token->headers()->get('typ'); // Print typ from headers print_r($token->headers()->get('typ')); // Retrieves all claims $token->claims()->all(); // Retrieves jti from claims $token->claims()->get('jti'); // Print jti from claims print_r($token->claims()->get('jti'));
Parse Token From String
/* @var $jwt \agielks\yii2\jwt\Jwt */ $now = new DateTimeImmutable(); $jwt = Yii::$app->get('jwt'); $token = $jwt ->builder() // ... ->expiresAt($now->modify('+1 hour')) ->getToken($jwt->signer(), $jwt->key()) ->toString(); // Parse without validation $data = $jwt->config()->parser()->parse($token); // Parse with validation $data = $jwt->load($token); // Print all headers print_r($data->headers()->all()); // Print all claims print_r($data->claims()->all()); // Validate token var_dump($data->isExpired($now)); var_dump($data->isExpired($now->modify('+2 hour')));
Validate Token
You can configure your own validation with simple configuration in your component
use \agielks\yii2\jwt\Jwt; use \Lcobucci\JWT\Signer\Hmac\Sha256; use \Lcobucci\JWT\Signer\Key\InMemory; use \Lcobucci\JWT\Validation\Constraint\LooseValidAt; use \Lcobucci\JWT\Validation\Constraint\SignedWith; use \Lcobucci\JWT\Validation\Constraint\IdentifiedBy; use \Lcobucci\Clock\SystemClock; 'components' => [ 'jwt' => [ 'class' => Jwt::class, 'signer' => new Sha256(), 'key' => InMemory::plainText('my-key'), 'constraints' => [ new LooseValidAt(SystemClock::fromSystemTimezone()), new SignedWith( new Sha256(), InMemory::plainText('my-key') ), new IdentifiedBy('my-identity'), ], ], ],
Login Example
Basic scheme
- Client send credentials. For example, login + password
- App validate the credentials
- If credentials is valid client receive token
- Client store token for the future requests
Step by step usage
- Install component
composer require agielks/yii2-jwt ~1.0
- Update your components configuration
'components' => [ // other components here... 'jwt' => [ 'class' => \agielks\yii2\jwt\Jwt::class, // 'singer' => new \Lcobucci\JWT\Signer\Hmac\Sha256(), 'signer' => 'HS256', // 'key' => \Lcobucci\JWT\Signer\Key\InMemory::plainText('my-key'), 'key' => 'my-key', , ], // ... ],
- Change method
User::findIdentityByAccessToken()
/** * {@inheritdoc} * @param \Lcobucci\JWT\Token $token */ public static function findIdentityByAccessToken($token, $type = null) { return static::findOne(['id' => $token->claims()->get('uid')]); }
If you want to use auth_key as key, update method as follows
/** * {@inheritdoc} * @param \Lcobucci\JWT\Token $token */ public static function findIdentityByAccessToken($token, $type = null) { return static::findOne(['auth_key' => $token->claims()->get('auth_key')]); }
- Create controller
use agielks\yii2\jwt\JwtBearerAuth; // Use your own login form use common\models\LoginForm; use DateTimeImmutable; use Yii; use yii\base\InvalidConfigException; use yii\filters\Cors; use yii\rest\Controller; use yii\web\Response; /** * Class SiteController */ class SiteController extends Controller { /** * {@inheritdoc} */ public function behaviors() { $behaviors = parent::behaviors(); $behaviors['contentNegotiator']['formats']['text/html'] = Response::FORMAT_JSON; $behaviors['corsFilter'] = ['class' => Cors::class]; $behaviors['authenticator'] = [ 'class' => JwtBearerAuth::class, 'optional' => [ 'login', ], ]; return $behaviors; } /** * {@inheritdoc} */ protected function verbs() { return [ 'login' => ['OPTIONS', 'POST'], ]; } /** * @return array|LoginForm * @throws InvalidConfigException */ public function actionLogin() { $model = new LoginForm(); if ($model->load(Yii::$app->getRequest()->getBodyParams(), '') && $model->login()) { /* @var $jwt \agielks\yii2\jwt\Jwt */ $now = new DateTimeImmutable(); $jwt = Yii::$app->get('jwt'); $user = $model->getUser(); return $jwt ->builder() // Configures the issuer (iss claim) ->issuedBy('http://example.com') // Configures the audience (aud claim) ->permittedFor('http://example.org') // Configures the id (jti claim) ->identifiedBy($user->id) // Configures the time that the token was issue (iat claim) ->issuedAt($now) // Configures the time that the token can be used (nbf claim) ->canOnlyBeUsedAfter($now) // Configures the expiration time of the token (exp claim) ->expiresAt($now->modify('+1 hour')) // Configures a new claim, called "uid" ->withClaim('uid', $user->id) // Configures a new claim, called "auth_key" ->withClaim('auth_key', $user->auth_key) // Returns a signed token to be used ->getToken($jwt->signer(), $jwt->key()) // Convert token to string ->toString(); } $model->validate(); return $model; } /** * Test authentication */ public function actionTest() { return ['auth' => 'success']; } }