Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Paseto Laravel Package

paragonie/paseto

Reference PHP implementation of PASETO security tokens (v3/v4): safer alternative to JWT/JWE/JWS with modern crypto. Supports local and public tokens, includes PASERK integration for key serialization/wrapping, and works with Sodium (or sodium_compat).

View on GitHub
Deep Wiki
Context7

PASETO (PHP) Documentation

If you're not already familiar with PASETO, you can learn more about its features here. If you were using an older version of PASETO, the migration guide is worth a read.

Most of the supporting documentation has been moved to the PASETO specification repository.

How to use the PHP library

The first thing you should know about this library is it tries to accomplish type-safety by wrapping cryptographic keys inside of objects. For example:

<?php
use ParagonIE\Paseto\Keys\{Base\AsymmetricSecretKey,Base\SymmetricKey};

$privateKey = new AsymmetricSecretKey(sodium_crypto_sign_keypair());
$publicKey = $privateKey->getPublicKey();

$sharedKey = new SymmetricKey(random_bytes(32));

You can access the key's internal strings by invoking $key->raw().

Storing asymmetric keys

If you need to store the keys on your server, you can encode/decode the key.

<?php
use ParagonIE\Paseto\Keys\Base\{AsymmetricPublicKey, AsymmetricSecretKey};

$privateKey = new AsymmetricSecretKey(sodium_crypto_sign_keypair());
$publicKey = $privateKey->getPublicKey();

$privateKeyEncoded = $privateKey->encode();
$publicKeyEncoded = $publicKey->encode();

$privateKeyDecoded = AsymmetricSecretKey::fromEncodedString($privateKeyEncoded);
$publicKeyDecoded = AsymmetricPublicKey::fromEncodedString($publicKeyEncoded);

Or export as PEM format, and reimport from PEM.

<?php
use ParagonIE\Paseto\Keys\Base\{AsymmetricPublicKey, AsymmetricSecretKey};

$privateKey = new AsymmetricSecretKey(sodium_crypto_sign_keypair());
$publicKey = $privateKey->getPublicKey();

$privateKeyEncoded = $privateKey->encodePem();
$publicKeyEncoded = $publicKey->encodePem();

$privateKeyDecoded = AsymmetricSecretKey::importPem($privateKeyEncoded);
$publicKeyDecoded = AsymmetricPublicKey::importPem($publicKeyEncoded);

No version of the protocol will let you misuse a key by accident. This will generate a TypeError:

<?php
use ParagonIE\Paseto\Keys\Base\SymmetricKey;use ParagonIE\Paseto\Protocol\Version4;

/**
 * We assume the same key $sharedKey was used from above.
 * [@var](https://github.com/var) SymmetricKey $sharedKey
 */

$token = Version4::sign('some arbitrary data', $sharedKey);

Building and Verifying Pasetos

The simplest use-case is to use shared-key authentication to achieve tamper-resistant tokens:

<?php
use ParagonIE\Paseto\Builder;use ParagonIE\Paseto\Keys\Base\SymmetricKey;use ParagonIE\Paseto\Protocol\Version4;use ParagonIE\Paseto\Purpose;

/**
 * We assume the same key $sharedKey was used from above.
 * [@var](https://github.com/var) SymmetricKey $sharedKey
 */
$token = Builder::getLocal($sharedKey, new Version4);

$token = (new Builder())
    ->setKey($sharedKey)
    ->setVersion(new Version4)
    ->setPurpose(Purpose::local())
    // Set it to expire in one day
    ->setIssuedAt()
    ->setNotBefore()
    ->setExpiration(
        (new DateTime())->add(new DateInterval('P01D'))
    )
    // Store arbitrary data
    ->setClaims([
        'example' => 'Hello world',
        'security' => 'Now as easy as PIE'
    ]);
echo $token; // Converts automatically to a string

Decoding tokens

First, you need to define your Parser rules.

  • Which versions of the protocol do you wish to allow? If you're only using v2 in your app, you should specify this.
