PHPackages                             issbox/yii2-jwt - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. issbox/yii2-jwt

ActiveYii2-extension[Authentication &amp; Authorization](/categories/authentication)

issbox/yii2-jwt
===============

JWT based on Icobucci

01PHP

Since Jun 29Pushed 1y ago1 watchersCompare

[ Source](https://github.com/jobsrey/yii2-jwt)[ Packagist](https://packagist.org/packages/issbox/yii2-jwt)[ RSS](/packages/issbox-yii2-jwt/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

Yii2 JWT
========

[](#yii2-jwt)

[![](https://camo.githubusercontent.com/6a869479b5b88051ec2dafa7987bb9283e76c691bd995ff9ccd35ccaed1436d6/68747470733a2f2f7472617669732d63692e6f72672f73697a65672f796969322d6a77742e737667)](https://camo.githubusercontent.com/6a869479b5b88051ec2dafa7987bb9283e76c691bd995ff9ccd35ccaed1436d6/68747470733a2f2f7472617669732d63692e6f72672f73697a65672f796969322d6a77742e737667)

This extension provides the [JWT](https://github.com/lcobucci/jwt) integration for the [Yii framework 2.0](http://www.yiiframework.com) (requires PHP 7.4 or ^8.0). It includes basic HTTP authentication support.

Table of contents
-----------------

[](#table-of-contents)

1. [Installation](#installation)
2. [Dependencies](#dependencies)
3. [Basic usage](#basicusage)
    1. [Creating](#basicusage-creating)
    2. [Parsing from strings](#basicusage-parsing)
    3. [Validating](#basicusage-validating)
4. [Token signature](#tokensign)
    1. [Hmac](#tokensign-hmac)
    2. [RSA and ECDSA](#tokensign-rsa-ecdsa)
5. [Yii2 basic template example](#yii2basic-example)

Installation
------------

[](#installation)

Package is available on [Packagist](https://packagist.org/packages/sizeg/yii2-jwt), you can install it using [Composer](http://getcomposer.org).

```
composer require sizeg/yii2-jwt
```

Dependencies
------------

[](#dependencies)

- PHP 7.4 or 8.0+
- OpenSSL Extension
- [lcobucci/jwt 4.2](https://github.com/lcobucci/jwt/tree/4.2.x)

[](#basicusage)

Basic usage
-----------

[](#basic-usage)

Add `jwt` component to your configuration file,

```
'components' => [
    'jwt' => [
        'class' => \sizeg\jwt\Jwt::class,
        'constraints' => [
            function () {
                return new \Lcobucci\JWT\Validation\Constraint\LooseValidAt(
                    \Lcobucci\Clock\SystemClock::fromSystemTimezone()
                );
            },
        ],
    ],
],
```

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` refer to a [doc](http://www.yiiframework.com/doc-2.0/guide-rest-authentication.html).

### Creating

[](#creating)

Just use the builder to create a new JWT/JWS tokens:

```
$now = new DateTimeImmutable();
$algorithm = $this->jwt->getSigner();
$key = $this->jwt->getSignerKey();

$token = Yii::$app->jwt->getBuilder()
   // Configures the issuer (iss claim)
   ->issuedBy('http://example.com')
   // Configures the audience (aud claim)
   ->permittedFor('http://example.org')
   // Configures the id (jti claim)
   ->identifiedBy('4f1g23a12aa')
   // 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->modify('+1 minute'))
   // Configures the expiration time of the token (exp claim)
   ->expiresAt($now->modify('+1 hour'))
   // Configures a new claim, called "uid"
   ->withClaim('uid', 1)
   // Configures a new header, called "foo"
   ->withHeader('foo', 'bar')
   // Builds a new token
   ->getToken($algorithm, $key);

$token->headers(); // Retrieves the token headers
$token->claims(); // Retrieves the token claims

echo $token->headers()->get('foo'); // will print "bar"
echo $token->claims()->get('jti'); // will print "4f1g23a12aa"
echo $token->claims()->get('iss'); // will print "http://example.com"
echo $token->claims()->get('uid'); // will print "1"
echo $token->toString(); // The string representation of the object is a JWT string (pretty easy, right?)
```

### Parsing from strings

[](#parsing-from-strings)

Use the parser to create a new token from a JWT string (using the previous token as example):

```
use Lcobucci\JWT\Encoding\CannotDecodeContent;
use Lcobucci\JWT\Token\InvalidTokenStructure;
use Lcobucci\JWT\Token\UnsupportedHeaderFound;
use Lcobucci\JWT\UnencryptedToken;

try {
    /** @var string $jwt JWT token string */
    $token = Yii::$app->jwt->parse($jwt); // Parses from a string
} catch (CannotDecodeContent | InvalidTokenStructure | UnsupportedHeaderFound $e) {
    echo 'Oh no, an error: ' . $e->getMessage();
}

assert($token instanceof UnencryptedToken);
```

### Validating

[](#validating)

We can easily validate if the token is valid (using the previous token as example):

```
use \Lcobucci\JWT\Validation\Constraint\IssuedBy;

if (!Yii::$app->jwt->validate($token, new IssuedBy('http://example.com'))) {
    echo 'Invalid token (1)!', PHP_EOL; // will not print this
}

if (!Yii::$app->jwt->validate($token, new IssuedBy('http://example.org'))) {
    echo 'Invalid token (1)!', PHP_EOL; // will print this
}
```

#### Available constraints

[](#available-constraints)

- `\Lcobucci\JWT\Validation\Constraint\IdentifiedBy`: verifies if the claim jti matches the expected value
- `\Lcobucci\JWT\Validation\Constraint\IssuedBy`: verifies if the claim iss is listed as expected values
- `\Lcobucci\JWT\Validation\Constraint\PermittedFor`: verifies if the claim aud contains the expected value
- `\Lcobucci\JWT\Validation\Constraint\RelatedTo`: verifies if the claim sub matches the expected value
- `\Lcobucci\JWT\Validation\Constraint\SignedWith`: verifies if the token was signed with the expected signer and key
- `\Lcobucci\JWT\Validation\Constraint\StrictValidAt`: verifies presence and validity of the claims iat, nbf, and exp (supports leeway configuration)
- `\Lcobucci\JWT\Validation\Constraint\LooseValidAt`: verifies the claims iat, nbf, and exp, when present (supports leeway configuration)
- `\Lcobucci\JWT\Validation\Constraint\HasClaimWithValue`: verifies that a custom claim has the expected value (not recommended when comparing cryptographic hashes)

#### Important

[](#important)

- You have to configure `\sizeg\jwt\Jwt::$constraints` informing all claims you want to validate the token by `Yii::$app->jwt->loadToken()`, this method also called inside `\sizeg\jwt\JwtHttpBearerAuth`.

Token signature
---------------

[](#token-signature)

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).

### Important

[](#important-1)

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](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries).

The examples below are safe because the choice in `Signer` is hard-coded and cannot be influenced by malicious users.

### Hmac

[](#hmac)

Hmac signatures are really simple to be used.

You may configure component:

```
'components' => [
    'jwt' => [
        'class' => \sizeg\jwt\Jwt::class,
        'signer' => \sizeg\jwt\JwtSigner::HS256,
        'signerKey' => \sizeg\jwt\JwtKey::PLAIN_TEXT,
        'signerKeyContents' => random_bytes(32),
        'signerKeyPassphrase' => 'secret',
        'constraints' => [
            function () {
                // Verifies the claims iat, nbf, and exp, when present (supports leeway configuration)
                return new \Lcobucci\JWT\Validation\Constraint\LooseValidAt(
                    \Lcobucci\Clock\SystemClock::fromSystemTimezone()
                );
            },
            function () {
                // Verifies if the token was signed with the expected signer and key
                return new \Lcobucci\JWT\Validation\Constraint\SignedWith(
                    Yii::$app->jwt->getSigner(),
                    Yii::$app->jwt->getSignerKey()
                );
            },
        ],
    ],
],
```

```
use \Lcobucci\JWT\Validation\Constraint\SignedWith;

$now = new DateTimeImmutable();

$algorithm = $this->jwt->getSigner(\sizeg\jwt\JwtSigner::HS256);
// ... and key
$contents = random_bytes(32);
$passphrase = 'secret';
$key = $this->jwt->getSignerKey(\sizeg\jwt\JwtKey::PLAIN_TEXT, $contents, $passphrase);

$token = Yii::$app->jwt->getBuilder()
    // Configures the issuer (iss claim)
    ->issuedBy('http://example.com')
    // Configures the audience (aud claim)
    ->permittedFor('http://example.org')
    // Configures the id (jti claim)
    ->identifiedBy('4f1g23a12aa')
    // 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->modify('+1 minute'))
    // Configures the expiration time of the token (exp claim)
    ->expiresAt($now->modify('+1 hour'))
    // Configures a new claim, called "uid"
    ->withClaim('uid', 1)
    // Configures a new header, called "foo"
    ->withHeader('foo', 'bar')
    // Builds a new token
    ->getToken($algorithm, $key);

if (!Yii::$app->jwt->validate($token, new SignedWith(
    Yii::$app->jwt->getSigner(\sizeg\jwt\JwtSigner::HS256),
    Yii::$app->jwt->getSignerKey(JwtKey::PLAIN_TEXT, $contents, $passphrase)
))) {
    echo 'Invalid token (1)!', PHP_EOL; // will not print this
}

if (!Yii::$app->jwt->validate($token, new SignedWith(
    Yii::$app->jwt->getSigner(\sizeg\jwt\JwtSigner::HS256),
    Yii::$app->jwt->getSignerKey(JwtKey::PLAIN_TEXT, random_bytes(32), 'other-secret')
))) {
    echo 'Invalid token (1)!', PHP_EOL; // will print this
}
```

### RSA and ECDSA

[](#rsa-and-ecdsa)

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:

```
use \Lcobucci\JWT\Validation\Constraint\SignedWith;

$now = new DateTimeImmutable();

// you can use 'ES256' if you're using ECDSA keys
$algorithm = Yii::$app->jwt->getSigner(\sizeg\jwt\JwtSigner::RS256);
$privateKey = Yii::$app->jwt->getSignerKey(\sizeg\jwt\JwtKey::FILE, 'file://{path to your private key}');

$token = Yii::$app->jwt->getBuilder()
    // Configures the issuer (iss claim)
    ->issuedBy('http://example.com')
    // Configures the audience (aud claim)
    ->permittedFor('http://example.org')
    // Configures the id (jti claim)
    ->identifiedBy('4f1g23a12aa')
    // 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->modify('+1 minute'))
    // Configures the expiration time of the token (exp claim)
    ->expiresAt($now->modify('+1 hour'))
    // Configures a new claim, called "uid"
    ->withClaim('uid', 1)
    // Configures a new header, called "foo"
    ->withHeader('foo', 'bar')
    // Builds a new token
    ->getToken($algorithm, $privateKey);

$publicKey = Yii::$app->jwt->getSignerKey(\sizeg\jwt\JwtKey::FILE, 'file://{path to your public key}');

var_dump(Yii::$app->jwt->validate($token, new SignedWith(
    Yii::$app->jwt->getSigner(\sizeg\jwt\JwtSigner::RS256),
    Yii::$app->jwt->getSignerKey(JwtKey::FILE, $publicKey)
))); // true when the public key was generated by the private one =)
```

**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!**

Yii2 basic template example
---------------------------

[](#yii2-basic-template-example)

### Basic scheme

[](#basic-scheme)

1. Client send credentials. For example, login + password
2. Backend validate them
3. If credentials is valid client receive token
4. Client store token for the future requests

### Step-by-step usage example

[](#step-by-step-usage-example)

1. Create Yii2 application

    In this example we will use [basic template](https://github.com/yiisoft/yii2-app-basic), but you can use [advanced template](https://github.com/yiisoft/yii2-app-advanced) in the same way.

    ```
    composer create-project --prefer-dist --stability=dev yiisoft/yii2-app-basic yii2-jwt-test
    ```
2. Install component

    ```
    composer require sizeg/yii2-jwt
    ```
3. Add to config/web.php into `components` section

    ```
    $config = [
        'components' => [
            // other default components here..
            'jwt' => [
                'class' => \sizeg\jwt\Jwt::class,
                'constraints' => [
                    function () {
                        return new \Lcobucci\JWT\Validation\Constraint\LooseValidAt(
                            \Lcobucci\Clock\SystemClock::fromSystemTimezone()
                        );
                    },
                ],
            ],
        ],
    ];
    ```
4. 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->claims()->get('uid')) {
                    return new static($user);
                }
            }

            return null;
        }
    ```
5. Create controller

    ```