<?php
use ParagonIE\Paseto\Exception\PasetoException;use ParagonIE\Paseto\JsonToken;use ParagonIE\Paseto\Keys\Base\SymmetricKey;use ParagonIE\Paseto\Parser;use ParagonIE\Paseto\ProtocolCollection;use ParagonIE\Paseto\Purpose;use ParagonIE\Paseto\Rules\{IssuedBy,ValidAt};

/**
 * We assume the same key $sharedKey was used from above.
 * $providedToken is $token (as a string) from the previous snippet.
 *
 * [@var](https://github.com/var) string $providedToken
 * [@var](https://github.com/var) SymmetricKey $sharedKey
 */
$parser = Parser::getLocal($sharedKey, ProtocolCollection::v4())
    ->addRule(new ValidAt)
    ->addRule(new IssuedBy('issuer defined during creation'));

// This is the same as:
$parser = new Parser
    ->setKey($sharedKey)
    // Adding rules to be checked against the token
    ->addRule(new ValidAt)
    ->addRule(new IssuedBy('issuer defined during creation'))
    ->setPurpose(Purpose::local())
    // Only allow version 4
    ->setAllowedVersions(ProtocolCollection::v4());

try {
    $token = $parser->parse($providedToken);
} catch (PasetoException $ex) {
    /* Handle invalid token cases here. */
}
var_dump($token instanceof JsonToken);
// bool(true)

Key Rings

A key ring is a set of named cryptographic keys.

Support for key rings is totally optional. If you don't need them, don't build support for them in your application. If you do need support for them, we've provided a first-class implementation.

Key rings are useful for integrating with multiple third-party identity providers, or adding mechanisms to enforce key-rotation with a window of overlap between two keys.

Here's an example:

<?php
use ParagonIE\Paseto\Keys\Base\AsymmetricPublicKey;use ParagonIE\Paseto\Keys\Base\SymmetricKey;use ParagonIE\Paseto\Protocol\Version4;use ParagonIE\Paseto\Purpose;use ParagonIE\Paseto\ReceivingKeyRing;

/**
 * [@var](https://github.com/var) SymmetricKey $localKey
 * [@var](https://github.com/var) AsymmetricPublicKey $pk1
 * [@var](https://github.com/var) AsymmetricPublicKey $pk2
 */
$keyring = new ReceivingKeyRing
    ->setVersion(new Version4)
    ->setPurpose(Purpose::public())
    ->addKey('gandalf0', $pk1)
    ->addKey('legolas1', $pk2);

$otherKeyring = new ReceivingKeyRing
    ->setVersion(new Version4)
    ->setPurpose(Purpose::local())
    ->addKey('boromir2', $localKey);

As you can see, each KeyRing object can be locked down to a given version and purpose. If you try to add an AsymmetricPublicKey to $otherKeyring, it will throw an exception.

$otherKeyring->addKey('gandalf0', $pk1); // throws

There is also a SendingKeyRing class, which behaves mostly the same way as ReceivingKeyRing, but only allows Sending Keys (SymmetricKey, AsymmetricSecretKey).

Using Key Rings in Builders and Parsers

The Parser and Builder classes both support Key Rings without additional logic necessary. Users are only responsible for correctly configuring their Key Ring to specify which version and purpose is permitted.

<?php
use ParagonIE\Paseto\{
    Builder,
    Parser,
    ReceivingKeyRing,
    SendingKeyRing
};
/**
 * [@var](https://github.com/var) Builder $builder
 * [@var](https://github.com/var) Parser $parser
 * [@var](https://github.com/var) ReceivingKeyRing $rcvKeyRing
 * [@var](https://github.com/var) SendingKeyRing $sendKeyRing
 */

// Building a token with a SendingKeyRing
$builder->setKey($sendKeyRing);
$token = $builder->toString();

// Parsing a token with a ReceivingKeyRing
$parser->setKey($rcvKeyRing);
$valid = $parser->parse($token);
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
make-dev/orca
dmstr/symfony-system-resources-bundle
dmstr/symfony-job-queue-bundle
dmstr/openapi-json-schema-bundle
dmstr/keycloak-security-bundle
dmstr/doctrine-audit-log-bundle
dmstr/api-platform-utils-bundle
dmstr/api-configuration-bundle
chrisdev/ux-components
baks-dev/finances
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle