init commit

This commit is contained in:
zino
2021-02-16 23:07:41 +01:00
parent ec3fc78e0f
commit 12b4ef5db4
5000 changed files with 2596132 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
{
"require": {
"lcobucci/jwt": "^3.3"
}
}

73
libs/lcobucci/composer.lock generated Normal file
View File

@@ -0,0 +1,73 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "81b3a8e620ab0efb6ed4bffd419c467b",
"packages": [
{
"name": "lcobucci/jwt",
"version": "3.3.3",
"source": {
"type": "git",
"url": "https://github.com/lcobucci/jwt.git",
"reference": "c1123697f6a2ec29162b82f170dd4a491f524773"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/c1123697f6a2ec29162b82f170dd4a491f524773",
"reference": "c1123697f6a2ec29162b82f170dd4a491f524773",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"ext-openssl": "*",
"php": "^5.6 || ^7.0"
},
"require-dev": {
"mikey179/vfsstream": "~1.5",
"phpmd/phpmd": "~2.2",
"phpunit/php-invoker": "~1.1",
"phpunit/phpunit": "^5.7 || ^7.3",
"squizlabs/php_codesniffer": "~2.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"psr-4": {
"Lcobucci\\JWT\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Luís Otávio Cobucci Oblonczyk",
"email": "lcobucci@gmail.com",
"role": "Developer"
}
],
"description": "A simple library to work with JSON Web Token and JSON Web Signature",
"keywords": [
"JWS",
"jwt"
],
"time": "2020-08-20T13:22:28+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}

7
libs/lcobucci/vendor/autoload.php vendored Normal file
View File

@@ -0,0 +1,7 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit60686c30a05558fffaa1a4b9225ce7b4::getLoader();

View File

@@ -0,0 +1,445 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see http://www.php-fig.org/psr/psr-0/
* @see http://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
private $fallbackDirsPsr4 = array();
// PSR-0
private $prefixesPsr0 = array();
private $fallbackDirsPsr0 = array();
private $useIncludePath = false;
private $classMap = array();
private $classMapAuthoritative = false;
private $missingClasses = array();
private $apcuPrefix;
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', $this->prefixesPsr0);
}
return array();
}
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array $classMap Class to filename map
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 base directories
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
/**
* Unregisters this instance as an autoloader.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return bool|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*/
function includeFile($file)
{
include $file;
}

21
libs/lcobucci/vendor/composer/LICENSE vendored Normal file
View File

@@ -0,0 +1,21 @@
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,9 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

View File

@@ -0,0 +1,9 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

View File

@@ -0,0 +1,10 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Lcobucci\\JWT\\' => array($vendorDir . '/lcobucci/jwt/src'),
);

View File

@@ -0,0 +1,52 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit60686c30a05558fffaa1a4b9225ce7b4
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit60686c30a05558fffaa1a4b9225ce7b4', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit60686c30a05558fffaa1a4b9225ce7b4', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit60686c30a05558fffaa1a4b9225ce7b4::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
$loader->register(true);
return $loader;
}
}

View File

@@ -0,0 +1,31 @@
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInit60686c30a05558fffaa1a4b9225ce7b4
{
public static $prefixLengthsPsr4 = array (
'L' =>
array (
'Lcobucci\\JWT\\' => 13,
),
);
public static $prefixDirsPsr4 = array (
'Lcobucci\\JWT\\' =>
array (
0 => __DIR__ . '/..' . '/lcobucci/jwt/src',
),
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit60686c30a05558fffaa1a4b9225ce7b4::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit60686c30a05558fffaa1a4b9225ce7b4::$prefixDirsPsr4;
}, null, ClassLoader::class);
}
}

View File

@@ -0,0 +1,59 @@
[
{
"name": "lcobucci/jwt",
"version": "3.3.3",
"version_normalized": "3.3.3.0",
"source": {
"type": "git",
"url": "https://github.com/lcobucci/jwt.git",
"reference": "c1123697f6a2ec29162b82f170dd4a491f524773"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/c1123697f6a2ec29162b82f170dd4a491f524773",
"reference": "c1123697f6a2ec29162b82f170dd4a491f524773",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"ext-openssl": "*",
"php": "^5.6 || ^7.0"
},
"require-dev": {
"mikey179/vfsstream": "~1.5",
"phpmd/phpmd": "~2.2",
"phpunit/php-invoker": "~1.1",
"phpunit/phpunit": "^5.7 || ^7.3",
"squizlabs/php_codesniffer": "~2.3"
},
"time": "2020-08-20T13:22:28+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Lcobucci\\JWT\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Luís Otávio Cobucci Oblonczyk",
"email": "lcobucci@gmail.com",
"role": "Developer"
}
],
"description": "A simple library to work with JSON Web Token and JSON Web Signature",
"keywords": [
"JWS",
"jwt"
]
}
]

View File

@@ -0,0 +1,3 @@
/vendor
/phpunit.xml
/composer.lock

View File

@@ -0,0 +1,56 @@
build:
environment:
mysql: false
postgresql: false
redis: false
rabbitmq: false
php:
version: 5.6
tools:
php_sim: true
php_pdepend: true
php_analyzer: true
php_changetracking: true
php_code_sniffer:
config:
standard: "PSR2"
php_mess_detector: true
checks:
php:
code_rating: true
duplication: true
argument_type_checks: true
assignment_of_null_return: true
avoid_conflicting_incrementers: true
avoid_useless_overridden_methods: true
catch_class_exists: true
closure_use_modifiable: true
closure_use_not_conflicting: true
deprecated_code_usage: true
method_calls_on_non_object: true
missing_arguments: true
no_duplicate_arguments: true
no_non_implemented_abstract_methods: true
no_property_on_interface: true
parameter_non_unique: true
precedence_in_conditions: true
precedence_mistakes: true
require_php_tag_first: true
security_vulnerabilities: true
sql_injection_vulnerabilities: true
too_many_arguments: true
unreachable_code: true
unused_methods: true
unused_parameters: true
unused_properties: true
unused_variables: true
use_statement_alias_conflict: true
useless_calls: true
variable_existence: true
verify_access_scope_valid: true
verify_argument_usable_as_reference: true
verify_property_names: true
filter:
excluded_paths:
- test/*

View File

@@ -0,0 +1,15 @@
language: php
php:
- 5.6
- 7.0
- 7.1
- 7.2
- 7.3
- nightly
matrix:
allow_failures:
- php: nightly
before_script:
- composer install --prefer-dist -o

View File

@@ -0,0 +1,27 @@
Copyright (c) 2014-2015, Luís Otávio Cobucci Oblonczyk
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,194 @@
# JWT
[![Gitter](https://img.shields.io/badge/GITTER-JOIN%20CHAT%20%E2%86%92-brightgreen.svg?style=flat-square)](https://gitter.im/lcobucci/jwt?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Total Downloads](https://img.shields.io/packagist/dt/lcobucci/jwt.svg?style=flat-square)](https://packagist.org/packages/lcobucci/jwt) [![Latest Stable Version](https://img.shields.io/packagist/v/lcobucci/jwt.svg?style=flat-square)](https://packagist.org/packages/lcobucci/jwt)
![Branch master](https://img.shields.io/badge/branch-master-brightgreen.svg?style=flat-square)
[![Build Status](https://img.shields.io/travis/lcobucci/jwt/master.svg?style=flat-square)](http://travis-ci.org/#!/lcobucci/jwt)
[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/lcobucci/jwt/master.svg?style=flat-square)](https://scrutinizer-ci.com/g/lcobucci/jwt/?branch=master)
[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/lcobucci/jwt/master.svg?style=flat-square)](https://scrutinizer-ci.com/g/lcobucci/jwt/?branch=master)
A simple library to work with JSON Web Token and JSON Web Signature (requires PHP 5.6+).
The implementation is based on the [RFC 7519](https://tools.ietf.org/html/rfc7519).
## Installation
Package is available on [Packagist](http://packagist.org/packages/lcobucci/jwt),
you can install it using [Composer](http://getcomposer.org).
```shell
composer require lcobucci/jwt
```
### Dependencies
- PHP 5.6+
- OpenSSL Extension
## Basic usage
### Creating
Just use the builder to create a new JWT/JWS tokens:
```php
use Lcobucci\JWT\Builder;
$time = time();
$token = (new Builder())->issuedBy('http://example.com') // Configures the issuer (iss claim)
->permittedFor('http://example.org') // Configures the audience (aud claim)
->identifiedBy('4f1g23a12aa', true) // Configures the id (jti claim), replicating as a header item
->issuedAt($time) // Configures the time that the token was issue (iat claim)
->canOnlyBeUsedAfter($time + 60) // Configures the time that the token can be used (nbf claim)
->expiresAt($time + 3600) // Configures the expiration time of the token (exp claim)
->withClaim('uid', 1) // Configures a new claim, called "uid"
->getToken(); // Retrieves the generated token
$token->getHeaders(); // Retrieves the token headers
$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"
echo $token; // The string representation of the object is a JWT string (pretty easy, right?)
```
### Parsing from strings
Use the parser to create a new token from a JWT string (using the previous token as example):
```php
use Lcobucci\JWT\Parser;
$token = (new Parser())->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"
```
### Validating
We can easily validate if the token is valid (using the previous token and time as example):
```php
use Lcobucci\JWT\ValidationData;
$data = new ValidationData(); // It will use the current time to validate (iat, nbf and exp)
$data->setIssuer('http://example.com');
$data->setAudience('http://example.org');
$data->setId('4f1g23a12aa');
var_dump($token->validate($data)); // false, because token cannot be used before now() + 60
$data->setCurrentTime($time + 61); // changing the validation time to future
var_dump($token->validate($data)); // true, because current time is between "nbf" and "exp" claims
$data->setCurrentTime($time + 4000); // changing the validation time to future
var_dump($token->validate($data)); // false, because token is expired since current time is greater than exp
// 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
$dataWithLeeway = new ValidationData($time, 20);
$dataWithLeeway->setIssuer('http://example.com');
$dataWithLeeway->setAudience('http://example.org');
$dataWithLeeway->setId('4f1g23a12aa');
var_dump($token->validate($dataWithLeeway)); // false, because token can't be used before now() + 60, not within leeway
$dataWithLeeway->setCurrentTime($time + 51); // changing the validation time to future
var_dump($token->validate($dataWithLeeway)); // true, because current time plus leeway is between "nbf" and "exp" claims
$dataWithLeeway->setCurrentTime($time + 3610); // changing the validation time to future but within leeway
var_dump($token->validate($dataWithLeeway)); // true, because current time - 20 seconds leeway is less than exp
$dataWithLeeway->setCurrentTime($time + 4000); // changing the validation time to future outside of leeway
var_dump($token->validate($dataWithLeeway)); // false, because token is expired since current time is greater than exp
```
#### Important
- You have to configure ```ValidationData``` informing all claims you want to validate the token.
- If ```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()```).
- The optional ```$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](https://tools.ietf.org/html/rfc7519#section-4.1).
## Token signature
We can use signatures to be able to verify if the token was not modified after its generation. This library implements Hmac, RSA and ECDSA signatures (using 256, 384 and 512).
### Important
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 signatures are really simple to be used:
```php
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Hmac\Sha256;
$signer = new Sha256();
$time = time();
$token = (new Builder())->issuedBy('http://example.com') // Configures the issuer (iss claim)
->permittedFor('http://example.org') // Configures the audience (aud claim)
->identifiedBy('4f1g23a12aa', true) // Configures the id (jti claim), replicating as a header item
->issuedAt($time) // Configures the time that the token was issue (iat claim)
->canOnlyBeUsedAfter($time + 60) // Configures the time that the token can be used (nbf claim)
->expiresAt($time + 3600) // Configures the expiration time of the token (exp claim)
->withClaim('uid', 1) // Configures a new claim, called "uid"
->getToken($signer, new Key('testing')); // Retrieves the generated token
var_dump($token->verify($signer, 'testing 1')); // false, because the key is different
var_dump($token->verify($signer, 'testing')); // true, because the key is the same
```
### 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:
```php
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Rsa\Sha256; // you can use Lcobucci\JWT\Signer\Ecdsa\Sha256 if you're using ECDSA keys
$signer = new Sha256();
$privateKey = new Key('file://{path to your private key}');
$time = time();
$token = (new Builder())->issuedBy('http://example.com') // Configures the issuer (iss claim)
->permittedFor('http://example.org') // Configures the audience (aud claim)
->identifiedBy('4f1g23a12aa', true) // Configures the id (jti claim), replicating as a header item
->issuedAt($time) // Configures the time that the token was issue (iat claim)
->canOnlyBeUsedAfter($time + 60) // Configures the time that the token can be used (nbf claim)
->expiresAt($time + 3600) // Configures the expiration time of the token (exp claim)
->withClaim('uid', 1) // Configures a new claim, called "uid"
->getToken($signer, $privateKey); // Retrieves the generated token
$publicKey = new Key('file://{path to your public key}');
var_dump($token->verify($signer, $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!**

View File

@@ -0,0 +1,49 @@
{
"name": "lcobucci/jwt",
"description": "A simple library to work with JSON Web Token and JSON Web Signature",
"type": "library",
"authors": [
{
"name": "Luís Otávio Cobucci Oblonczyk",
"email": "lcobucci@gmail.com",
"role": "Developer"
}
],
"keywords": [
"JWT",
"JWS"
],
"license": [
"BSD-3-Clause"
],
"require": {
"php": "^5.6 || ^7.0",
"ext-mbstring": "*",
"ext-openssl": "*"
},
"require-dev": {
"phpunit/phpunit": "^5.7 || ^7.3",
"squizlabs/php_codesniffer": "~2.3",
"phpmd/phpmd": "~2.2",
"phpunit/php-invoker": "~1.1",
"mikey179/vfsstream": "~1.5"
},
"autoload": {
"psr-4": {
"Lcobucci\\JWT\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Lcobucci\\JWT\\": [
"test/unit",
"test/functional"
]
}
},
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
}
}

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
colors="true"
verbose="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
beStrictAboutChangesToGlobalState="true"
beStrictAboutCoversAnnotation="true"
beStrictAboutResourceUsageDuringSmallTests="true"
beStrictAboutTestsThatDoNotTestAnything="true"
forceCoversAnnotation="true">
<testsuites>
<testsuite name="Unit Test Suite">
<directory>test/unit</directory>
</testsuite>
<testsuite name="Integration Test Suite">
<directory>test/functional</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
</whitelist>
</filter>
</phpunit>

View File

@@ -0,0 +1,472 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT;
use Lcobucci\JWT\Claim\Factory as ClaimFactory;
use Lcobucci\JWT\Parsing\Encoder;
use Lcobucci\JWT\Signer\Key;
use function implode;
/**
* This class makes easier the token creation process
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
class Builder
{
/**
* The token header
*
* @var array
*/
private $headers = ['typ'=> 'JWT', 'alg' => 'none'];
/**
* The token claim set
*
* @var array
*/
private $claims = [];
/**
* The data encoder
*
* @var Encoder
*/
private $encoder;
/**
* The factory of claims
*
* @var ClaimFactory
*/
private $claimFactory;
/**
* @var Signer|null
*/
private $signer;
/**
* @var Key|null
*/
private $key;
/**
* Initializes a new builder
*
* @param Encoder $encoder
* @param ClaimFactory $claimFactory
*/
public function __construct(
Encoder $encoder = null,
ClaimFactory $claimFactory = null
) {
$this->encoder = $encoder ?: new Encoder();
$this->claimFactory = $claimFactory ?: new ClaimFactory();
}
/**
* Configures the audience
*
* @deprecated This method has been wrongly added and doesn't exist on v4
* @see Builder::permittedFor()
*
* @param string $audience
* @param bool $replicateAsHeader
*
* @return Builder
*/
public function canOnlyBeUsedBy($audience, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('aud', (string) $audience, $replicateAsHeader);
}
/**
* Configures the audience
*
* @param string $audience
* @param bool $replicateAsHeader
*
* @return Builder
*/
public function permittedFor($audience, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('aud', (string) $audience, $replicateAsHeader);
}
/**
* Configures the audience
*
* @deprecated This method will be removed on v4
* @see Builder::permittedFor()
*
* @param string $audience
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function setAudience($audience, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('aud', (string) $audience, $replicateAsHeader);
}
/**
* Configures the expiration time
*
* @param int $expiration
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function expiresAt($expiration, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('exp', (int) $expiration, $replicateAsHeader);
}
/**
* Configures the expiration time
*
* @deprecated This method will be removed on v4
* @see Builder::expiresAt()
*
* @param int $expiration
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function setExpiration($expiration, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('exp', (int) $expiration, $replicateAsHeader);
}
/**
* Configures the token id
*
* @param string $id
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function identifiedBy($id, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('jti', (string) $id, $replicateAsHeader);
}
/**
* Configures the token id
*
* @deprecated This method will be removed on v4
* @see Builder::identifiedBy()
*
* @param string $id
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function setId($id, $replicateAsHeader = false)
{
return $this->identifiedBy($id, $replicateAsHeader);
}
/**
* Configures the time that the token was issued
*
* @param int $issuedAt
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function issuedAt($issuedAt, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('iat', (int) $issuedAt, $replicateAsHeader);
}
/**
* Configures the time that the token was issued
*
* @deprecated This method will be removed on v4
* @see Builder::issuedAt()
*
* @param int $issuedAt
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function setIssuedAt($issuedAt, $replicateAsHeader = false)
{
return $this->issuedAt($issuedAt, $replicateAsHeader);
}
/**
* Configures the issuer
*
* @param string $issuer
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function issuedBy($issuer, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('iss', (string) $issuer, $replicateAsHeader);
}
/**
* Configures the issuer
*
* @deprecated This method will be removed on v4
* @see Builder::issuedBy()
*
* @param string $issuer
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function setIssuer($issuer, $replicateAsHeader = false)
{
return $this->issuedBy($issuer, $replicateAsHeader);
}
/**
* Configures the time before which the token cannot be accepted
*
* @param int $notBefore
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function canOnlyBeUsedAfter($notBefore, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('nbf', (int) $notBefore, $replicateAsHeader);
}
/**
* Configures the time before which the token cannot be accepted
*
* @deprecated This method will be removed on v4
* @see Builder::canOnlyBeUsedAfter()
*
* @param int $notBefore
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function setNotBefore($notBefore, $replicateAsHeader = false)
{
return $this->canOnlyBeUsedAfter($notBefore, $replicateAsHeader);
}
/**
* Configures the subject
*
* @param string $subject
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function relatedTo($subject, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('sub', (string) $subject, $replicateAsHeader);
}
/**
* Configures the subject
*
* @deprecated This method will be removed on v4
* @see Builder::relatedTo()
*
* @param string $subject
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function setSubject($subject, $replicateAsHeader = false)
{
return $this->relatedTo($subject, $replicateAsHeader);
}
/**
* Configures a registered claim
*
* @param string $name
* @param mixed $value
* @param boolean $replicate
*
* @return Builder
*/
protected function setRegisteredClaim($name, $value, $replicate)
{
$this->withClaim($name, $value);
if ($replicate) {
$this->headers[$name] = $this->claims[$name];
}
return $this;
}
/**
* Configures a header item
*
* @param string $name
* @param mixed $value
*
* @return Builder
*/
public function withHeader($name, $value)
{
$this->headers[(string) $name] = $this->claimFactory->create($name, $value);
return $this;
}
/**
* Configures a header item
*
* @deprecated This method will be removed on v4
* @see Builder::withHeader()
*
* @param string $name
* @param mixed $value
*
* @return Builder
*/
public function setHeader($name, $value)
{
return $this->withHeader($name, $value);
}
/**
* Configures a claim item
*
* @deprecated This method has been wrongly added and doesn't exist on v4
* @see Builder::withClaim()
*
* @param string $name
* @param mixed $value
*
* @return Builder
*/
public function with($name, $value)
{
return $this->withClaim($name, $value);
}
/**
* Configures a claim item
*
* @param string $name
* @param mixed $value
*
* @return Builder
*/
public function withClaim($name, $value)
{
$this->claims[(string) $name] = $this->claimFactory->create($name, $value);
return $this;
}
/**
* Configures a claim item
*
* @deprecated This method will be removed on v4
* @see Builder::withClaim()
*
* @param string $name
* @param mixed $value
*
* @return Builder
*/
public function set($name, $value)
{
return $this->withClaim($name, $value);
}
/**
* Signs the data
*
* @deprecated This method will be removed on v4
* @see Builder::getToken()
*
* @param Signer $signer
* @param Key|string $key
*
* @return Builder
*/
public function sign(Signer $signer, $key)
{
if (! $key instanceof Key) {
$key = new Key($key);
}
$this->signer = $signer;
$this->key = $key;
return $this;
}
/**
* Removes the signature from the builder
*
* @deprecated This method will be removed on v4
* @see Builder::getToken()
*
* @return Builder
*/
public function unsign()
{
$this->signer = null;
$this->key = null;
return $this;
}
/**
* Returns the resultant token
*
* @return Token
*/
public function getToken(Signer $signer = null, Key $key = null)
{
$signer = $signer ?: $this->signer;
$key = $key ?: $this->key;
if ($signer instanceof Signer) {
$signer->modifyHeader($this->headers);
}
$payload = [
$this->encoder->base64UrlEncode($this->encoder->jsonEncode($this->headers)),
$this->encoder->base64UrlEncode($this->encoder->jsonEncode($this->claims))
];
$signature = $this->createSignature($payload, $signer, $key);
if ($signature !== null) {
$payload[] = $this->encoder->base64UrlEncode($signature);
}
return new Token($this->headers, $this->claims, $signature, $payload);
}
/**
* @param string[] $payload
*
* @return Signature|null
*/
private function createSignature(array $payload, Signer $signer = null, Key $key = null)
{
if ($signer === null || $key === null) {
return null;
}
return $signer->sign(implode('.', $payload), $key);
}
}

View File

@@ -0,0 +1,40 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT;
use JsonSerializable;
/**
* Basic interface for token claims
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/
interface Claim extends JsonSerializable
{
/**
* Returns the claim name
*
* @return string
*/
public function getName();
/**
* Returns the claim value
*
* @return mixed
*/
public function getValue();
/**
* Returns the string representation of the claim
*
* @return string
*/
public function __toString();
}

View File

@@ -0,0 +1,75 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Claim;
use Lcobucci\JWT\Claim;
/**
* The default claim
*
* @deprecated This class will be removed on v4
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/
class Basic implements Claim
{
/**
* @var string
*/
private $name;
/**
* @var mixed
*/
private $value;
/**
* Initializes the claim
*
* @param string $name
* @param mixed $value
*/
public function __construct($name, $value)
{
$this->name = $name;
$this->value = $value;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->name;
}
/**
* {@inheritdoc}
*/
public function getValue()
{
return $this->value;
}
/**
* {@inheritdoc}
*/
public function jsonSerialize()
{
return $this->value;
}
/**
* {@inheritdoc}
*/
public function __toString()
{
return (string) $this->value;
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Claim;
use Lcobucci\JWT\Claim;
use Lcobucci\JWT\ValidationData;
/**
* Validatable claim that checks if value is strictly equals to the given data
*
* @deprecated This class will be removed on v4
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/
class EqualsTo extends Basic implements Claim, Validatable
{
/**
* {@inheritdoc}
*/
public function validate(ValidationData $data)
{
if ($data->has($this->getName())) {
return $this->getValue() === $data->get($this->getName());
}
return true;
}
}

View File

@@ -0,0 +1,118 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Claim;
use Lcobucci\JWT\Claim;
/**
* Class that create claims
*
* @deprecated This class will be removed on v4
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/
class Factory
{
/**
* The list of claim callbacks
*
* @var array
*/
private $callbacks;
/**
* Initializes the factory, registering the default callbacks
*
* @param array $callbacks
*/
public function __construct(array $callbacks = [])
{
$this->callbacks = array_merge(
[
'iat' => [$this, 'createLesserOrEqualsTo'],
'nbf' => [$this, 'createLesserOrEqualsTo'],
'exp' => [$this, 'createGreaterOrEqualsTo'],
'iss' => [$this, 'createEqualsTo'],
'aud' => [$this, 'createEqualsTo'],
'sub' => [$this, 'createEqualsTo'],
'jti' => [$this, 'createEqualsTo']
],
$callbacks
);
}
/**
* Create a new claim
*
* @param string $name
* @param mixed $value
*
* @return Claim
*/
public function create($name, $value)
{
if (!empty($this->callbacks[$name])) {
return call_user_func($this->callbacks[$name], $name, $value);
}
return $this->createBasic($name, $value);
}
/**
* Creates a claim that can be compared (greator or equals)
*
* @param string $name
* @param mixed $value
*
* @return GreaterOrEqualsTo
*/
private function createGreaterOrEqualsTo($name, $value)
{
return new GreaterOrEqualsTo($name, $value);
}
/**
* Creates a claim that can be compared (greator or equals)
*
* @param string $name
* @param mixed $value
*
* @return LesserOrEqualsTo
*/
private function createLesserOrEqualsTo($name, $value)
{
return new LesserOrEqualsTo($name, $value);
}
/**
* Creates a claim that can be compared (equals)
*
* @param string $name
* @param mixed $value
*
* @return EqualsTo
*/
private function createEqualsTo($name, $value)
{
return new EqualsTo($name, $value);
}
/**
* Creates a basic claim
*
* @param string $name
* @param mixed $value
*
* @return Basic
*/
private function createBasic($name, $value)
{
return new Basic($name, $value);
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Claim;
use Lcobucci\JWT\Claim;
use Lcobucci\JWT\ValidationData;
/**
* Validatable claim that checks if value is greater or equals the given data
*
* @deprecated This class will be removed on v4
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/
class GreaterOrEqualsTo extends Basic implements Claim, Validatable
{
/**
* {@inheritdoc}
*/
public function validate(ValidationData $data)
{
if ($data->has($this->getName())) {
return $this->getValue() >= $data->get($this->getName());
}
return true;
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Claim;
use Lcobucci\JWT\Claim;
use Lcobucci\JWT\ValidationData;
/**
* Validatable claim that checks if value is lesser or equals to the given data
*
* @deprecated This class will be removed on v4
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/
class LesserOrEqualsTo extends Basic implements Claim, Validatable
{
/**
* {@inheritdoc}
*/
public function validate(ValidationData $data)
{
if ($data->has($this->getName())) {
return $this->getValue() <= $data->get($this->getName());
}
return true;
}
}

View File

@@ -0,0 +1,30 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Claim;
use Lcobucci\JWT\ValidationData;
/**
* Basic interface for validatable token claims
*
* @deprecated This interface will be removed on v4
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/
interface Validatable
{
/**
* Returns if claim is valid according with given data
*
* @param ValidationData $data
*
* @return boolean
*/
public function validate(ValidationData $data);
}

View File

@@ -0,0 +1,157 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT;
use InvalidArgumentException;
use Lcobucci\JWT\Claim\Factory as ClaimFactory;
use Lcobucci\JWT\Parsing\Decoder;
/**
* This class parses the JWT strings and convert them into tokens
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
class Parser
{
/**
* The data decoder
*
* @var Decoder
*/
private $decoder;
/**
* The claims factory
*
* @var ClaimFactory
*/
private $claimFactory;
/**
* Initializes the object
*
* @param Decoder $decoder
* @param ClaimFactory $claimFactory
*/
public function __construct(
Decoder $decoder = null,
ClaimFactory $claimFactory = null
) {
$this->decoder = $decoder ?: new Decoder();
$this->claimFactory = $claimFactory ?: new ClaimFactory();
}
/**
* Parses the JWT and returns a token
*
* @param string $jwt
*
* @return Token
*/
public function parse($jwt)
{
$data = $this->splitJwt($jwt);
$header = $this->parseHeader($data[0]);
$claims = $this->parseClaims($data[1]);
$signature = $this->parseSignature($header, $data[2]);
foreach ($claims as $name => $value) {
if (isset($header[$name])) {
$header[$name] = $value;
}
}
if ($signature === null) {
unset($data[2]);
}
return new Token($header, $claims, $signature, $data);
}
/**
* Splits the JWT string into an array
*
* @param string $jwt
*
* @return array
*
* @throws InvalidArgumentException When JWT is not a string or is invalid
*/
protected function splitJwt($jwt)
{
if (!is_string($jwt)) {
throw new InvalidArgumentException('The JWT string must have two dots');
}
$data = explode('.', $jwt);
if (count($data) != 3) {
throw new InvalidArgumentException('The JWT string must have two dots');
}
return $data;
}
/**
* Parses the header from a string
*
* @param string $data
*
* @return array
*
* @throws InvalidArgumentException When an invalid header is informed
*/
protected function parseHeader($data)
{
$header = (array) $this->decoder->jsonDecode($this->decoder->base64UrlDecode($data));
if (isset($header['enc'])) {
throw new InvalidArgumentException('Encryption is not supported yet');
}
return $header;
}
/**
* Parses the claim set from a string
*
* @param string $data
*
* @return array
*/
protected function parseClaims($data)
{
$claims = (array) $this->decoder->jsonDecode($this->decoder->base64UrlDecode($data));
foreach ($claims as $name => &$value) {
$value = $this->claimFactory->create($name, $value);
}
return $claims;
}
/**
* Returns the signature from given data
*
* @param array $header
* @param string $data
*
* @return Signature
*/
protected function parseSignature(array $header, $data)
{
if ($data == '' || !isset($header['alg']) || $header['alg'] == 'none') {
return null;
}
$hash = $this->decoder->base64UrlDecode($data);
return new Signature($hash);
}
}

View File

@@ -0,0 +1,56 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Parsing;
use RuntimeException;
/**
* Class that decodes data according with the specs of RFC-4648
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*
* @link http://tools.ietf.org/html/rfc4648#section-5
*/
class Decoder
{
/**
* Decodes from JSON, validating the errors (will return an associative array
* instead of objects)
*
* @param string $json
* @return mixed
*
* @throws RuntimeException When something goes wrong while decoding
*/
public function jsonDecode($json)
{
$data = json_decode($json);
if (json_last_error() != JSON_ERROR_NONE) {
throw new RuntimeException('Error while decoding to JSON: ' . json_last_error_msg());
}
return $data;
}
/**
* Decodes from base64url
*
* @param string $data
* @return string
*/
public function base64UrlDecode($data)
{
if ($remainder = strlen($data) % 4) {
$data .= str_repeat('=', 4 - $remainder);
}
return base64_decode(strtr($data, '-_', '+/'));
}
}

View File

@@ -0,0 +1,51 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Parsing;
use RuntimeException;
/**
* Class that encodes data according with the specs of RFC-4648
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*
* @link http://tools.ietf.org/html/rfc4648#section-5
*/
class Encoder
{
/**
* Encodes to JSON, validating the errors
*
* @param mixed $data
* @return string
*
* @throws RuntimeException When something goes wrong while encoding
*/
public function jsonEncode($data)
{
$json = json_encode($data);
if (json_last_error() != JSON_ERROR_NONE) {
throw new RuntimeException('Error while encoding to JSON: ' . json_last_error_msg());
}
return $json;
}
/**
* Encodes to base64url
*
* @param string $data
* @return string
*/
public function base64UrlEncode($data)
{
return str_replace('=', '', strtr(base64_encode($data), '+/', '-_'));
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT;
use Lcobucci\JWT\Signer\Key;
/**
* This class represents a token signature
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
class Signature
{
/**
* The resultant hash
*
* @var string
*/
protected $hash;
/**
* Initializes the object
*
* @param string $hash
*/
public function __construct($hash)
{
$this->hash = $hash;
}
/**
* Verifies if the current hash matches with with the result of the creation of
* a new signature with given data
*
* @param Signer $signer
* @param string $payload
* @param Key|string $key
*
* @return boolean
*/
public function verify(Signer $signer, $payload, $key)
{
return $signer->verify($this->hash, $payload, $key);
}
/**
* Returns the current hash as a string representation of the signature
*
* @return string
*/
public function __toString()
{
return $this->hash;
}
}

View File

@@ -0,0 +1,59 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT;
use InvalidArgumentException;
use Lcobucci\JWT\Signer\Key;
/**
* Basic interface for token signers
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
interface Signer
{
/**
* Returns the algorithm id
*
* @return string
*/
public function getAlgorithmId();
/**
* Apply changes on headers according with algorithm
*
* @param array $headers
*/
public function modifyHeader(array &$headers);
/**
* Returns a signature for given data
*
* @param string $payload
* @param Key|string $key
*
* @return Signature
*
* @throws InvalidArgumentException When given key is invalid
*/
public function sign($payload, $key);
/**
* Returns if the expected hash matches with the data and key
*
* @param string $expected
* @param string $payload
* @param Key|string $key
*
* @return boolean
*
* @throws InvalidArgumentException When given key is invalid
*/
public function verify($expected, $payload, $key);
}

View File

@@ -0,0 +1,85 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer;
use Lcobucci\JWT\Signature;
use Lcobucci\JWT\Signer;
/**
* Base class for signers
*
* @deprecated This class will be removed on v4
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
abstract class BaseSigner implements Signer
{
/**
* {@inheritdoc}
*/
public function modifyHeader(array &$headers)
{
$headers['alg'] = $this->getAlgorithmId();
}
/**
* {@inheritdoc}
*/
public function sign($payload, $key)
{
return new Signature($this->createHash($payload, $this->getKey($key)));
}
/**
* {@inheritdoc}
*/
public function verify($expected, $payload, $key)
{
return $this->doVerify($expected, $payload, $this->getKey($key));
}
/**
* @param Key|string $key
*
* @return Key
*/
private function getKey($key)
{
if (is_string($key)) {
$key = new Key($key);
}
return $key;
}
/**
* Creates a hash with the given data
*
* @internal
*
* @param string $payload
* @param Key $key
*
* @return string
*/
abstract public function createHash($payload, Key $key);
/**
* Performs the signature verification
*
* @internal
*
* @param string $expected
* @param string $payload
* @param Key $key
*
* @return boolean
*/
abstract public function doVerify($expected, $payload, Key $key);
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer;
use Lcobucci\JWT\Signer\Ecdsa\MultibyteStringConverter;
use Lcobucci\JWT\Signer\Ecdsa\SignatureConverter;
use const OPENSSL_KEYTYPE_EC;
/**
* Base class for ECDSA signers
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
abstract class Ecdsa extends OpenSSL
{
/**
* @var SignatureConverter
*/
private $converter;
public function __construct(SignatureConverter $converter = null)
{
$this->converter = $converter ?: new MultibyteStringConverter();
}
/**
* {@inheritdoc}
*/
public function createHash($payload, Key $key)
{
return $this->converter->fromAsn1(
parent::createHash($payload, $key),
$this->getKeyLength()
);
}
/**
* {@inheritdoc}
*/
public function doVerify($expected, $payload, Key $key)
{
return parent::doVerify(
$this->converter->toAsn1($expected, $this->getKeyLength()),
$payload,
$key
);
}
/**
* Returns the length of each point in the signature, so that we can calculate and verify R and S points properly
*
* @internal
*/
abstract public function getKeyLength();
/**
* {@inheritdoc}
*/
final public function getKeyType()
{
return OPENSSL_KEYTYPE_EC;
}
}

View File

@@ -0,0 +1,134 @@
<?php
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2018 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*
* @link https://github.com/web-token/jwt-framework/blob/v1.2/src/Component/Core/Util/ECSignature.php
*/
namespace Lcobucci\JWT\Signer\Ecdsa;
use InvalidArgumentException;
use function bin2hex;
use function dechex;
use function hex2bin;
use function hexdec;
use function mb_strlen;
use function mb_substr;
use function str_pad;
use const STR_PAD_LEFT;
/**
* ECDSA signature converter using ext-mbstring
*
* @internal
*/
final class MultibyteStringConverter implements SignatureConverter
{
const ASN1_SEQUENCE = '30';
const ASN1_INTEGER = '02';
const ASN1_MAX_SINGLE_BYTE = 128;
const ASN1_LENGTH_2BYTES = '81';
const ASN1_BIG_INTEGER_LIMIT = '7f';
const ASN1_NEGATIVE_INTEGER = '00';
const BYTE_SIZE = 2;
public function toAsn1($signature, $length)
{
$signature = bin2hex($signature);
if (self::octetLength($signature) !== $length) {
throw new InvalidArgumentException('Invalid signature length.');
}
$pointR = self::preparePositiveInteger(mb_substr($signature, 0, $length, '8bit'));
$pointS = self::preparePositiveInteger(mb_substr($signature, $length, null, '8bit'));
$lengthR = self::octetLength($pointR);
$lengthS = self::octetLength($pointS);
$totalLength = $lengthR + $lengthS + self::BYTE_SIZE + self::BYTE_SIZE;
$lengthPrefix = $totalLength > self::ASN1_MAX_SINGLE_BYTE ? self::ASN1_LENGTH_2BYTES : '';
$asn1 = hex2bin(
self::ASN1_SEQUENCE
. $lengthPrefix . dechex($totalLength)
. self::ASN1_INTEGER . dechex($lengthR) . $pointR
. self::ASN1_INTEGER . dechex($lengthS) . $pointS
);
return $asn1;
}
private static function octetLength($data)
{
return (int) (mb_strlen($data, '8bit') / self::BYTE_SIZE);
}
private static function preparePositiveInteger($data)
{
if (mb_substr($data, 0, self::BYTE_SIZE, '8bit') > self::ASN1_BIG_INTEGER_LIMIT) {
return self::ASN1_NEGATIVE_INTEGER . $data;
}
while (mb_substr($data, 0, self::BYTE_SIZE, '8bit') === self::ASN1_NEGATIVE_INTEGER
&& mb_substr($data, 2, self::BYTE_SIZE, '8bit') <= self::ASN1_BIG_INTEGER_LIMIT) {
$data = mb_substr($data, 2, null, '8bit');
}
return $data;
}
public function fromAsn1($signature, $length)
{
$message = bin2hex($signature);
$position = 0;
if (self::readAsn1Content($message, $position, self::BYTE_SIZE) !== self::ASN1_SEQUENCE) {
throw new InvalidArgumentException('Invalid data. Should start with a sequence.');
}
if (self::readAsn1Content($message, $position, self::BYTE_SIZE) === self::ASN1_LENGTH_2BYTES) {
$position += self::BYTE_SIZE;
}
$pointR = self::retrievePositiveInteger(self::readAsn1Integer($message, $position));
$pointS = self::retrievePositiveInteger(self::readAsn1Integer($message, $position));
$points = hex2bin(str_pad($pointR, $length, '0', STR_PAD_LEFT) . str_pad($pointS, $length, '0', STR_PAD_LEFT));
return $points;
}
private static function readAsn1Content($message, &$position, $length)
{
$content = mb_substr($message, $position, $length, '8bit');
$position += $length;
return $content;
}
private static function readAsn1Integer($message, &$position)
{
if (self::readAsn1Content($message, $position, self::BYTE_SIZE) !== self::ASN1_INTEGER) {
throw new InvalidArgumentException('Invalid data. Should contain an integer.');
}
$length = (int) hexdec(self::readAsn1Content($message, $position, self::BYTE_SIZE));
return self::readAsn1Content($message, $position, $length * self::BYTE_SIZE);
}
private static function retrievePositiveInteger($data)
{
while (mb_substr($data, 0, self::BYTE_SIZE, '8bit') === self::ASN1_NEGATIVE_INTEGER
&& mb_substr($data, 2, self::BYTE_SIZE, '8bit') > self::ASN1_BIG_INTEGER_LIMIT) {
$data = mb_substr($data, 2, null, '8bit');
}
return $data;
}
}

View File

@@ -0,0 +1,43 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer\Ecdsa;
use Lcobucci\JWT\Signer\Ecdsa;
/**
* Signer for ECDSA SHA-256
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
class Sha256 extends Ecdsa
{
/**
* {@inheritdoc}
*/
public function getAlgorithmId()
{
return 'ES256';
}
/**
* {@inheritdoc}
*/
public function getAlgorithm()
{
return 'sha256';
}
/**
* {@inheritdoc}
*/
public function getKeyLength()
{
return 64;
}
}

View File

@@ -0,0 +1,43 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer\Ecdsa;
use Lcobucci\JWT\Signer\Ecdsa;
/**
* Signer for ECDSA SHA-384
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
class Sha384 extends Ecdsa
{
/**
* {@inheritdoc}
*/
public function getAlgorithmId()
{
return 'ES384';
}
/**
* {@inheritdoc}
*/
public function getAlgorithm()
{
return 'sha384';
}
/**
* {@inheritdoc}
*/
public function getKeyLength()
{
return 96;
}
}

View File

@@ -0,0 +1,43 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer\Ecdsa;
use Lcobucci\JWT\Signer\Ecdsa;
/**
* Signer for ECDSA SHA-512
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
class Sha512 extends Ecdsa
{
/**
* {@inheritdoc}
*/
public function getAlgorithmId()
{
return 'ES512';
}
/**
* {@inheritdoc}
*/
public function getAlgorithm()
{
return 'sha512';
}
/**
* {@inheritdoc}
*/
public function getKeyLength()
{
return 132;
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace Lcobucci\JWT\Signer\Ecdsa;
/**
* Manipulates the result of a ECDSA signature (points R and S) according to the
* JWA specs.
*
* OpenSSL creates a signature using the ASN.1 format and, according the JWA specs,
* the signature for JWTs must be the concatenated values of points R and S (in
* big-endian octet order).
*
* @internal
*
* @see https://tools.ietf.org/html/rfc7518#page-9
* @see https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One
*/
interface SignatureConverter
{
/**
* Converts the signature generated by OpenSSL into what JWA defines
*
* @param string $signature
* @param int $length
*
* @return string
*/
public function fromAsn1($signature, $length);
/**
* Converts the JWA signature into something OpenSSL understands
*
* @param string $points
* @param int $length
*
* @return string
*/
public function toAsn1($points, $length);
}

View File

@@ -0,0 +1,75 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer;
/**
* Base class for hmac signers
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
abstract class Hmac extends BaseSigner
{
/**
* {@inheritdoc}
*/
public function createHash($payload, Key $key)
{
return hash_hmac($this->getAlgorithm(), $payload, $key->getContent(), true);
}
/**
* {@inheritdoc}
*/
public function doVerify($expected, $payload, Key $key)
{
if (!is_string($expected)) {
return false;
}
$callback = function_exists('hash_equals') ? 'hash_equals' : [$this, 'hashEquals'];
return call_user_func($callback, $expected, $this->createHash($payload, $key));
}
/**
* PHP < 5.6 timing attack safe hash comparison
*
* @internal
*
* @param string $expected
* @param string $generated
*
* @return boolean
*/
public function hashEquals($expected, $generated)
{
$expectedLength = strlen($expected);
if ($expectedLength !== strlen($generated)) {
return false;
}
$res = 0;
for ($i = 0; $i < $expectedLength; ++$i) {
$res |= ord($expected[$i]) ^ ord($generated[$i]);
}
return $res === 0;
}
/**
* Returns the algorithm name
*
* @internal
*
* @return string
*/
abstract public function getAlgorithm();
}

View File

@@ -0,0 +1,35 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer\Hmac;
use Lcobucci\JWT\Signer\Hmac;
/**
* Signer for HMAC SHA-256
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
class Sha256 extends Hmac
{
/**
* {@inheritdoc}
*/
public function getAlgorithmId()
{
return 'HS256';
}
/**
* {@inheritdoc}
*/
public function getAlgorithm()
{
return 'sha256';
}
}

View File

@@ -0,0 +1,35 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer\Hmac;
use Lcobucci\JWT\Signer\Hmac;
/**
* Signer for HMAC SHA-384
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
class Sha384 extends Hmac
{
/**
* {@inheritdoc}
*/
public function getAlgorithmId()
{
return 'HS384';
}
/**
* {@inheritdoc}
*/
public function getAlgorithm()
{
return 'sha384';
}
}

View File

@@ -0,0 +1,35 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer\Hmac;
use Lcobucci\JWT\Signer\Hmac;
/**
* Signer for HMAC SHA-512
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
class Sha512 extends Hmac
{
/**
* {@inheritdoc}
*/
public function getAlgorithmId()
{
return 'HS512';
}
/**
* {@inheritdoc}
*/
public function getAlgorithm()
{
return 'sha512';
}
}

View File

@@ -0,0 +1,92 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer;
use Exception;
use InvalidArgumentException;
use SplFileObject;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 3.0.4
*/
final class Key
{
/**
* @var string
*/
private $content;
/**
* @var string
*/
private $passphrase;
/**
* @param string $content
* @param string $passphrase
*/
public function __construct($content, $passphrase = null)
{
$this->setContent($content);
$this->passphrase = $passphrase;
}
/**
* @param string $content
*
* @throws InvalidArgumentException
*/
private function setContent($content)
{
if (strpos($content, 'file://') === 0) {
$content = $this->readFile($content);
}
$this->content = $content;
}
/**
* @param string $content
*
* @return string
*
* @throws InvalidArgumentException
*/
private function readFile($content)
{
try {
$file = new SplFileObject(substr($content, 7));
$content = '';
while (! $file->eof()) {
$content .= $file->fgets();
}
return $content;
} catch (Exception $exception) {
throw new InvalidArgumentException('You must provide a valid key file', 0, $exception);
}
}
/**
* @return string
*/
public function getContent()
{
return $this->content;
}
/**
* @return string
*/
public function getPassphrase()
{
return $this->passphrase;
}
}

View File

@@ -0,0 +1,44 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer;
/**
* A utilitarian class that encapsulates the retrieval of public and private keys
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*
* @deprecated Since we've removed OpenSSL from ECDSA there's no reason to use this class
*/
class Keychain
{
/**
* Returns a private key from file path or content
*
* @param string $key
* @param string $passphrase
*
* @return Key
*/
public function getPrivateKey($key, $passphrase = null)
{
return new Key($key, $passphrase);
}
/**
* Returns a public key from file path or content
*
* @param string $certificate
*
* @return Key
*/
public function getPublicKey($certificate)
{
return new Key($certificate);
}
}

View File

@@ -0,0 +1,115 @@
<?php
namespace Lcobucci\JWT\Signer;
use InvalidArgumentException;
use Lcobucci\JWT\Signer;
use function assert;
use function is_array;
use function is_resource;
use function openssl_error_string;
use function openssl_free_key;
use function openssl_pkey_get_details;
use function openssl_pkey_get_private;
use function openssl_pkey_get_public;
use function openssl_sign;
use function openssl_verify;
abstract class OpenSSL extends BaseSigner
{
public function createHash($payload, Key $key)
{
$privateKey = $this->getPrivateKey($key->getContent(), $key->getPassphrase());
try {
$signature = '';
if (! openssl_sign($payload, $signature, $privateKey, $this->getAlgorithm())) {
throw new InvalidArgumentException(
'There was an error while creating the signature: ' . openssl_error_string()
);
}
return $signature;
} finally {
openssl_free_key($privateKey);
}
}
/**
* @param string $pem
* @param string $passphrase
*
* @return resource
*/
private function getPrivateKey($pem, $passphrase)
{
$privateKey = openssl_pkey_get_private($pem, $passphrase);
$this->validateKey($privateKey);
return $privateKey;
}
/**
* @param $expected
* @param $payload
* @param $pem
* @return bool
*/
public function doVerify($expected, $payload, Key $key)
{
$publicKey = $this->getPublicKey($key->getContent());
$result = openssl_verify($payload, $expected, $publicKey, $this->getAlgorithm());
openssl_free_key($publicKey);
return $result === 1;
}
/**
* @param string $pem
*
* @return resource
*/
private function getPublicKey($pem)
{
$publicKey = openssl_pkey_get_public($pem);
$this->validateKey($publicKey);
return $publicKey;
}
/**
* Raises an exception when the key type is not the expected type
*
* @param resource|bool $key
*
* @throws InvalidArgumentException
*/
private function validateKey($key)
{
if (! is_resource($key)) {
throw new InvalidArgumentException(
'It was not possible to parse your key, reason: ' . openssl_error_string()
);
}
$details = openssl_pkey_get_details($key);
if (! isset($details['key']) || $details['type'] !== $this->getKeyType()) {
throw new InvalidArgumentException('This key is not compatible with this signer');
}
}
/**
* Returns the type of key to be used to create/verify the signature (using OpenSSL constants)
*
* @internal
*/
abstract public function getKeyType();
/**
* Returns which algorithm to be used to create/verify the signature (using OpenSSL constants)
*
* @internal
*/
abstract public function getAlgorithm();
}

View File

@@ -0,0 +1,24 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer;
use const OPENSSL_KEYTYPE_RSA;
/**
* Base class for RSASSA-PKCS1 signers
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
abstract class Rsa extends OpenSSL
{
final public function getKeyType()
{
return OPENSSL_KEYTYPE_RSA;
}
}

View File

@@ -0,0 +1,35 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer\Rsa;
use Lcobucci\JWT\Signer\Rsa;
/**
* Signer for RSA SHA-256
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
class Sha256 extends Rsa
{
/**
* {@inheritdoc}
*/
public function getAlgorithmId()
{
return 'RS256';
}
/**
* {@inheritdoc}
*/
public function getAlgorithm()
{
return OPENSSL_ALGO_SHA256;
}
}

View File

@@ -0,0 +1,35 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer\Rsa;
use Lcobucci\JWT\Signer\Rsa;
/**
* Signer for RSA SHA-384
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
class Sha384 extends Rsa
{
/**
* {@inheritdoc}
*/
public function getAlgorithmId()
{
return 'RS384';
}
/**
* {@inheritdoc}
*/
public function getAlgorithm()
{
return OPENSSL_ALGO_SHA384;
}
}

View File

@@ -0,0 +1,35 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer\Rsa;
use Lcobucci\JWT\Signer\Rsa;
/**
* Signer for RSA SHA-512
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
class Sha512 extends Rsa
{
/**
* {@inheritdoc}
*/
public function getAlgorithmId()
{
return 'RS512';
}
/**
* {@inheritdoc}
*/
public function getAlgorithm()
{
return OPENSSL_ALGO_SHA512;
}
}

View File

@@ -0,0 +1,285 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT;
use BadMethodCallException;
use DateTime;
use DateTimeInterface;
use Generator;
use Lcobucci\JWT\Claim\Validatable;
use Lcobucci\JWT\Signer\Key;
use OutOfBoundsException;
/**
* Basic structure of the JWT
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
class Token
{
/**
* The token headers
*
* @var array
*/
private $headers;
/**
* The token claim set
*
* @var array
*/
private $claims;
/**
* The token signature
*
* @var Signature
*/
private $signature;
/**
* The encoded data
*
* @var array
*/
private $payload;
/**
* Initializes the object
*
* @param array $headers
* @param array $claims
* @param array $payload
* @param Signature $signature
*/
public function __construct(
array $headers = ['alg' => 'none'],
array $claims = [],
Signature $signature = null,
array $payload = ['', '']
) {
$this->headers = $headers;
$this->claims = $claims;
$this->signature = $signature;
$this->payload = $payload;
}
/**
* Returns the token headers
*
* @return array
*/
public function getHeaders()
{
return $this->headers;
}
/**
* Returns if the header is configured
*
* @param string $name
*
* @return boolean
*/
public function hasHeader($name)
{
return array_key_exists($name, $this->headers);
}
/**
* Returns the value of a token header
*
* @param string $name
* @param mixed $default
*
* @return mixed
*
* @throws OutOfBoundsException
*/
public function getHeader($name, $default = null)
{
if ($this->hasHeader($name)) {
return $this->getHeaderValue($name);
}
if ($default === null) {
throw new OutOfBoundsException('Requested header is not configured');
}
return $default;
}
/**
* Returns the value stored in header
*
* @param string $name
*
* @return mixed
*/
private function getHeaderValue($name)
{
$header = $this->headers[$name];
if ($header instanceof Claim) {
return $header->getValue();
}
return $header;
}
/**
* Returns the token claim set
*
* @return array
*/
public function getClaims()
{
return $this->claims;
}
/**
* Returns if the claim is configured
*
* @param string $name
*
* @return boolean
*/
public function hasClaim($name)
{
return array_key_exists($name, $this->claims);
}
/**
* Returns the value of a token claim
*
* @param string $name
* @param mixed $default
*
* @return mixed
*
* @throws OutOfBoundsException
*/
public function getClaim($name, $default = null)
{
if ($this->hasClaim($name)) {
return $this->claims[$name]->getValue();
}
if ($default === null) {
throw new OutOfBoundsException('Requested claim is not configured');
}
return $default;
}
/**
* Verify if the key matches with the one that created the signature
*
* @param Signer $signer
* @param Key|string $key
*
* @return boolean
*
* @throws BadMethodCallException When token is not signed
*/
public function verify(Signer $signer, $key)
{
if ($this->signature === null) {
throw new BadMethodCallException('This token is not signed');
}
if ($this->headers['alg'] !== $signer->getAlgorithmId()) {
return false;
}
return $this->signature->verify($signer, $this->getPayload(), $key);
}
/**
* Validates if the token is valid
*
* @param ValidationData $data
*
* @return boolean
*/
public function validate(ValidationData $data)
{
foreach ($this->getValidatableClaims() as $claim) {
if (!$claim->validate($data)) {
return false;
}
}
return true;
}
/**
* Determine if the token is expired.
*
* @param DateTimeInterface $now Defaults to the current time.
*
* @return bool
*/
public function isExpired(DateTimeInterface $now = null)
{
$exp = $this->getClaim('exp', false);
if ($exp === false) {
return false;
}
$now = $now ?: new DateTime();
$expiresAt = new DateTime();
$expiresAt->setTimestamp($exp);
return $now > $expiresAt;
}
/**
* Yields the validatable claims
*
* @return Generator
*/
private function getValidatableClaims()
{
foreach ($this->claims as $claim) {
if ($claim instanceof Validatable) {
yield $claim;
}
}
}
/**
* Returns the token payload
*
* @return string
*/
public function getPayload()
{
return $this->payload[0] . '.' . $this->payload[1];
}
/**
* Returns an encoded representation of the token
*
* @return string
*/
public function __toString()
{
$data = implode('.', $this->payload);
if ($this->signature === null) {
$data .= '.';
}
return $data;
}
}

View File

@@ -0,0 +1,129 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT;
/**
* Class that wraps validation values
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/
class ValidationData
{
/**
* The list of things to be validated
*
* @var array
*/
private $items;
/**
* The leeway (in seconds) to use when validating time claims
* @var int
*/
private $leeway;
/**
* Initializes the object
*
* @param int $currentTime
* @param int $leeway
*/
public function __construct($currentTime = null, $leeway = 0)
{
$currentTime = $currentTime ?: time();
$this->leeway = (int) $leeway;
$this->items = [
'jti' => null,
'iss' => null,
'aud' => null,
'sub' => null
];
$this->setCurrentTime($currentTime);
}
/**
* Configures the id
*
* @param string $id
*/
public function setId($id)
{
$this->items['jti'] = (string) $id;
}
/**
* Configures the issuer
*
* @param string $issuer
*/
public function setIssuer($issuer)
{
$this->items['iss'] = (string) $issuer;
}
/**
* Configures the audience
*
* @param string $audience
*/
public function setAudience($audience)
{
$this->items['aud'] = (string) $audience;
}
/**
* Configures the subject
*
* @param string $subject
*/
public function setSubject($subject)
{
$this->items['sub'] = (string) $subject;
}
/**
* Configures the time that "iat", "nbf" and "exp" should be based on
*
* @param int $currentTime
*/
public function setCurrentTime($currentTime)
{
$currentTime = (int) $currentTime;
$this->items['iat'] = $currentTime + $this->leeway;
$this->items['nbf'] = $currentTime + $this->leeway;
$this->items['exp'] = $currentTime - $this->leeway;
}
/**
* Returns the requested item
*
* @param string $name
*
* @return mixed
*/
public function get($name)
{
return isset($this->items[$name]) ? $this->items[$name] : null;
}
/**
* Returns if the item is present
*
* @param string $name
*
* @return boolean
*/
public function has($name)
{
return !empty($this->items[$name]);
}
}

View File

@@ -0,0 +1,328 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\FunctionalTests;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Token;
use Lcobucci\JWT\Signature;
use Lcobucci\JWT\Signer\Ecdsa\Sha256;
use Lcobucci\JWT\Signer\Ecdsa\Sha512;
use Lcobucci\JWT\Signer\Keychain;
use Lcobucci\JWT\Keys;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
class EcdsaTokenTest extends \PHPUnit\Framework\TestCase
{
use Keys;
/**
* @var Sha256
*/
private $signer;
/**
* @before
*/
public function createSigner()
{
$this->signer = new Sha256();
}
/**
* @test
*
* @expectedException \InvalidArgumentException
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers Lcobucci\JWT\Signer\Ecdsa
* @covers \Lcobucci\JWT\Signer\Ecdsa\MultibyteStringConverter
* @covers Lcobucci\JWT\Signer\Ecdsa\Sha256
* @covers \Lcobucci\JWT\Signer\OpenSSL
*/
public function builderShouldRaiseExceptionWhenKeyIsInvalid()
{
$user = (object) ['name' => 'testing', 'email' => 'testing@abc.com'];
(new Builder())->setId(1)
->setAudience('http://client.abc.com')
->setIssuer('http://api.abc.com')
->set('user', $user)
->getToken($this->signer, new Key('testing'));
}
/**
* @test
*
* @expectedException \InvalidArgumentException
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers Lcobucci\JWT\Signer\Ecdsa
* @covers \Lcobucci\JWT\Signer\Ecdsa\MultibyteStringConverter
* @covers Lcobucci\JWT\Signer\Ecdsa\Sha256
* @covers \Lcobucci\JWT\Signer\OpenSSL
*/
public function builderShouldRaiseExceptionWhenKeyIsNotEcdsaCompatible()
{
$user = (object) ['name' => 'testing', 'email' => 'testing@abc.com'];
(new Builder())->setId(1)
->setAudience('http://client.abc.com')
->setIssuer('http://api.abc.com')
->set('user', $user)
->getToken($this->signer, static::$rsaKeys['private']);
}
/**
* @test
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers Lcobucci\JWT\Signer\Ecdsa
* @covers \Lcobucci\JWT\Signer\Ecdsa\MultibyteStringConverter
* @covers Lcobucci\JWT\Signer\Ecdsa\Sha256
* @covers \Lcobucci\JWT\Signer\OpenSSL
*/
public function builderCanGenerateAToken()
{
$user = (object) ['name' => 'testing', 'email' => 'testing@abc.com'];
$token = (new Builder())->setId(1)
->setAudience('http://client.abc.com')
->setIssuer('http://api.abc.com')
->set('user', $user)
->setHeader('jki', '1234')
->sign($this->signer, static::$ecdsaKeys['private'])
->getToken();
$this->assertAttributeInstanceOf(Signature::class, 'signature', $token);
$this->assertEquals('1234', $token->getHeader('jki'));
$this->assertEquals('http://client.abc.com', $token->getClaim('aud'));
$this->assertEquals('http://api.abc.com', $token->getClaim('iss'));
$this->assertEquals($user, $token->getClaim('user'));
return $token;
}
/**
* @test
*
* @depends builderCanGenerateAToken
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Parsing\Decoder
* @covers Lcobucci\JWT\Signer\Ecdsa
*/
public function parserCanReadAToken(Token $generated)
{
$read = (new Parser())->parse((string) $generated);
$this->assertEquals($generated, $read);
$this->assertEquals('testing', $read->getClaim('user')->name);
}
/**
* @test
*
* @depends builderCanGenerateAToken
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers Lcobucci\JWT\Signer\Ecdsa
* @covers \Lcobucci\JWT\Signer\Ecdsa\MultibyteStringConverter
* @covers Lcobucci\JWT\Signer\Ecdsa\Sha256
* @covers \Lcobucci\JWT\Signer\OpenSSL
*/
public function verifyShouldReturnFalseWhenKeyIsNotRight(Token $token)
{
$this->assertFalse($token->verify($this->signer, static::$ecdsaKeys['public2']));
}
/**
* @test
*
* @depends builderCanGenerateAToken
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers Lcobucci\JWT\Signer\Ecdsa
* @covers \Lcobucci\JWT\Signer\Ecdsa\MultibyteStringConverter
* @covers Lcobucci\JWT\Signer\Ecdsa\Sha256
* @covers Lcobucci\JWT\Signer\Ecdsa\Sha512
* @covers \Lcobucci\JWT\Signer\OpenSSL
*/
public function verifyShouldReturnFalseWhenAlgorithmIsDifferent(Token $token)
{
$this->assertFalse($token->verify(new Sha512(), static::$ecdsaKeys['public1']));
}
/**
* @test
*
* @expectedException \InvalidArgumentException
*
* @depends builderCanGenerateAToken
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers Lcobucci\JWT\Signer\Ecdsa
* @covers \Lcobucci\JWT\Signer\Ecdsa\MultibyteStringConverter
* @covers Lcobucci\JWT\Signer\Ecdsa\Sha256
* @covers \Lcobucci\JWT\Signer\OpenSSL
*/
public function verifyShouldRaiseExceptionWhenKeyIsNotEcdsaCompatible(Token $token)
{
$this->assertFalse($token->verify($this->signer, static::$rsaKeys['public']));
}
/**
* @test
*
* @depends builderCanGenerateAToken
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers Lcobucci\JWT\Signer\Ecdsa
* @covers \Lcobucci\JWT\Signer\Ecdsa\MultibyteStringConverter
* @covers Lcobucci\JWT\Signer\Ecdsa\Sha256
* @covers \Lcobucci\JWT\Signer\OpenSSL
*/
public function verifyShouldReturnTrueWhenKeyIsRight(Token $token)
{
$this->assertTrue($token->verify($this->signer, static::$ecdsaKeys['public1']));
}
/**
* @test
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers Lcobucci\JWT\Signer\Ecdsa
* @covers \Lcobucci\JWT\Signer\Ecdsa\MultibyteStringConverter
* @covers Lcobucci\JWT\Signer\Ecdsa\Sha256
* @covers \Lcobucci\JWT\Signer\OpenSSL
*/
public function everythingShouldWorkWithAKeyWithParams()
{
$user = (object) ['name' => 'testing', 'email' => 'testing@abc.com'];
$token = (new Builder())->setId(1)
->setAudience('http://client.abc.com')
->setIssuer('http://api.abc.com')
->set('user', $user)
->setHeader('jki', '1234')
->sign($this->signer, static::$ecdsaKeys['private-params'])
->getToken();
$this->assertTrue($token->verify($this->signer, static::$ecdsaKeys['public-params']));
}
/**
* @test
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers Lcobucci\JWT\Signer\Ecdsa
* @covers \Lcobucci\JWT\Signer\Ecdsa\MultibyteStringConverter
* @covers Lcobucci\JWT\Signer\Ecdsa\Sha512
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers Lcobucci\JWT\Signer\Keychain
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Parsing\Decoder
*/
public function everythingShouldWorkWhenUsingATokenGeneratedByOtherLibs()
{
$data = 'eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9.eyJoZWxsbyI6IndvcmxkIn0.'
. 'AQx1MqdTni6KuzfOoedg2-7NUiwe-b88SWbdmviz40GTwrM0Mybp1i1tVtm'
. 'TSQ91oEXGXBdtwsN6yalzP9J-sp2YATX_Tv4h-BednbdSvYxZsYnUoZ--ZU'
. 'dL10t7g8Yt3y9hdY_diOjIptcha6ajX8yzkDGYG42iSe3f5LywSuD6FO5c';
$key = '-----BEGIN PUBLIC KEY-----' . PHP_EOL
. 'MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAcpkss6wI7PPlxj3t7A1RqMH3nvL4' . PHP_EOL
. 'L5Tzxze/XeeYZnHqxiX+gle70DlGRMqqOq+PJ6RYX7vK0PJFdiAIXlyPQq0B3KaU' . PHP_EOL
. 'e86IvFeQSFrJdCc0K8NfiH2G1loIk3fiR+YLqlXk6FAeKtpXJKxR1pCQCAM+vBCs' . PHP_EOL
. 'mZudf1zCUZ8/4eodlHU=' . PHP_EOL
. '-----END PUBLIC KEY-----';
$keychain = new Keychain();
$token = (new Parser())->parse((string) $data);
$this->assertEquals('world', $token->getClaim('hello'));
$this->assertTrue($token->verify(new Sha512(), $keychain->getPublicKey($key)));
}
}

View File

@@ -0,0 +1,186 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\FunctionalTests;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Token;
use Lcobucci\JWT\Signature;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Hmac\Sha512;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
class HmacTokenTest extends \PHPUnit\Framework\TestCase
{
/**
* @var Sha256
*/
private $signer;
/**
* @before
*/
public function createSigner()
{
$this->signer = new Sha256();
}
/**
* @test
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers Lcobucci\JWT\Signer\Hmac
* @covers Lcobucci\JWT\Signer\Hmac\Sha256
*/
public function builderCanGenerateAToken()
{
$user = (object) ['name' => 'testing', 'email' => 'testing@abc.com'];
$token = (new Builder())->setId(1)
->setAudience('http://client.abc.com')
->setIssuer('http://api.abc.com')
->set('user', $user)
->setHeader('jki', '1234')
->sign($this->signer, 'testing')
->getToken();
$this->assertAttributeInstanceOf(Signature::class, 'signature', $token);
$this->assertEquals('1234', $token->getHeader('jki'));
$this->assertEquals('http://client.abc.com', $token->getClaim('aud'));
$this->assertEquals('http://api.abc.com', $token->getClaim('iss'));
$this->assertEquals($user, $token->getClaim('user'));
return $token;
}
/**
* @test
*
* @depends builderCanGenerateAToken
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Parsing\Decoder
*/
public function parserCanReadAToken(Token $generated)
{
$read = (new Parser())->parse((string) $generated);
$this->assertEquals($generated, $read);
$this->assertEquals('testing', $read->getClaim('user')->name);
}
/**
* @test
*
* @depends builderCanGenerateAToken
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers Lcobucci\JWT\Signer\Hmac
* @covers Lcobucci\JWT\Signer\Hmac\Sha256
*/
public function verifyShouldReturnFalseWhenKeyIsNotRight(Token $token)
{
$this->assertFalse($token->verify($this->signer, 'testing1'));
}
/**
* @test
*
* @depends builderCanGenerateAToken
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers Lcobucci\JWT\Signer\Hmac
* @covers Lcobucci\JWT\Signer\Hmac\Sha256
* @covers Lcobucci\JWT\Signer\Hmac\Sha512
*/
public function verifyShouldReturnFalseWhenAlgorithmIsDifferent(Token $token)
{
$this->assertFalse($token->verify(new Sha512(), 'testing'));
}
/**
* @test
*
* @depends builderCanGenerateAToken
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers Lcobucci\JWT\Signer\Hmac
* @covers Lcobucci\JWT\Signer\Hmac\Sha256
*/
public function verifyShouldReturnTrueWhenKeyIsRight(Token $token)
{
$this->assertTrue($token->verify($this->signer, 'testing'));
}
/**
* @test
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers Lcobucci\JWT\Signer\Hmac
* @covers Lcobucci\JWT\Signer\Hmac\Sha256
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Parsing\Decoder
*/
public function everythingShouldWorkWhenUsingATokenGeneratedByOtherLibs()
{
$data = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJoZWxsbyI6IndvcmxkIn0.Rh'
. '7AEgqCB7zae1PkgIlvOpeyw9Ab8NGTbeOH7heHO0o';
$token = (new Parser())->parse((string) $data);
$this->assertEquals('world', $token->getClaim('hello'));
$this->assertTrue($token->verify($this->signer, 'testing'));
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace Lcobucci\JWT;
use Lcobucci\JWT\Signer\Keychain;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
*/
trait Keys
{
/**
* @var array
*/
protected static $rsaKeys;
/**
* @var array
*/
protected static $ecdsaKeys;
/**
* @beforeClass
*/
public static function createRsaKeys()
{
$keychain = new Keychain();
$dir = 'file://' . __DIR__;
static::$rsaKeys = [
'private' => $keychain->getPrivateKey($dir . '/rsa/private.key'),
'public' => $keychain->getPublicKey($dir . '/rsa/public.key'),
'encrypted-private' => $keychain->getPrivateKey($dir . '/rsa/encrypted-private.key', 'testing'),
'encrypted-public' => $keychain->getPublicKey($dir . '/rsa/encrypted-public.key')
];
}
/**
* @beforeClass
*/
public static function createEcdsaKeys()
{
$keychain = new Keychain();
$dir = 'file://' . __DIR__;
static::$ecdsaKeys = [
'private' => $keychain->getPrivateKey($dir . '/ecdsa/private.key'),
'private-params' => $keychain->getPrivateKey($dir . '/ecdsa/private2.key'),
'public1' => $keychain->getPublicKey($dir . '/ecdsa/public1.key'),
'public2' => $keychain->getPublicKey($dir . '/ecdsa/public2.key'),
'public-params' => $keychain->getPublicKey($dir . '/ecdsa/public3.key'),
];
}
}

View File

@@ -0,0 +1,154 @@
<?php
namespace Lcobucci\JWT\FunctionalTests;
use Lcobucci\JWT\Signer\Ecdsa;
use Lcobucci\JWT\Signer\Ecdsa\Sha256;
use Lcobucci\JWT\Signer\Ecdsa\Sha384;
use Lcobucci\JWT\Signer\Ecdsa\Sha512;
use Lcobucci\JWT\Signer\Key;
use PHPUnit\Framework\TestCase;
use const PHP_EOL;
use function assert;
use function hex2bin;
use function is_string;
final class RFC6978VectorTest extends TestCase
{
/**
* @see https://tools.ietf.org/html/rfc6979#appendix-A.2.5
* @see https://tools.ietf.org/html/rfc6979#appendix-A.2.6
* @see https://tools.ietf.org/html/rfc6979#appendix-A.2.7
*
* @test
* @dataProvider dataRFC6979
*
* @covers \Lcobucci\JWT\Signer\Key
* @covers \Lcobucci\JWT\Signer\Ecdsa
* @covers \Lcobucci\JWT\Signer\Ecdsa\MultibyteStringConverter
* @covers \Lcobucci\JWT\Signer\Ecdsa\Sha256
* @covers \Lcobucci\JWT\Signer\Ecdsa\Sha384
* @covers \Lcobucci\JWT\Signer\Ecdsa\Sha512
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\Signer\BaseSigner
*/
public function theVectorsFromRFC6978CanBeVerified(
Ecdsa $signer,
Key $key,
$payload,
$expectedR,
$expectedS
) {
$signature = hex2bin($expectedR . $expectedS);
assert(is_string($signature));
static::assertTrue($signer->verify($signature, $payload, $key));
}
/**
* @return mixed[]
*/
public function dataRFC6979()
{
return $this->sha256Data() + $this->sha384Data() + $this->sha512Data();
}
/**
* @return mixed[]
*/
public function sha256Data()
{
$signer = new Sha256();
$key = new Key(
'-----BEGIN PUBLIC KEY-----' . PHP_EOL
. 'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYP7UuiVanTHJYet0xjVtaMBJuJI7' . PHP_EOL
. 'Yfps5mliLmDyn7Z5A/4QCLi8maQa6elWKLxk8vGyDC1+n1F3o8KU1EYimQ==' . PHP_EOL
. '-----END PUBLIC KEY-----'
);
return [
'SHA-256 (sample)' => [
$signer,
$key,
'sample',
'EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716',
'F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8',
],
'SHA-256 (test)' => [
$signer,
$key,
'test',
'F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367',
'019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083',
]
];
}
/**
* @return mixed[]
*/
public function sha384Data()
{
$signer = new Sha384();
$key = new Key(
'-----BEGIN PUBLIC KEY-----' . PHP_EOL
. 'MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE7DpOQVtOGaRWhhgCn0J/pdqai8SukuAu' . PHP_EOL
. 'BqrlKGswDGTe+PDqkFWGYGSiVFFUgLwTgBXZty19VyROqO+awMYhiWcIpZNn+d+5' . PHP_EOL
. '9UyoSz8cnbEoiyMcOuDU/nNE/SUzJkcg' . PHP_EOL
. '-----END PUBLIC KEY-----'
);
return [
'SHA-384 (sample)' => [
$signer,
$key,
'sample',
'94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C81A648152E44ACF96E36DD1E80FABE46',
'99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94FA329C145786E679E7B82C71A38628AC8',
],
'SHA-384 (test)' => [
$signer,
$key,
'test',
'8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB0542A7F0812998DA8F1DD3CA3CF023DB',
'DDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E06A739F040649A667BF3B828246BAA5A5',
]
];
}
/**
* @return mixed[]
*/
public function sha512Data()
{
$signer = new Sha512();
$key = new Key(
'-----BEGIN PUBLIC KEY-----' . PHP_EOL
. 'MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBiUVQ0HhZMuAOqiO2lPIT+MMSH4bc' . PHP_EOL
. 'l6BOWnFn205bzTcRI9RuRdtrXVNwp/IPtjMVXTj/oW0r12HcrEdLmi9QI6QASTEB' . PHP_EOL
. 'yWLNTS/d94IoXmRYQTnC+RtH+H/4I1TWYw90aiig2yV0G1s0qCgAiyKswj+ST6r7' . PHP_EOL
. '1NM/gepmlW3+qiv9/PU=' . PHP_EOL
. '-----END PUBLIC KEY-----'
);
return [
'SHA-512 (sample)' => [
$signer,
$key,
'sample',
'00C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F174E25A1EE9017B5D450606ADD152B534931D7D4E8'
. '455CC91F9B15BF05EC36E377FA',
'00617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF282623EAA63E5B5C0723D8B8C37FF0777B1A20F8CC'
. 'B1DCCC43997F1EE0E44DA4A67A',
],
'SHA-512 (test)' => [
$signer,
$key,
'test',
'013E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0C'
. 'E2BD7051B7CEF945BABD47EE6D',
'01FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78A19CA69EFF5C57400E3B3A0AD66CE0978214D13BA'
. 'F4E9AC60752F7B155E2DE4DCE3',
],
];
}
}

View File

@@ -0,0 +1,280 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\FunctionalTests;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Keys;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Token;
use Lcobucci\JWT\Signature;
use Lcobucci\JWT\Signer\Rsa\Sha256;
use Lcobucci\JWT\Signer\Rsa\Sha512;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
class RsaTokenTest extends \PHPUnit\Framework\TestCase
{
use Keys;
/**
* @var Sha256
*/
private $signer;
/**
* @before
*/
public function createSigner()
{
$this->signer = new Sha256();
}
/**
* @test
*
* @expectedException \InvalidArgumentException
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\Signer\Rsa
* @covers \Lcobucci\JWT\Signer\Rsa\Sha256
*/
public function builderShouldRaiseExceptionWhenKeyIsInvalid()
{
$user = (object) ['name' => 'testing', 'email' => 'testing@abc.com'];
(new Builder())->setId(1)
->setAudience('http://client.abc.com')
->setIssuer('http://api.abc.com')
->set('user', $user)
->getToken($this->signer, new Key('testing'));
}
/**
* @test
*
* @expectedException \InvalidArgumentException
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\Signer\Rsa
* @covers \Lcobucci\JWT\Signer\Rsa\Sha256
*/
public function builderShouldRaiseExceptionWhenKeyIsNotRsaCompatible()
{
$user = (object) ['name' => 'testing', 'email' => 'testing@abc.com'];
(new Builder())->setId(1)
->setAudience('http://client.abc.com')
->setIssuer('http://api.abc.com')
->set('user', $user)
->getToken($this->signer, static::$ecdsaKeys['private']);
}
/**
* @test
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\Signer\Rsa
* @covers \Lcobucci\JWT\Signer\Rsa\Sha256
*/
public function builderCanGenerateAToken()
{
$user = (object) ['name' => 'testing', 'email' => 'testing@abc.com'];
$token = (new Builder())->setId(1)
->setAudience('http://client.abc.com')
->setIssuer('http://api.abc.com')
->set('user', $user)
->setHeader('jki', '1234')
->sign($this->signer, static::$rsaKeys['private'])
->getToken();
$this->assertAttributeInstanceOf(Signature::class, 'signature', $token);
$this->assertEquals('1234', $token->getHeader('jki'));
$this->assertEquals('http://client.abc.com', $token->getClaim('aud'));
$this->assertEquals('http://api.abc.com', $token->getClaim('iss'));
$this->assertEquals($user, $token->getClaim('user'));
return $token;
}
/**
* @test
*
* @depends builderCanGenerateAToken
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Parsing\Decoder
*/
public function parserCanReadAToken(Token $generated)
{
$read = (new Parser())->parse((string) $generated);
$this->assertEquals($generated, $read);
$this->assertEquals('testing', $read->getClaim('user')->name);
}
/**
* @test
*
* @depends builderCanGenerateAToken
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\Signer\Rsa
* @covers \Lcobucci\JWT\Signer\Rsa\Sha256
*/
public function verifyShouldReturnFalseWhenKeyIsNotRight(Token $token)
{
$this->assertFalse($token->verify($this->signer, self::$rsaKeys['encrypted-public']));
}
/**
* @test
*
* @depends builderCanGenerateAToken
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\Signer\Rsa
* @covers \Lcobucci\JWT\Signer\Rsa\Sha256
* @covers \Lcobucci\JWT\Signer\Rsa\Sha512
*/
public function verifyShouldReturnFalseWhenAlgorithmIsDifferent(Token $token)
{
$this->assertFalse($token->verify(new Sha512(), self::$rsaKeys['public']));
}
/**
* @test
*
* @expectedException \InvalidArgumentException
*
* @depends builderCanGenerateAToken
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\Signer\Rsa
* @covers \Lcobucci\JWT\Signer\Rsa\Sha256
*/
public function verifyShouldRaiseExceptionWhenKeyIsNotRsaCompatible(Token $token)
{
$this->assertFalse($token->verify($this->signer, self::$ecdsaKeys['public1']));
}
/**
* @test
*
* @depends builderCanGenerateAToken
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\Signer\Rsa
* @covers \Lcobucci\JWT\Signer\Rsa\Sha256
*/
public function verifyShouldReturnTrueWhenKeyIsRight(Token $token)
{
$this->assertTrue($token->verify($this->signer, self::$rsaKeys['public']));
}
/**
* @test
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Signature
* @covers Lcobucci\JWT\Signer\Key
* @covers Lcobucci\JWT\Signer\BaseSigner
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\Signer\Rsa
* @covers \Lcobucci\JWT\Signer\Rsa\Sha256
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Parsing\Decoder
*/
public function everythingShouldWorkWhenUsingATokenGeneratedByOtherLibs()
{
$data = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXUyJ9.eyJoZWxsbyI6IndvcmxkIn0.s'
. 'GYbB1KrmnESNfJ4D9hOe1Zad_BMyxdb8G4p4LNP7StYlOyBWck6q7XPpPj_6gB'
. 'Bo1ohD3MA2o0HY42lNIrAStaVhfsFKGdIou8TarwMGZBPcif_3ThUV1pGS3fZc'
. 'lFwF2SP7rqCngQis_xcUVCyqa8E1Wa_v28grnl1QZrnmQFO8B5JGGLqcrfUHJO'
. 'nJCupP-Lqh4TmIhftIimSCgLNmJg80wyrpUEfZYReE7hPuEmY0ClTqAGIMQoNS'
. '98ljwDxwhfbSuL2tAdbV4DekbTpWzspe3dOJ7RSzmPKVZ6NoezaIazKqyqkmHZfcMaHI1lQeGia6LTbHU1bp0gINi74Vw';
$token = (new Parser())->parse((string) $data);
$this->assertEquals('world', $token->getClaim('hello'));
$this->assertTrue($token->verify($this->signer, self::$rsaKeys['public']));
}
}

View File

@@ -0,0 +1,161 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\FunctionalTests;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Token;
use Lcobucci\JWT\ValidationData;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
class UnsignedTokenTest extends \PHPUnit\Framework\TestCase
{
const CURRENT_TIME = 100000;
/**
* @test
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Parsing\Encoder
*/
public function builderCanGenerateAToken()
{
$user = (object) ['name' => 'testing', 'email' => 'testing@abc.com'];
$token = (new Builder())->setId(1)
->setAudience('http://client.abc.com')
->setIssuer('http://api.abc.com')
->setExpiration(self::CURRENT_TIME + 3000)
->set('user', $user)
->getToken();
$this->assertAttributeEquals(null, 'signature', $token);
$this->assertEquals('http://client.abc.com', $token->getClaim('aud'));
$this->assertEquals('http://api.abc.com', $token->getClaim('iss'));
$this->assertEquals(self::CURRENT_TIME + 3000, $token->getClaim('exp'));
$this->assertEquals($user, $token->getClaim('user'));
return $token;
}
/**
* @test
*
* @depends builderCanGenerateAToken
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Parsing\Decoder
*/
public function parserCanReadAToken(Token $generated)
{
$read = (new Parser())->parse((string) $generated);
$this->assertEquals($generated, $read);
$this->assertEquals('testing', $read->getClaim('user')->name);
}
/**
* @test
*
* @depends builderCanGenerateAToken
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\ValidationData
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Claim\EqualsTo
* @covers Lcobucci\JWT\Claim\GreaterOrEqualsTo
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Parsing\Decoder
*/
public function tokenValidationShouldReturnWhenEverythingIsFine(Token $generated)
{
$data = new ValidationData(self::CURRENT_TIME - 10);
$data->setAudience('http://client.abc.com');
$data->setIssuer('http://api.abc.com');
$this->assertTrue($generated->validate($data));
}
/**
* @test
*
* @dataProvider invalidValidationData
*
* @depends builderCanGenerateAToken
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\ValidationData
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Claim\EqualsTo
* @covers Lcobucci\JWT\Claim\GreaterOrEqualsTo
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Parsing\Decoder
*/
public function tokenValidationShouldReturnFalseWhenExpectedDataDontMatch(ValidationData $data, Token $generated)
{
$this->assertFalse($generated->validate($data));
}
/**
* @test
*
* @depends builderCanGenerateAToken
*
* @covers Lcobucci\JWT\Builder
* @covers Lcobucci\JWT\Parser
* @covers Lcobucci\JWT\Token
* @covers Lcobucci\JWT\ValidationData
* @covers Lcobucci\JWT\Claim\Factory
* @covers Lcobucci\JWT\Claim\Basic
* @covers Lcobucci\JWT\Claim\EqualsTo
* @covers Lcobucci\JWT\Claim\GreaterOrEqualsTo
* @covers Lcobucci\JWT\Parsing\Encoder
* @covers Lcobucci\JWT\Parsing\Decoder
*/
public function tokenValidationShouldReturnTrueWhenExpectedDataMatchBecauseOfLeeway(Token $generated)
{
$notExpiredDueToLeeway = new ValidationData(self::CURRENT_TIME + 3020, 50);
$notExpiredDueToLeeway->setAudience('http://client.abc.com');
$notExpiredDueToLeeway->setIssuer('http://api.abc.com');
$this->assertTrue($generated->validate($notExpiredDueToLeeway));
}
public function invalidValidationData()
{
$expired = new ValidationData(self::CURRENT_TIME + 3020);
$expired->setAudience('http://client.abc.com');
$expired->setIssuer('http://api.abc.com');
$invalidAudience = new ValidationData(self::CURRENT_TIME - 10);
$invalidAudience->setAudience('http://cclient.abc.com');
$invalidAudience->setIssuer('http://api.abc.com');
$invalidIssuer = new ValidationData(self::CURRENT_TIME - 10);
$invalidIssuer->setAudience('http://client.abc.com');
$invalidIssuer->setIssuer('http://aapi.abc.com');
return [[$expired], [$invalidAudience], [$invalidIssuer]];
}
}

View File

@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIBGpMoZJ64MMSzuo5JbmXpf9V4qSWdLIl/8RmJLcfn/qoAoGCCqGSM49
AwEHoUQDQgAE7it/EKmcv9bfpcV1fBreLMRXxWpnd0wxa2iFruiI2tsEdGFTLTsy
U+GeRqC7zN0aTnTQajarUylKJ3UWr/r1kg==
-----END EC PRIVATE KEY-----

View File

@@ -0,0 +1,8 @@
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIM6G7WZ6SqoPwrHwGXhOJkYD+ErT8dfRvrNifgBQvSb7oAoGCCqGSM49
AwEHoUQDQgAE09Hkp/u0tIGdzlQ99R/sXCOr9DTZAfLex4D4Po0C1L3qUqHrzZ0m
B3bAhe+pwEDQ/jqVqdzxhA9i4PqT7F4Aew==
-----END EC PRIVATE KEY-----

View File

@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7it/EKmcv9bfpcV1fBreLMRXxWpn
d0wxa2iFruiI2tsEdGFTLTsyU+GeRqC7zN0aTnTQajarUylKJ3UWr/r1kg==
-----END PUBLIC KEY-----

View File

@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdgxRxlhzhHGj+v6S2ikp+33LoGp5
QWbEWv8BORsr2Ayg6C7deDDRM/s/f0R++4zZqXro1gDTVF5VDv7nE+EfEw==
-----END PUBLIC KEY-----

View File

@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE09Hkp/u0tIGdzlQ99R/sXCOr9DTZ
AfLex4D4Po0C1L3qUqHrzZ0mB3bAhe+pwEDQ/jqVqdzxhA9i4PqT7F4Aew==
-----END PUBLIC KEY-----

View File

@@ -0,0 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,0D71668CE71033CB9150ED82FC87F4A1
uLzPNDdlHnZ77tAGMHyPYERDMBcdV4SsQJYcSjiHhR2o0dLGTdgOpQrXTHPX4GJF
LlEWLhAAV9wx2mM/2kHDWB4uZwThtT9/v+RFoW1WbVO/d3lhI9fg4/73/DWAH/7/
afMRc7ZOVoAmVCESotPx4khCHoE97RdY/JtkLTzc3+peqmL53AbYXrg9rTN1B+ZV
U3w4ciQS8Uki87zDYIBjYtaOCyMUTvug25CvdssvUMBoc/Jc0xps6/vAyXrnzlGT
pZD0Tst8idswfDi613BhAaxJspeY0AErWA59qJ3eGzbiQq5RDWcbJe/Tz5r/6+NN
DkvNQ7DaEZ6LpeWX0MUq6/QWfrM8yE95XhjyC1d3LYn32lXHUygbgTFWIgLDoOE6
nBhu34SWtbLAnqYGewaJFxhlYVS9rb/uvYQg70r5X9Sx6alCQPiPyIv39IItezn2
HF2GRfE91MPZUeDhdqdvvOlSZVM5KnYc1fhamGAwM48gdDDXe8Czu/JEGoANNvC3
l/Z1p5RtGF4hrel9WpeX9zQq3pvtfVcVIiWuRUwCOSQytXlieRK37sMuYeggvmjV
VvaCods3mS/panWg9T/D/deIXjhzNJLvyiJg8+3sY5H4yNe0XpbaAc/ySwt9Rcxy
FzFQ+5pghLSZgR1uV3AhdcnzXBU2GkYhdGKt2tUsH0UeVQ2BXxTlBFsCOh2dWqcj
y3suIG65bukDAAWidQ4q3S6ZIMpXBhhCj7nwB5jQ7wSlU3U9So0ndr7zxdUILiMm
chHi3q5apVZnMGcwv2B33rt4nD7HgGEmRKkCelrSrBATY1ut+T4rCDzKDqDs3jpv
hYIWrlNPTkJyQz3eWly6Db+FJEfdYGadYJusc7/nOxCh/QmUu8Sh3NhKT6TH0bS7
1AAqd8H+2hJ9I32Dhd2qwAF7PkNe2LGi+P8tbAtepKGim5w65wnsPePMnrfxumsG
PeDnMrqeCKy+fME7a/MS5kmEBpmD4BMhVC6/OhFVz8gBty1f8yIEZggHNQN2QK7m
NIrG+PwqW2w8HoxOlAi2Ix4LTPifrdfsH02U7aM1pgo1rZzD4AOzqvzCaK43H2VB
BHLeTBGoLEUxXA9C+iGbeQlKXkMC00QKkjK5+nvkvnvePFfsrTQIpuyGufD/MoPb
6fpwsyHZDxhxMN1PJk1b1lPq2Ui4hXpVNOYd4Q6OQz7bwxTMRX9XQromUlKMMgAT
edX8v2NdM7Ssy1IwHuGVbDEpZdjoeaWZ1iNRV17i/EaJAqwYDQLfsuHBlzZL1ov1
xkKVJdL8Y3q80oRAzTQDVdzL/rI44LLAfv609YByCnw29feYJY2W6gV0O7ZSw413
XUkc5CaEbR1LuG8NtnOOPJV4Tb/hNsIDtvVm7Hl5npBKBe4iVgQ2LNuC2eT69d/z
uvzgjISlumPiO5ivuYe0QtLPuJSc+/Bl8bPL8gcNQEtqkzj7IftHPPZNs+bJC2uY
bPjq5KoDNAMF6VHuKHwu48MBYpnXDIg3ZenmJwGRULRBhK6324hDS6NJ7ULTBU2M
TZCHmg89ySLBfCAspVeo63o/R7bs9a7BP9x2h5uwCBogSvkEwhhPKnboVN45bp9c
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwLpbUP8a9yflt5LKUUS3
NPuRM7yEouPWg0VKeY5AURu4i8bqQ20K5jwfRJ+w05FvlywG4EuxpnpTFTVS2/do
q3xufzTf/C3KIDOAHEifkdx4140btKxxm4mD9Eu2CQ32adZyScha50KUFlfnAAic
Hb8wYxjFyWo3PAbGYmCQCn2z97Ab0Ar6NR1e+V9f8EL9Orr2f04puKJfQTZdWVDF
UJR4w7QZ/CPY0LEsiFLW3QQCNraka1mtrLJwPqreBtDEkj8IoISNkrguu/97RQZz
miJgBQkVjr6OfqG5WIFr0MzbRZc1/aK9g8ft88nhhQm0E3GqkCxBKTwgA03HtK07
qQIDAQAB
-----END PUBLIC KEY-----

View File

@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDTvwE87MtgREYL
TL4aHhQo3ZzogmxxvMUsKnPzyxRs1YrXOSOpwN0npsXarBKKVIUMNLfFODp/vnQn
2Zp06N8XG59WAOKwvC4MfxLDQkA+JXggzHlkbVoTN+dUkdYIFqSKuAPGwiWToRK2
SxEhij3rE2FON8jQZvDxZkiP9a4vxJO3OTPQwKredXFiObsXD/c3RtLFhKctjCyH
OIrP0bQEsee/m7JNtG4ry6BPusN6wb+vJo5ieBYPa3c19akNq6q/nYWhplhkkJSu
aOrL5xXEFzI5TvcvnXR568GVcxK8YLfFkdxpsXGt5rAbeh0h/U5kILEAqv8P9PGT
ZpicKbrnAgMBAAECggEAd3yTQEQHR91/ASVfKPHMQns77eCbPVtekFusbugsMHYY
EPdHbqVMpvFvOMRc+f5Tzd15ziq6qBdbCJm8lThLm4iU0z1QrpaiDZ8vgUvDYM5Y
CXoZDli+uZWUTp60/n94fmb0ipZIChScsI2PrzOJWTvobvD/uso8MJydWc8zafQm
uqYzygOfjFZvU4lSfgzpefhpquy0JUy5TiKRmGUnwLb3TtcsVavjsn4QmNwLYgOF
2OE+R12ex3pAKTiRE6FcnE1xFIo1GKhBa2Otgw3MDO6Gg+kn8Q4alKz6C6RRlgaH
R7sYzEfJhsk/GGFTYOzXKQz2lSaStKt9wKCor04RcQKBgQDzPOu5jCTfayUo7xY2
jHtiogHyKLLObt9l3qbwgXnaD6rnxYNvCrA0OMvT+iZXsFZKJkYzJr8ZOxOpPROk
10WdOaefiwUyL5dypueSwlIDwVm+hI4Bs82MajHtzOozh+73wA+aw5rPs84Uix9w
VbbwaVR6qP/BV09yJYS5kQ7fmwKBgQDe2xjywX2d2MC+qzRr+LfU+1+gq0jjhBCX
WHqRN6IECB0xTnXUf9WL/VCoI1/55BhdbbEja+4btYgcXSPmlXBIRKQ4VtFfVmYB
kPXeD8oZ7LyuNdCsbKNe+x1IHXDe6Wfs3L9ulCfXxeIE84wy3fd66mQahyXV9iD9
CkuifMqUpQKBgQCiydHlY1LGJ/o9tA2Ewm5Na6mrvOs2V2Ox1NqbObwoYbX62eiF
53xX5u8bVl5U75JAm+79it/4bd5RtKux9dUETbLOhwcaOFm+hM+VG/IxyzRZ2nMD
1qcpY2U5BpxzknUvYF3RMTop6edxPk7zKpp9ubCtSu+oINvtxAhY/SkcIwKBgGP1
upcImyO2GZ5shLL5eNubdSVILwV+M0LveOqyHYXZbd6z5r5OKKcGFKuWUnJwEU22
6gGNY9wh7M9sJ7JBzX9c6pwqtPcidda2AtJ8GpbOTUOG9/afNBhiYpv6OKqD3w2r
ZmJfKg/qvpqh83zNezgy8nvDqwDxyZI2j/5uIx/RAoGBAMWRmxtv6H2cKhibI/aI
MTJM4QRjyPNxQqvAQsv+oHUbid06VK3JE+9iQyithjcfNOwnCaoO7I7qAj9QEfJS
MZQc/W/4DHJebo2kd11yoXPVTXXOuEwLSKCejBXABBY0MPNuPUmiXeU0O3Tyi37J
TUKzrgcd7NvlA41Y4xKcOqEA
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA078BPOzLYERGC0y+Gh4U
KN2c6IJscbzFLCpz88sUbNWK1zkjqcDdJ6bF2qwSilSFDDS3xTg6f750J9madOjf
FxufVgDisLwuDH8Sw0JAPiV4IMx5ZG1aEzfnVJHWCBakirgDxsIlk6EStksRIYo9
6xNhTjfI0Gbw8WZIj/WuL8STtzkz0MCq3nVxYjm7Fw/3N0bSxYSnLYwshziKz9G0
BLHnv5uyTbRuK8ugT7rDesG/ryaOYngWD2t3NfWpDauqv52FoaZYZJCUrmjqy+cV
xBcyOU73L510eevBlXMSvGC3xZHcabFxreawG3odIf1OZCCxAKr/D/Txk2aYnCm6
5wIDAQAB
-----END PUBLIC KEY-----

View File

@@ -0,0 +1,633 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT;
use Lcobucci\JWT\Claim\Factory as ClaimFactory;
use Lcobucci\JWT\Parsing\Encoder;
use Lcobucci\JWT\Signer\Key;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
class BuilderTest extends \PHPUnit\Framework\TestCase
{
/**
* @var Encoder|\PHPUnit_Framework_MockObject_MockObject
*/
protected $encoder;
/**
* @var ClaimFactory|\PHPUnit_Framework_MockObject_MockObject
*/
protected $claimFactory;
/**
* @var Claim|\PHPUnit_Framework_MockObject_MockObject
*/
protected $defaultClaim;
/**
* {@inheritdoc}
*/
protected function setUp()
{
$this->encoder = $this->createMock(Encoder::class);
$this->claimFactory = $this->createMock(ClaimFactory::class);
$this->defaultClaim = $this->createMock(Claim::class);
$this->claimFactory->expects($this->any())
->method('create')
->willReturn($this->defaultClaim);
}
/**
* @return Builder
*/
private function createBuilder()
{
return new Builder($this->encoder, $this->claimFactory);
}
/**
* @test
*
* @covers Lcobucci\JWT\Builder::__construct
*/
public function constructMustInitializeTheAttributes()
{
$builder = $this->createBuilder();
$this->assertAttributeEquals(['alg' => 'none', 'typ' => 'JWT'], 'headers', $builder);
$this->assertAttributeEquals([], 'claims', $builder);
$this->assertAttributeSame($this->encoder, 'encoder', $builder);
$this->assertAttributeSame($this->claimFactory, 'claimFactory', $builder);
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::permittedFor
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function permittedForMustChangeTheAudClaim()
{
$builder = $this->createBuilder();
$builder->permittedFor('test');
$this->assertAttributeEquals(['alg' => 'none', 'typ' => 'JWT'], 'headers', $builder);
$this->assertAttributeEquals(['aud' => $this->defaultClaim], 'claims', $builder);
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::permittedFor
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function permittedForCanReplicateItemOnHeader()
{
$builder = $this->createBuilder();
$builder->permittedFor('test', true);
$this->assertAttributeEquals(['aud' => $this->defaultClaim], 'claims', $builder);
$this->assertAttributeEquals(
['alg' => 'none', 'typ' => 'JWT', 'aud' => $this->defaultClaim],
'headers',
$builder
);
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::permittedFor
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function permittedForMustKeepAFluentInterface()
{
$builder = $this->createBuilder();
$this->assertSame($builder, $builder->permittedFor('test'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::expiresAt
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function expiresAtMustChangeTheExpClaim()
{
$builder = $this->createBuilder();
$builder->expiresAt('2');
$this->assertAttributeEquals(['alg' => 'none', 'typ' => 'JWT'], 'headers', $builder);
$this->assertAttributeEquals(['exp' => $this->defaultClaim], 'claims', $builder);
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::expiresAt
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function expiresAtCanReplicateItemOnHeader()
{
$builder = $this->createBuilder();
$builder->expiresAt('2', true);
$this->assertAttributeEquals(['exp' => $this->defaultClaim], 'claims', $builder);
$this->assertAttributeEquals(
['alg' => 'none', 'typ' => 'JWT', 'exp' => $this->defaultClaim],
'headers',
$builder
);
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::expiresAt
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function expiresAtMustKeepAFluentInterface()
{
$builder = $this->createBuilder();
$this->assertSame($builder, $builder->expiresAt('2'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::identifiedBy
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function identifiedByMustChangeTheJtiClaim()
{
$builder = $this->createBuilder();
$builder->identifiedBy('2');
$this->assertAttributeEquals(['alg' => 'none', 'typ' => 'JWT'], 'headers', $builder);
$this->assertAttributeEquals(['jti' => $this->defaultClaim], 'claims', $builder);
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::identifiedBy
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function identifiedByCanReplicateItemOnHeader()
{
$builder = $this->createBuilder();
$builder->identifiedBy('2', true);
$this->assertAttributeEquals(['jti' => $this->defaultClaim], 'claims', $builder);
$this->assertAttributeEquals(
['alg' => 'none', 'typ' => 'JWT', 'jti' => $this->defaultClaim],
'headers',
$builder
);
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::identifiedBy
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function identifiedByMustKeepAFluentInterface()
{
$builder = $this->createBuilder();
$this->assertSame($builder, $builder->identifiedBy('2'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::issuedAt
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function issuedAtMustChangeTheIatClaim()
{
$builder = $this->createBuilder();
$builder->issuedAt('2');
$this->assertAttributeEquals(['alg' => 'none', 'typ' => 'JWT'], 'headers', $builder);
$this->assertAttributeEquals(['iat' => $this->defaultClaim], 'claims', $builder);
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::issuedAt
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function issuedAtCanReplicateItemOnHeader()
{
$builder = $this->createBuilder();
$builder->issuedAt('2', true);
$this->assertAttributeEquals(['iat' => $this->defaultClaim], 'claims', $builder);
$this->assertAttributeEquals(
['alg' => 'none', 'typ' => 'JWT', 'iat' => $this->defaultClaim],
'headers',
$builder
);
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::issuedAt
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function issuedAtMustKeepAFluentInterface()
{
$builder = $this->createBuilder();
$this->assertSame($builder, $builder->issuedAt('2'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::issuedBy
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function issuedByMustChangeTheIssClaim()
{
$builder = $this->createBuilder();
$builder->issuedBy('2');
$this->assertAttributeEquals(['alg' => 'none', 'typ' => 'JWT'], 'headers', $builder);
$this->assertAttributeEquals(['iss' => $this->defaultClaim], 'claims', $builder);
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::issuedBy
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function issuedByCanReplicateItemOnHeader()
{
$builder = $this->createBuilder();
$builder->issuedBy('2', true);
$this->assertAttributeEquals(['iss' => $this->defaultClaim], 'claims', $builder);
$this->assertAttributeEquals(
['alg' => 'none', 'typ' => 'JWT', 'iss' => $this->defaultClaim],
'headers',
$builder
);
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::issuedBy
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function issuedByMustKeepAFluentInterface()
{
$builder = $this->createBuilder();
$this->assertSame($builder, $builder->issuedBy('2'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::canOnlyBeUsedAfter
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function canOnlyBeUsedAfterMustChangeTheNbfClaim()
{
$builder = $this->createBuilder();
$builder->canOnlyBeUsedAfter('2');
$this->assertAttributeEquals(['alg' => 'none', 'typ' => 'JWT'], 'headers', $builder);
$this->assertAttributeEquals(['nbf' => $this->defaultClaim], 'claims', $builder);
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::canOnlyBeUsedAfter
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function canOnlyBeUsedAfterCanReplicateItemOnHeader()
{
$builder = $this->createBuilder();
$builder->canOnlyBeUsedAfter('2', true);
$this->assertAttributeEquals(['nbf' => $this->defaultClaim], 'claims', $builder);
$this->assertAttributeEquals(
['alg' => 'none', 'typ' => 'JWT', 'nbf' => $this->defaultClaim],
'headers',
$builder
);
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::canOnlyBeUsedAfter
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function canOnlyBeUsedAfterMustKeepAFluentInterface()
{
$builder = $this->createBuilder();
$this->assertSame($builder, $builder->canOnlyBeUsedAfter('2'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::relatedTo
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function relatedToMustChangeTheSubClaim()
{
$builder = $this->createBuilder();
$builder->relatedTo('2');
$this->assertAttributeEquals(['alg' => 'none', 'typ' => 'JWT'], 'headers', $builder);
$this->assertAttributeEquals(['sub' => $this->defaultClaim], 'claims', $builder);
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::relatedTo
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function relatedToCanReplicateItemOnHeader()
{
$builder = $this->createBuilder();
$builder->relatedTo('2', true);
$this->assertAttributeEquals(['sub' => $this->defaultClaim], 'claims', $builder);
$this->assertAttributeEquals(
['alg' => 'none', 'typ' => 'JWT', 'sub' => $this->defaultClaim],
'headers',
$builder
);
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
*
* @covers Lcobucci\JWT\Builder::relatedTo
* @covers Lcobucci\JWT\Builder::setRegisteredClaim
*/
public function relatedToMustKeepAFluentInterface()
{
$builder = $this->createBuilder();
$this->assertSame($builder, $builder->relatedTo('2'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
*
* @covers Lcobucci\JWT\Builder::withClaim
*/
public function withClaimMustConfigureTheGivenClaim()
{
$builder = $this->createBuilder();
$builder->withClaim('userId', 2);
$this->assertAttributeEquals(['userId' => $this->defaultClaim], 'claims', $builder);
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
*
* @covers Lcobucci\JWT\Builder::withClaim
*/
public function withClaimMustKeepAFluentInterface()
{
$builder = $this->createBuilder();
$this->assertSame($builder, $builder->withClaim('userId', 2));
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
*
* @covers Lcobucci\JWT\Builder::withHeader
*/
public function withHeaderMustConfigureTheGivenClaim()
{
$builder = $this->createBuilder();
$builder->withHeader('userId', 2);
$this->assertAttributeEquals(
['alg' => 'none', 'typ' => 'JWT', 'userId' => $this->defaultClaim],
'headers',
$builder
);
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
*
* @covers Lcobucci\JWT\Builder::withHeader
*/
public function withHeaderMustKeepAFluentInterface()
{
$builder = $this->createBuilder();
$this->assertSame($builder, $builder->withHeader('userId', 2));
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::getToken
* @uses Lcobucci\JWT\Token
*
* @covers Lcobucci\JWT\Builder::sign
*/
public function signMustConfigureSignerAndKey()
{
$signer = $this->createMock(Signer::class);
$builder = $this->createBuilder();
$builder->sign($signer, 'test');
$this->assertAttributeSame($signer, 'signer', $builder);
$this->assertAttributeEquals(new Key('test'), 'key', $builder);
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::getToken
* @uses Lcobucci\JWT\Token
*
* @covers Lcobucci\JWT\Builder::sign
*/
public function signMustKeepAFluentInterface()
{
$signer = $this->createMock(Signer::class);
$builder = $this->createBuilder();
$this->assertSame($builder, $builder->sign($signer, 'test'));
return $builder;
}
/**
* @test
*
* @depends signMustKeepAFluentInterface
*
* @covers Lcobucci\JWT\Builder::unsign
*/
public function unsignMustRemoveTheSignerAndKey(Builder $builder)
{
$builder->unsign();
$this->assertAttributeSame(null, 'signer', $builder);
$this->assertAttributeSame(null, 'key', $builder);
}
/**
* @test
*
* @depends signMustKeepAFluentInterface
*
* @covers Lcobucci\JWT\Builder::unsign
*/
public function unsignMustKeepAFluentInterface(Builder $builder)
{
$this->assertSame($builder, $builder->unsign());
}
/**
* @test
*
* @uses Lcobucci\JWT\Builder::__construct
* @uses Lcobucci\JWT\Builder::withClaim
* @uses Lcobucci\JWT\Token
*
* @covers Lcobucci\JWT\Builder::getToken
*/
public function getTokenMustReturnANewTokenWithCurrentConfiguration()
{
$signer = $this->createMock(Signer::class);
$signature = $this->createMock(Signature::class);
$signer->method('sign')->willReturn($signature);
$this->encoder->expects($this->exactly(2))
->method('jsonEncode')
->withConsecutive([['typ'=> 'JWT', 'alg' => 'none']], [['test' => $this->defaultClaim]])
->willReturnOnConsecutiveCalls('1', '2');
$this->encoder->expects($this->exactly(3))
->method('base64UrlEncode')
->withConsecutive(['1'], ['2'], [$signature])
->willReturnOnConsecutiveCalls('1', '2', '3');
$builder = $this->createBuilder()->withClaim('test', 123);
$token = $builder->getToken($signer, new Key('testing'));
$this->assertAttributeEquals(['1', '2', '3'], 'payload', $token);
$this->assertAttributeEquals($token->getHeaders(), 'headers', $builder);
$this->assertAttributeEquals($token->getClaims(), 'claims', $builder);
$this->assertAttributeSame($signature, 'signature', $token);
}
}

View File

@@ -0,0 +1,84 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Claim;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/
class BasicTest extends \PHPUnit\Framework\TestCase
{
/**
* @test
*
* @covers Lcobucci\JWT\Claim\Basic::__construct
*/
public function constructorShouldConfigureTheAttributes()
{
$claim = new Basic('test', 1);
$this->assertAttributeEquals('test', 'name', $claim);
$this->assertAttributeEquals(1, 'value', $claim);
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Basic::__construct
*
* @covers Lcobucci\JWT\Claim\Basic::getName
*/
public function getNameShouldReturnTheClaimName()
{
$claim = new Basic('test', 1);
$this->assertEquals('test', $claim->getName());
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Basic::__construct
*
* @covers Lcobucci\JWT\Claim\Basic::getValue
*/
public function getValueShouldReturnTheClaimValue()
{
$claim = new Basic('test', 1);
$this->assertEquals(1, $claim->getValue());
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Basic::__construct
*
* @covers Lcobucci\JWT\Claim\Basic::jsonSerialize
*/
public function jsonSerializeShouldReturnTheClaimValue()
{
$claim = new Basic('test', 1);
$this->assertEquals(1, $claim->jsonSerialize());
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Basic::__construct
*
* @covers Lcobucci\JWT\Claim\Basic::__toString
*/
public function toStringShouldReturnTheClaimValue()
{
$claim = new Basic('test', 1);
$this->assertEquals('1', (string) $claim);
}
}

View File

@@ -0,0 +1,83 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Claim;
use Lcobucci\JWT\ValidationData;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/
class EqualsToTest extends \PHPUnit\Framework\TestCase
{
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Basic::__construct
* @uses Lcobucci\JWT\Claim\Basic::getName
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::has
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\Claim\EqualsTo::validate
*/
public function validateShouldReturnTrueWhenValidationDontHaveTheClaim()
{
$claim = new EqualsTo('iss', 'test');
$this->assertTrue($claim->validate(new ValidationData()));
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Basic::__construct
* @uses Lcobucci\JWT\Claim\Basic::getName
* @uses Lcobucci\JWT\Claim\Basic::getValue
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setIssuer
* @uses Lcobucci\JWT\ValidationData::has
* @uses Lcobucci\JWT\ValidationData::get
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\Claim\EqualsTo::validate
*/
public function validateShouldReturnTrueWhenValueIsEqualsToValidationData()
{
$claim = new EqualsTo('iss', 'test');
$data = new ValidationData();
$data->setIssuer('test');
$this->assertTrue($claim->validate($data));
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Basic::__construct
* @uses Lcobucci\JWT\Claim\Basic::getName
* @uses Lcobucci\JWT\Claim\Basic::getValue
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setIssuer
* @uses Lcobucci\JWT\ValidationData::has
* @uses Lcobucci\JWT\ValidationData::get
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\Claim\EqualsTo::validate
*/
public function validateShouldReturnFalseWhenValueIsNotEqualsToValidationData()
{
$claim = new EqualsTo('iss', 'test');
$data = new ValidationData();
$data->setIssuer('test1');
$this->assertFalse($claim->validate($data));
}
}

View File

@@ -0,0 +1,168 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Claim;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/
class FactoryTest extends \PHPUnit\Framework\TestCase
{
/**
* @test
*
* @covers Lcobucci\JWT\Claim\Factory::__construct
*/
public function constructMustConfigureTheCallbacks()
{
$callback = function () {
};
$factory = new Factory(['test' => $callback]);
$expected = [
'iat' => [$factory, 'createLesserOrEqualsTo'],
'nbf' => [$factory, 'createLesserOrEqualsTo'],
'exp' => [$factory, 'createGreaterOrEqualsTo'],
'iss' => [$factory, 'createEqualsTo'],
'aud' => [$factory, 'createEqualsTo'],
'sub' => [$factory, 'createEqualsTo'],
'jti' => [$factory, 'createEqualsTo'],
'test' => $callback
];
$this->assertAttributeEquals($expected, 'callbacks', $factory);
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Factory::__construct
* @uses Lcobucci\JWT\Claim\Basic::__construct
*
* @covers Lcobucci\JWT\Claim\Factory::create
* @covers Lcobucci\JWT\Claim\Factory::createLesserOrEqualsTo
*/
public function createShouldReturnALesserOrEqualsToClaimForIssuedAt()
{
$claim = new Factory();
$this->assertInstanceOf(LesserOrEqualsTo::class, $claim->create('iat', 1));
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Factory::__construct
* @uses Lcobucci\JWT\Claim\Basic::__construct
*
* @covers Lcobucci\JWT\Claim\Factory::create
* @covers Lcobucci\JWT\Claim\Factory::createLesserOrEqualsTo
*/
public function createShouldReturnALesserOrEqualsToClaimForNotBefore()
{
$claim = new Factory();
$this->assertInstanceOf(LesserOrEqualsTo::class, $claim->create('nbf', 1));
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Factory::__construct
* @uses Lcobucci\JWT\Claim\Basic::__construct
*
* @covers Lcobucci\JWT\Claim\Factory::create
* @covers Lcobucci\JWT\Claim\Factory::createGreaterOrEqualsTo
*/
public function createShouldReturnAGreaterOrEqualsToClaimForExpiration()
{
$claim = new Factory();
$this->assertInstanceOf(GreaterOrEqualsTo::class, $claim->create('exp', 1));
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Factory::__construct
* @uses Lcobucci\JWT\Claim\Basic::__construct
*
* @covers Lcobucci\JWT\Claim\Factory::create
* @covers Lcobucci\JWT\Claim\Factory::createEqualsTo
*/
public function createShouldReturnAnEqualsToClaimForId()
{
$claim = new Factory();
$this->assertInstanceOf(EqualsTo::class, $claim->create('jti', 1));
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Factory::__construct
* @uses Lcobucci\JWT\Claim\Basic::__construct
*
* @covers Lcobucci\JWT\Claim\Factory::create
* @covers Lcobucci\JWT\Claim\Factory::createEqualsTo
*/
public function createShouldReturnAnEqualsToClaimForIssuer()
{
$claim = new Factory();
$this->assertInstanceOf(EqualsTo::class, $claim->create('iss', 1));
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Factory::__construct
* @uses Lcobucci\JWT\Claim\Basic::__construct
*
* @covers Lcobucci\JWT\Claim\Factory::create
* @covers Lcobucci\JWT\Claim\Factory::createEqualsTo
*/
public function createShouldReturnAnEqualsToClaimForAudience()
{
$claim = new Factory();
$this->assertInstanceOf(EqualsTo::class, $claim->create('aud', 1));
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Factory::__construct
* @uses Lcobucci\JWT\Claim\Basic::__construct
*
* @covers Lcobucci\JWT\Claim\Factory::create
* @covers Lcobucci\JWT\Claim\Factory::createEqualsTo
*/
public function createShouldReturnAnEqualsToClaimForSubject()
{
$claim = new Factory();
$this->assertInstanceOf(EqualsTo::class, $claim->create('sub', 1));
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Factory::__construct
* @uses Lcobucci\JWT\Claim\Basic::__construct
*
* @covers Lcobucci\JWT\Claim\Factory::create
* @covers Lcobucci\JWT\Claim\Factory::createBasic
*/
public function createShouldReturnABasiclaimForOtherClaims()
{
$claim = new Factory();
$this->assertInstanceOf(Basic::class, $claim->create('test', 1));
}
}

View File

@@ -0,0 +1,107 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Claim;
use Lcobucci\JWT\ValidationData;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/
class GreaterOrEqualsToTest extends \PHPUnit\Framework\TestCase
{
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Basic::__construct
* @uses Lcobucci\JWT\Claim\Basic::getName
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::has
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\Claim\GreaterOrEqualsTo::validate
*/
public function validateShouldReturnTrueWhenValidationDontHaveTheClaim()
{
$claim = new GreaterOrEqualsTo('iss', 10);
$this->assertTrue($claim->validate(new ValidationData()));
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Basic::__construct
* @uses Lcobucci\JWT\Claim\Basic::getName
* @uses Lcobucci\JWT\Claim\Basic::getValue
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setIssuer
* @uses Lcobucci\JWT\ValidationData::has
* @uses Lcobucci\JWT\ValidationData::get
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\Claim\GreaterOrEqualsTo::validate
*/
public function validateShouldReturnTrueWhenValueIsGreaterThanValidationData()
{
$claim = new GreaterOrEqualsTo('iss', 11);
$data = new ValidationData();
$data->setIssuer(10);
$this->assertTrue($claim->validate($data));
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Basic::__construct
* @uses Lcobucci\JWT\Claim\Basic::getName
* @uses Lcobucci\JWT\Claim\Basic::getValue
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setIssuer
* @uses Lcobucci\JWT\ValidationData::has
* @uses Lcobucci\JWT\ValidationData::get
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\Claim\GreaterOrEqualsTo::validate
*/
public function validateShouldReturnTrueWhenValueIsEqualsToValidationData()
{
$claim = new GreaterOrEqualsTo('iss', 10);
$data = new ValidationData();
$data->setIssuer(10);
$this->assertTrue($claim->validate($data));
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Basic::__construct
* @uses Lcobucci\JWT\Claim\Basic::getName
* @uses Lcobucci\JWT\Claim\Basic::getValue
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setIssuer
* @uses Lcobucci\JWT\ValidationData::has
* @uses Lcobucci\JWT\ValidationData::get
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\Claim\GreaterOrEqualsTo::validate
*/
public function validateShouldReturnFalseWhenValueIsLesserThanValidationData()
{
$claim = new GreaterOrEqualsTo('iss', 10);
$data = new ValidationData();
$data->setIssuer(11);
$this->assertFalse($claim->validate($data));
}
}

View File

@@ -0,0 +1,107 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Claim;
use Lcobucci\JWT\ValidationData;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/
class LesserOrEqualsToTest extends \PHPUnit\Framework\TestCase
{
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Basic::__construct
* @uses Lcobucci\JWT\Claim\Basic::getName
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::has
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\Claim\LesserOrEqualsTo::validate
*/
public function validateShouldReturnTrueWhenValidationDontHaveTheClaim()
{
$claim = new LesserOrEqualsTo('iss', 10);
$this->assertTrue($claim->validate(new ValidationData()));
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Basic::__construct
* @uses Lcobucci\JWT\Claim\Basic::getName
* @uses Lcobucci\JWT\Claim\Basic::getValue
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setIssuer
* @uses Lcobucci\JWT\ValidationData::has
* @uses Lcobucci\JWT\ValidationData::get
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\Claim\LesserOrEqualsTo::validate
*/
public function validateShouldReturnTrueWhenValueIsLesserThanValidationData()
{
$claim = new LesserOrEqualsTo('iss', 10);
$data = new ValidationData();
$data->setIssuer(11);
$this->assertTrue($claim->validate($data));
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Basic::__construct
* @uses Lcobucci\JWT\Claim\Basic::getName
* @uses Lcobucci\JWT\Claim\Basic::getValue
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setIssuer
* @uses Lcobucci\JWT\ValidationData::has
* @uses Lcobucci\JWT\ValidationData::get
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\Claim\LesserOrEqualsTo::validate
*/
public function validateShouldReturnTrueWhenValueIsEqualsToValidationData()
{
$claim = new LesserOrEqualsTo('iss', 10);
$data = new ValidationData();
$data->setIssuer(10);
$this->assertTrue($claim->validate($data));
}
/**
* @test
*
* @uses Lcobucci\JWT\Claim\Basic::__construct
* @uses Lcobucci\JWT\Claim\Basic::getName
* @uses Lcobucci\JWT\Claim\Basic::getValue
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setIssuer
* @uses Lcobucci\JWT\ValidationData::has
* @uses Lcobucci\JWT\ValidationData::get
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\Claim\LesserOrEqualsTo::validate
*/
public function validateShouldReturnFalseWhenValueIsGreaterThanValidationData()
{
$claim = new LesserOrEqualsTo('iss', 11);
$data = new ValidationData();
$data->setIssuer(10);
$this->assertFalse($claim->validate($data));
}
}

View File

@@ -0,0 +1,244 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT;
use Lcobucci\JWT\Claim\Factory as ClaimFactory;
use Lcobucci\JWT\Parsing\Decoder;
use RuntimeException;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
class ParserTest extends \PHPUnit\Framework\TestCase
{
/**
* @var Decoder|\PHPUnit_Framework_MockObject_MockObject
*/
protected $decoder;
/**
* @var ClaimFactory|\PHPUnit_Framework_MockObject_MockObject
*/
protected $claimFactory;
/**
* @var Claim|\PHPUnit_Framework_MockObject_MockObject
*/
protected $defaultClaim;
/**
* {@inheritdoc}
*/
protected function setUp()
{
$this->decoder = $this->createMock(Decoder::class);
$this->claimFactory = $this->createMock(ClaimFactory::class, [], [], '', false);
$this->defaultClaim = $this->createMock(Claim::class);
$this->claimFactory->expects($this->any())
->method('create')
->willReturn($this->defaultClaim);
}
/**
* @return Parser
*/
private function createParser()
{
return new Parser($this->decoder, $this->claimFactory);
}
/**
* @test
*
* @covers Lcobucci\JWT\Parser::__construct
*/
public function constructMustConfigureTheAttributes()
{
$parser = $this->createParser();
$this->assertAttributeSame($this->decoder, 'decoder', $parser);
$this->assertAttributeSame($this->claimFactory, 'claimFactory', $parser);
}
/**
* @test
*
* @uses Lcobucci\JWT\Parser::__construct
*
* @covers Lcobucci\JWT\Parser::parse
* @covers Lcobucci\JWT\Parser::splitJwt
*
* @expectedException InvalidArgumentException
*/
public function parseMustRaiseExceptionWhenJWSIsNotAString()
{
$parser = $this->createParser();
$parser->parse(['asdasd']);
}
/**
* @test
*
* @uses Lcobucci\JWT\Parser::__construct
*
* @covers Lcobucci\JWT\Parser::parse
* @covers Lcobucci\JWT\Parser::splitJwt
*
* @expectedException InvalidArgumentException
*/
public function parseMustRaiseExceptionWhenJWSDontHaveThreeParts()
{
$parser = $this->createParser();
$parser->parse('');
}
/**
* @test
*
* @uses Lcobucci\JWT\Parser::__construct
*
* @covers Lcobucci\JWT\Parser::parse
* @covers Lcobucci\JWT\Parser::splitJwt
* @covers Lcobucci\JWT\Parser::parseHeader
*
* @expectedException RuntimeException
*/
public function parseMustRaiseExceptionWhenHeaderCannotBeDecoded()
{
$this->decoder->expects($this->any())
->method('jsonDecode')
->willThrowException(new RuntimeException());
$parser = $this->createParser();
$parser->parse('asdfad.asdfasdf.');
}
/**
* @test
*
* @uses Lcobucci\JWT\Parser::__construct
*
* @covers Lcobucci\JWT\Parser::parse
* @covers Lcobucci\JWT\Parser::splitJwt
* @covers Lcobucci\JWT\Parser::parseHeader
*
* @expectedException InvalidArgumentException
*/
public function parseMustRaiseExceptionWhenHeaderIsFromAnEncryptedToken()
{
$this->decoder->expects($this->any())
->method('jsonDecode')
->willReturn(['enc' => 'AAA']);
$parser = $this->createParser();
$parser->parse('a.a.');
}
/**
* @test
*
* @uses Lcobucci\JWT\Parser::__construct
* @uses Lcobucci\JWT\Token::__construct
*
* @covers Lcobucci\JWT\Parser::parse
* @covers Lcobucci\JWT\Parser::splitJwt
* @covers Lcobucci\JWT\Parser::parseHeader
* @covers Lcobucci\JWT\Parser::parseClaims
* @covers Lcobucci\JWT\Parser::parseSignature
*
*/
public function parseMustReturnANonSignedTokenWhenSignatureIsNotInformed()
{
$this->decoder->expects($this->at(1))
->method('jsonDecode')
->willReturn(['typ' => 'JWT', 'alg' => 'none']);
$this->decoder->expects($this->at(3))
->method('jsonDecode')
->willReturn(['aud' => 'test']);
$parser = $this->createParser();
$token = $parser->parse('a.a.');
$this->assertAttributeEquals(['typ' => 'JWT', 'alg' => 'none'], 'headers', $token);
$this->assertAttributeEquals(['aud' => $this->defaultClaim], 'claims', $token);
$this->assertAttributeEquals(null, 'signature', $token);
}
/**
* @test
*
* @uses Lcobucci\JWT\Parser::__construct
* @uses Lcobucci\JWT\Token::__construct
*
* @covers Lcobucci\JWT\Parser::parse
* @covers Lcobucci\JWT\Parser::splitJwt
* @covers Lcobucci\JWT\Parser::parseHeader
* @covers Lcobucci\JWT\Parser::parseClaims
* @covers Lcobucci\JWT\Parser::parseSignature
*/
public function parseShouldReplicateClaimValueOnHeaderWhenNeeded()
{
$this->decoder->expects($this->at(1))
->method('jsonDecode')
->willReturn(['typ' => 'JWT', 'alg' => 'none', 'aud' => 'test']);
$this->decoder->expects($this->at(3))
->method('jsonDecode')
->willReturn(['aud' => 'test']);
$parser = $this->createParser();
$token = $parser->parse('a.a.');
$this->assertAttributeEquals(
['typ' => 'JWT', 'alg' => 'none', 'aud' => $this->defaultClaim],
'headers',
$token
);
$this->assertAttributeEquals(['aud' => $this->defaultClaim], 'claims', $token);
$this->assertAttributeEquals(null, 'signature', $token);
}
/**
* @test
*
* @uses Lcobucci\JWT\Parser::__construct
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\Signature::__construct
*
* @covers Lcobucci\JWT\Parser::parse
* @covers Lcobucci\JWT\Parser::splitJwt
* @covers Lcobucci\JWT\Parser::parseHeader
* @covers Lcobucci\JWT\Parser::parseClaims
* @covers Lcobucci\JWT\Parser::parseSignature
*/
public function parseMustReturnASignedTokenWhenSignatureIsInformed()
{
$this->decoder->expects($this->at(1))
->method('jsonDecode')
->willReturn(['typ' => 'JWT', 'alg' => 'HS256']);
$this->decoder->expects($this->at(3))
->method('jsonDecode')
->willReturn(['aud' => 'test']);
$this->decoder->expects($this->at(4))
->method('base64UrlDecode')
->willReturn('aaa');
$parser = $this->createParser();
$token = $parser->parse('a.a.a');
$this->assertAttributeEquals(['typ' => 'JWT', 'alg' => 'HS256'], 'headers', $token);
$this->assertAttributeEquals(['aud' => $this->defaultClaim], 'claims', $token);
$this->assertAttributeEquals(new Signature('aaa'), 'signature', $token);
}
}

View File

@@ -0,0 +1,56 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Parsing;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
class DecoderTest extends \PHPUnit\Framework\TestCase
{
/**
* @test
*
* @covers Lcobucci\JWT\Parsing\Decoder::jsonDecode
*/
public function jsonDecodeMustReturnTheDecodedData()
{
$decoder = new Decoder();
$this->assertEquals(
(object) ['test' => 'test'],
$decoder->jsonDecode('{"test":"test"}')
);
}
/**
* @test
*
* @covers Lcobucci\JWT\Parsing\Decoder::jsonDecode
*
* @expectedException \RuntimeException
*/
public function jsonDecodeMustRaiseExceptionWhenAnErrorHasOccured()
{
$decoder = new Decoder();
$decoder->jsonDecode('{"test":\'test\'}');
}
/**
* @test
*
* @covers Lcobucci\JWT\Parsing\Decoder::base64UrlDecode
*/
public function base64UrlDecodeMustReturnTheRightData()
{
$data = base64_decode('0MB2wKB+L3yvIdzeggmJ+5WOSLaRLTUPXbpzqUe0yuo=');
$decoder = new Decoder();
$this->assertEquals($data, $decoder->base64UrlDecode('0MB2wKB-L3yvIdzeggmJ-5WOSLaRLTUPXbpzqUe0yuo'));
}
}

View File

@@ -0,0 +1,53 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Parsing;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
class EncoderTest extends \PHPUnit\Framework\TestCase
{
/**
* @test
*
* @covers Lcobucci\JWT\Parsing\Encoder::jsonEncode
*/
public function jsonEncodeMustReturnAJSONString()
{
$encoder = new Encoder();
$this->assertEquals('{"test":"test"}', $encoder->jsonEncode(['test' => 'test']));
}
/**
* @test
*
* @covers Lcobucci\JWT\Parsing\Encoder::jsonEncode
*
* @expectedException \RuntimeException
*/
public function jsonEncodeMustRaiseExceptionWhenAnErrorHasOccured()
{
$encoder = new Encoder();
$encoder->jsonEncode("\xB1\x31");
}
/**
* @test
*
* @covers Lcobucci\JWT\Parsing\Encoder::base64UrlEncode
*/
public function base64UrlEncodeMustReturnAnUrlSafeBase64()
{
$data = base64_decode('0MB2wKB+L3yvIdzeggmJ+5WOSLaRLTUPXbpzqUe0yuo=');
$encoder = new Encoder();
$this->assertEquals('0MB2wKB-L3yvIdzeggmJ-5WOSLaRLTUPXbpzqUe0yuo', $encoder->base64UrlEncode($data));
}
}

View File

@@ -0,0 +1,73 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
class SignatureTest extends \PHPUnit\Framework\TestCase
{
/**
* @var Signer|\PHPUnit_Framework_MockObject_MockObject
*/
protected $signer;
/**
* {@inheritdoc}
*/
protected function setUp()
{
$this->signer = $this->createMock(Signer::class);
}
/**
* @test
*
* @covers Lcobucci\JWT\Signature::__construct
*/
public function constructorMustConfigureAttributes()
{
$signature = new Signature('test');
$this->assertAttributeEquals('test', 'hash', $signature);
}
/**
* @test
*
* @uses Lcobucci\JWT\Signature::__construct
*
* @covers Lcobucci\JWT\Signature::__toString
*/
public function toStringMustReturnTheHash()
{
$signature = new Signature('test');
$this->assertEquals('test', (string) $signature);
}
/**
* @test
*
* @uses Lcobucci\JWT\Signature::__construct
* @uses Lcobucci\JWT\Signature::__toString
*
* @covers Lcobucci\JWT\Signature::verify
*/
public function verifyMustReturnWhatSignerSays()
{
$this->signer->expects($this->any())
->method('verify')
->willReturn(true);
$signature = new Signature('test');
$this->assertTrue($signature->verify($this->signer, 'one', 'key'));
}
}

View File

@@ -0,0 +1,128 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer;
use Lcobucci\JWT\Signature;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
class BaseSignerTest extends \PHPUnit\Framework\TestCase
{
/**
* @var BaseSigner|\PHPUnit_Framework_MockObject_MockObject
*/
protected $signer;
/**
* {@inheritdoc}
*/
protected function setUp()
{
$this->signer = $this->getMockForAbstractClass(BaseSigner::class);
$this->signer->method('getAlgorithmId')
->willReturn('TEST123');
}
/**
* @test
*
* @covers Lcobucci\JWT\Signer\BaseSigner::modifyHeader
*/
public function modifyHeaderShouldChangeAlgorithm()
{
$headers = ['typ' => 'JWT'];
$this->signer->modifyHeader($headers);
$this->assertEquals($headers['typ'], 'JWT');
$this->assertEquals($headers['alg'], 'TEST123');
}
/**
* @test
*
* @uses Lcobucci\JWT\Signature::__construct
* @uses Lcobucci\JWT\Signer\Key
*
* @covers Lcobucci\JWT\Signer\BaseSigner::sign
* @covers Lcobucci\JWT\Signer\BaseSigner::getKey
*/
public function signMustReturnANewSignature()
{
$key = new Key('123');
$this->signer->expects($this->once())
->method('createHash')
->with('test', $key)
->willReturn('test');
$this->assertEquals(new Signature('test'), $this->signer->sign('test', $key));
}
/**
* @test
*
* @uses Lcobucci\JWT\Signature::__construct
* @uses Lcobucci\JWT\Signer\Key
*
* @covers Lcobucci\JWT\Signer\BaseSigner::sign
* @covers Lcobucci\JWT\Signer\BaseSigner::getKey
*/
public function signShouldConvertKeyWhenItsNotAnObject()
{
$this->signer->expects($this->once())
->method('createHash')
->with('test', new Key('123'))
->willReturn('test');
$this->assertEquals(new Signature('test'), $this->signer->sign('test', '123'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Signature::__construct
* @uses Lcobucci\JWT\Signer\Key
*
* @covers Lcobucci\JWT\Signer\BaseSigner::verify
* @covers Lcobucci\JWT\Signer\BaseSigner::getKey
*/
public function verifyShouldDelegateTheCallToAbstractMethod()
{
$key = new Key('123');
$this->signer->expects($this->once())
->method('doVerify')
->with('test', 'test', $key)
->willReturn(true);
$this->assertTrue($this->signer->verify('test', 'test', $key));
}
/**
* @test
*
* @uses Lcobucci\JWT\Signature::__construct
* @uses Lcobucci\JWT\Signer\Key
*
* @covers Lcobucci\JWT\Signer\BaseSigner::verify
* @covers Lcobucci\JWT\Signer\BaseSigner::getKey
*/
public function verifyShouldConvertKeyWhenItsNotAnObject()
{
$this->signer->expects($this->once())
->method('doVerify')
->with('test', 'test', new Key('123'))
->willReturn(true);
$this->assertTrue($this->signer->verify('test', 'test', '123'));
}
}

View File

@@ -0,0 +1,127 @@
<?php
namespace Lcobucci\JWT\Signer\Ecdsa;
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
use function bin2hex;
use function hex2bin;
use function strlen;
/**
* @coversDefaultClass \Lcobucci\JWT\Signer\Ecdsa\MultibyteStringConverter
*/
final class MultibyteStringConverterTest extends TestCase
{
/**
* @test
* @dataProvider pointsConversionData
*
* @covers ::toAsn1
* @covers ::octetLength
* @covers ::preparePositiveInteger
*/
public function toAsn1ShouldReturnThePointsInAnAsn1SequenceFormat(
$r,
$s,
$asn1
) {
$converter = new MultibyteStringConverter();
$message = hex2bin($r . $s);
self::assertSame($asn1, bin2hex($converter->toAsn1($message, strlen($r))));
}
/**
* @test
*
* @covers ::toAsn1
* @covers ::octetLength
*/
public function toAsn1ShouldRaiseExceptionWhenPointsDoNotHaveCorrectLength()
{
$converter = new MultibyteStringConverter();
self::expectException(InvalidArgumentException::class);
$converter->toAsn1('a very wrong string', 64);
}
/**
* @test
* @dataProvider pointsConversionData
*
* @covers ::fromAsn1
* @covers ::readAsn1Content
* @covers ::readAsn1Integer
* @covers ::retrievePositiveInteger
*/
public function fromAsn1ShouldReturnTheConcatenatedPoints($r, $s, $asn1)
{
$converter = new MultibyteStringConverter();
$message = hex2bin($asn1);
self::assertSame($r . $s, bin2hex($converter->fromAsn1($message, strlen($r))));
}
/**
* @return string[][]
*/
public function pointsConversionData()
{
return [
[
'efd48b2aacb6a8fd1140dd9cd45e81d69d2c877b56aaf991c34d0ea84eaf3716',
'f7cb1c942d657c41d436c7a1b6e29f65f3e900dbb9aff4064dc4ab2f843acda8',
'3046022100efd48b2aacb6a8fd1140dd9cd45e81d69d2c877b56aaf991c34d0ea84eaf3716022100f7cb1c942d657c41d436c7'
. 'a1b6e29f65f3e900dbb9aff4064dc4ab2f843acda8',
],
[
'94edbb92a5ecb8aad4736e56c691916b3f88140666ce9fa73d64c4ea95ad133c81a648152e44acf96e36dd1e80fabe46',
'99ef4aeb15f178cea1fe40db2603138f130e740a19624526203b6351d0a3a94fa329c145786e679e7b82c71a38628ac8',
'306602310094edbb92a5ecb8aad4736e56c691916b3f88140666ce9fa73d64c4ea95ad133c81a648152e44acf96e36dd1e80fa'
. 'be4602310099ef4aeb15f178cea1fe40db2603138f130e740a19624526203b6351d0a3a94fa329c145786e679e7b82c71a38'
. '628ac8',
],
[
'00c328fafcbd79dd77850370c46325d987cb525569fb63c5d3bc53950e6d4c5f174e25a1ee9017b5d450606add152b534931d7'
. 'd4e8455cc91f9b15bf05ec36e377fa',
'00617cce7cf5064806c467f678d3b4080d6f1cc50af26ca209417308281b68af282623eaa63e5b5c0723d8b8c37ff0777b1a20'
. 'f8ccb1dccc43997f1ee0e44da4a67a',
'308187024200c328fafcbd79dd77850370c46325d987cb525569fb63c5d3bc53950e6d4c5f174e25a1ee9017b5d450606add15'
. '2b534931d7d4e8455cc91f9b15bf05ec36e377fa0241617cce7cf5064806c467f678d3b4080d6f1cc50af26ca20941730828'
. '1b68af282623eaa63e5b5c0723d8b8c37ff0777b1a20f8ccb1dccc43997f1ee0e44da4a67a',
],
];
}
/**
* @test
* @dataProvider invalidAsn1Structures
*
* @covers ::fromAsn1
* @covers ::readAsn1Content
* @covers ::readAsn1Integer
* @covers ::retrievePositiveInteger
*/
public function fromAsn1ShouldRaiseExceptionOnInvalidMessage($message)
{
$converter = new MultibyteStringConverter();
$message = hex2bin($message);
$this->expectException(InvalidArgumentException::class);
$converter->fromAsn1($message, 64);
}
/**
* @return string[][]
*/
public function invalidAsn1Structures()
{
return [
'Not a sequence' => [''],
'Sequence without length' => ['30'],
'Only one string element' => ['3006030204f0'],
'Only one integer element' => ['3004020101'],
'Integer+string elements' => ['300a020101030204f0'],
];
}
}

View File

@@ -0,0 +1,60 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer\Ecdsa;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
class Sha256Test extends \PHPUnit\Framework\TestCase
{
/**
* @test
*
* @uses Lcobucci\JWT\Signer\Ecdsa
* @uses Lcobucci\JWT\Signer\OpenSSL
*
* @covers Lcobucci\JWT\Signer\Ecdsa\Sha256::getAlgorithmId
*/
public function getAlgorithmIdMustBeCorrect()
{
$signer = new Sha256();
$this->assertEquals('ES256', $signer->getAlgorithmId());
}
/**
* @test
*
* @uses Lcobucci\JWT\Signer\Ecdsa
* @uses Lcobucci\JWT\Signer\OpenSSL
*
* @covers Lcobucci\JWT\Signer\Ecdsa\Sha256::getAlgorithm
*/
public function getAlgorithmMustBeCorrect()
{
$signer = new Sha256();
$this->assertEquals('sha256', $signer->getAlgorithm());
}
/**
* @test
*
* @uses Lcobucci\JWT\Signer\Ecdsa
* @uses Lcobucci\JWT\Signer\OpenSSL
*
* @covers Lcobucci\JWT\Signer\Ecdsa\Sha256::getKeyLength
*/
public function getKeyLengthMustBeCorrect()
{
$signer = new Sha256();
$this->assertEquals(64, $signer->getKeyLength());
}
}

View File

@@ -0,0 +1,60 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer\Ecdsa;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
class Sha384Test extends \PHPUnit\Framework\TestCase
{
/**
* @test
*
* @uses Lcobucci\JWT\Signer\Ecdsa
* @uses Lcobucci\JWT\Signer\OpenSSL
*
* @covers Lcobucci\JWT\Signer\Ecdsa\Sha384::getAlgorithmId
*/
public function getAlgorithmIdMustBeCorrect()
{
$signer = new Sha384();
$this->assertEquals('ES384', $signer->getAlgorithmId());
}
/**
* @test
*
* @uses Lcobucci\JWT\Signer\Ecdsa
* @uses Lcobucci\JWT\Signer\OpenSSL
*
* @covers Lcobucci\JWT\Signer\Ecdsa\Sha384::getAlgorithm
*/
public function getAlgorithmMustBeCorrect()
{
$signer = new Sha384();
$this->assertEquals('sha384', $signer->getAlgorithm());
}
/**
* @test
*
* @uses Lcobucci\JWT\Signer\Ecdsa
* @uses Lcobucci\JWT\Signer\OpenSSL
*
* @covers Lcobucci\JWT\Signer\Ecdsa\Sha384::getKeyLength
*/
public function getKeyLengthMustBeCorrect()
{
$signer = new Sha384();
$this->assertEquals(96, $signer->getKeyLength());
}
}

View File

@@ -0,0 +1,60 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer\Ecdsa;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
class Sha512Test extends \PHPUnit\Framework\TestCase
{
/**
* @test
*
* @uses Lcobucci\JWT\Signer\Ecdsa
* @uses Lcobucci\JWT\Signer\OpenSSL
*
* @covers Lcobucci\JWT\Signer\Ecdsa\Sha512::getAlgorithmId
*/
public function getAlgorithmIdMustBeCorrect()
{
$signer = new Sha512();
$this->assertEquals('ES512', $signer->getAlgorithmId());
}
/**
* @test
*
* @uses Lcobucci\JWT\Signer\Ecdsa
* @uses Lcobucci\JWT\Signer\OpenSSL
*
* @covers Lcobucci\JWT\Signer\Ecdsa\Sha512::getAlgorithm
*/
public function getAlgorithmMustBeCorrect()
{
$signer = new Sha512();
$this->assertEquals('sha512', $signer->getAlgorithm());
}
/**
* @test
*
* @uses Lcobucci\JWT\Signer\Ecdsa
* @uses Lcobucci\JWT\Signer\OpenSSL
*
* @covers Lcobucci\JWT\Signer\Ecdsa\Sha512::getKeyLength
*/
public function getKeyLengthMustBeCorrect()
{
$signer = new Sha512();
$this->assertEquals(132, $signer->getKeyLength());
}
}

View File

@@ -0,0 +1,117 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer;
use Lcobucci\JWT\Keys;
use Lcobucci\JWT\Signer\Ecdsa\MultibyteStringConverter;
use const OPENSSL_ALGO_SHA256;
use function openssl_pkey_get_private;
use function openssl_pkey_get_public;
use function openssl_sign;
use function openssl_verify;
class EcdsaTest extends \PHPUnit\Framework\TestCase
{
use Keys;
/**
* @var MultibyteStringConverter
*/
private $pointsManipulator;
/**
* @before
*/
public function createDependencies()
{
$this->pointsManipulator = new MultibyteStringConverter();
}
private function getSigner()
{
$signer = $this->getMockForAbstractClass(Ecdsa::class, [$this->pointsManipulator]);
$signer->method('getAlgorithm')
->willReturn(OPENSSL_ALGO_SHA256);
$signer->method('getAlgorithmId')
->willReturn('ES256');
$signer->method('getKeyLength')
->willReturn(64);
return $signer;
}
/**
* @test
*
* @covers \Lcobucci\JWT\Signer\Ecdsa::createHash
* @covers \Lcobucci\JWT\Signer\Ecdsa::getKeyType
* @covers \Lcobucci\JWT\Signer\Ecdsa\MultibyteStringConverter
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\Signer\BaseSigner
*
* @uses \Lcobucci\JWT\Signer\Ecdsa::__construct
* @uses \Lcobucci\JWT\Signer\Key
* @uses \Lcobucci\JWT\Signature
*/
public function createHashShouldReturnTheAHashBasedOnTheOpenSslSignature()
{
$payload = 'testing';
$signer = $this->getSigner();
$signature = $signer->sign($payload, self::$ecdsaKeys['private']);
$publicKey = openssl_pkey_get_public(self::$ecdsaKeys['public1']->getContent());
self::assertInternalType('resource', $publicKey);
self::assertSame(
1,
openssl_verify(
$payload,
$this->pointsManipulator->toAsn1($signature, $signer->getKeyLength()),
$publicKey,
OPENSSL_ALGO_SHA256
)
);
}
/**
* @test
*
* @covers \Lcobucci\JWT\Signer\Ecdsa::doVerify
* @covers \Lcobucci\JWT\Signer\Ecdsa::getKeyType
* @covers \Lcobucci\JWT\Signer\Ecdsa\MultibyteStringConverter
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\Signer\BaseSigner
*
* @uses \Lcobucci\JWT\Signer\Ecdsa::__construct
* @uses \Lcobucci\JWT\Signer\Key
*/
public function doVerifyShouldDelegateToEcdsaSignerUsingPublicKey()
{
$payload = 'testing';
$privateKey = openssl_pkey_get_private(self::$ecdsaKeys['private']->getContent());
self::assertInternalType('resource', $privateKey);
$signature = '';
openssl_sign($payload, $signature, $privateKey, OPENSSL_ALGO_SHA256);
$signer = $this->getSigner();
self::assertTrue(
$signer->verify(
$this->pointsManipulator->fromAsn1($signature, $signer->getKeyLength()),
$payload,
self::$ecdsaKeys['public1']
)
);
}
}

View File

@@ -0,0 +1,39 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer\Hmac;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
class Sha256Test extends \PHPUnit\Framework\TestCase
{
/**
* @test
*
* @covers Lcobucci\JWT\Signer\Hmac\Sha256::getAlgorithmId
*/
public function getAlgorithmIdMustBeCorrect()
{
$signer = new Sha256();
$this->assertEquals('HS256', $signer->getAlgorithmId());
}
/**
* @test
*
* @covers Lcobucci\JWT\Signer\Hmac\Sha256::getAlgorithm
*/
public function getAlgorithmMustBeCorrect()
{
$signer = new Sha256();
$this->assertEquals('sha256', $signer->getAlgorithm());
}
}

View File

@@ -0,0 +1,39 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer\Hmac;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
class Sha384Test extends \PHPUnit\Framework\TestCase
{
/**
* @test
*
* @covers Lcobucci\JWT\Signer\Hmac\Sha384::getAlgorithmId
*/
public function getAlgorithmIdMustBeCorrect()
{
$signer = new Sha384();
$this->assertEquals('HS384', $signer->getAlgorithmId());
}
/**
* @test
*
* @covers Lcobucci\JWT\Signer\Hmac\Sha384::getAlgorithm
*/
public function getAlgorithmMustBeCorrect()
{
$signer = new Sha384();
$this->assertEquals('sha384', $signer->getAlgorithm());
}
}

View File

@@ -0,0 +1,39 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer\Hmac;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
class Sha512Test extends \PHPUnit\Framework\TestCase
{
/**
* @test
*
* @covers Lcobucci\JWT\Signer\Hmac\Sha512::getAlgorithmId
*/
public function getAlgorithmIdMustBeCorrect()
{
$signer = new Sha512();
$this->assertEquals('HS512', $signer->getAlgorithmId());
}
/**
* @test
*
* @covers Lcobucci\JWT\Signer\Hmac\Sha512::getAlgorithm
*/
public function getAlgorithmMustBeCorrect()
{
$signer = new Sha512();
$this->assertEquals('sha512', $signer->getAlgorithm());
}
}

View File

@@ -0,0 +1,134 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
class HmacTest extends \PHPUnit\Framework\TestCase
{
/**
* @var Hmac|\PHPUnit_Framework_MockObject_MockObject
*/
protected $signer;
/**
* {@inheritdoc}
*/
protected function setUp()
{
$this->signer = $this->getMockForAbstractClass(Hmac::class);
$this->signer->expects($this->any())
->method('getAlgorithmId')
->willReturn('TEST123');
$this->signer->expects($this->any())
->method('getAlgorithm')
->willReturn('sha256');
}
/**
* @test
*
* @uses Lcobucci\JWT\Signer\Key
*
* @covers Lcobucci\JWT\Signer\Hmac::createHash
*/
public function createHashMustReturnAHashAccordingWithTheAlgorithm()
{
$hash = hash_hmac('sha256', 'test', '123', true);
$this->assertEquals($hash, $this->signer->createHash('test', new Key('123')));
return $hash;
}
/**
* @test
*
* @depends createHashMustReturnAHashAccordingWithTheAlgorithm
*
* @uses Lcobucci\JWT\Signer\Hmac::createHash
* @uses Lcobucci\JWT\Signer\Key
*
* @covers Lcobucci\JWT\Signer\Hmac::doVerify
*/
public function doVerifyShouldReturnTrueWhenExpectedHashWasCreatedWithSameInformation($expected)
{
$this->assertTrue($this->signer->doVerify($expected, 'test', new Key('123')));
}
/**
* @test
*
* @depends createHashMustReturnAHashAccordingWithTheAlgorithm
*
* @uses Lcobucci\JWT\Signer\Hmac::createHash
* @uses Lcobucci\JWT\Signer\Key
*
* @covers Lcobucci\JWT\Signer\Hmac::doVerify
*/
public function doVerifyShouldReturnFalseWhenExpectedHashWasNotCreatedWithSameInformation($expected)
{
$this->assertFalse($this->signer->doVerify($expected, 'test', new Key('1234')));
}
/**
* @test
*
* @uses Lcobucci\JWT\Signer\Key
*
* @covers Lcobucci\JWT\Signer\Hmac::doVerify
*/
public function doVerifyShouldReturnFalseWhenExpectedHashIsNotString()
{
$this->assertFalse($this->signer->doVerify(false, 'test', new Key('1234')));
}
/**
* @test
*
* @covers Lcobucci\JWT\Signer\Hmac::hashEquals
*/
public function hashEqualsShouldReturnFalseWhenExpectedHashHasDifferentLengthThanGenerated()
{
$this->assertFalse($this->signer->hashEquals('123', '1234'));
}
/**
* @test
*
* @depends createHashMustReturnAHashAccordingWithTheAlgorithm
*
* @uses Lcobucci\JWT\Signer\Hmac::createHash
* @uses Lcobucci\JWT\Signer\Key
*
* @covers Lcobucci\JWT\Signer\Hmac::hashEquals
*/
public function hashEqualsShouldReturnFalseWhenExpectedHashIsDifferentThanGenerated($expected)
{
$this->assertFalse($this->signer->hashEquals($expected, $this->signer->createHash('test', new Key('1234'))));
}
/**
* @test
*
* @depends createHashMustReturnAHashAccordingWithTheAlgorithm
*
* @uses Lcobucci\JWT\Signer\Hmac::createHash
* @uses Lcobucci\JWT\Signer\Key
*
* @covers Lcobucci\JWT\Signer\Hmac::hashEquals
*/
public function hashEqualsShouldReturnTrueWhenExpectedHashIsEqualsThanGenerated($expected)
{
$this->assertTrue($this->signer->hashEquals($expected, $this->signer->createHash('test', new Key('123'))));
}
}

View File

@@ -0,0 +1,119 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer;
use org\bovigo\vfs\vfsStream;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 3.0.4
*/
class KeyTest extends \PHPUnit\Framework\TestCase
{
/**
* @before
*/
public function configureRootDir()
{
vfsStream::setup(
'root',
null,
[
'test.pem' => 'testing',
'emptyFolder' => []
]
);
}
/**
* @test
*
* @covers Lcobucci\JWT\Signer\Key::__construct
* @covers Lcobucci\JWT\Signer\Key::setContent
*/
public function constructShouldConfigureContentAndPassphrase()
{
$key = new Key('testing', 'test');
$this->assertAttributeEquals('testing', 'content', $key);
$this->assertAttributeEquals('test', 'passphrase', $key);
}
/**
* @test
*
* @covers Lcobucci\JWT\Signer\Key::__construct
* @covers Lcobucci\JWT\Signer\Key::setContent
* @covers Lcobucci\JWT\Signer\Key::readFile
*/
public function constructShouldBeAbleToConfigureContentFromFile()
{
$key = new Key('file://' . vfsStream::url('root/test.pem'));
$this->assertAttributeEquals('testing', 'content', $key);
$this->assertAttributeEquals(null, 'passphrase', $key);
}
/**
* @test
*
* @expectedException \InvalidArgumentException
*
* @covers Lcobucci\JWT\Signer\Key::__construct
* @covers Lcobucci\JWT\Signer\Key::setContent
* @covers Lcobucci\JWT\Signer\Key::readFile
*/
public function constructShouldRaiseExceptionWhenFileDoesNotExists()
{
new Key('file://' . vfsStream::url('root/test2.pem'));
}
/**
* @test
*
* @expectedException \InvalidArgumentException
*
* @covers Lcobucci\JWT\Signer\Key::__construct
* @covers Lcobucci\JWT\Signer\Key::setContent
* @covers Lcobucci\JWT\Signer\Key::readFile
*/
public function constructShouldRaiseExceptionWhenFileGetContentsFailed()
{
new Key('file://' . vfsStream::url('root/emptyFolder'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Signer\Key::__construct
* @uses Lcobucci\JWT\Signer\Key::setContent
*
* @covers Lcobucci\JWT\Signer\Key::getContent
*/
public function getContentShouldReturnConfiguredData()
{
$key = new Key('testing', 'test');
$this->assertEquals('testing', $key->getContent());
}
/**
* @test
*
* @uses Lcobucci\JWT\Signer\Key::__construct
* @uses Lcobucci\JWT\Signer\Key::setContent
*
* @covers Lcobucci\JWT\Signer\Key::getPassphrase
*/
public function getPassphraseShouldReturnConfiguredData()
{
$key = new Key('testing', 'test');
$this->assertEquals('test', $key->getPassphrase());
}
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
class KeychainTest extends \PHPUnit\Framework\TestCase
{
/**
* @test
*
* @uses Lcobucci\JWT\Signer\Key
*
* @covers Lcobucci\JWT\Signer\Keychain::getPrivateKey
*/
public function getPrivateKeyShouldReturnAKey()
{
$keychain = new Keychain();
$key = $keychain->getPrivateKey('testing', 'test');
$this->assertInstanceOf(Key::class, $key);
$this->assertAttributeEquals('testing', 'content', $key);
$this->assertAttributeEquals('test', 'passphrase', $key);
}
/**
* @test
*
* @uses Lcobucci\JWT\Signer\Key
*
* @covers Lcobucci\JWT\Signer\Keychain::getPublicKey
*/
public function getPublicKeyShouldReturnAValidResource()
{
$keychain = new Keychain();
$key = $keychain->getPublicKey('testing');
$this->assertInstanceOf(Key::class, $key);
$this->assertAttributeEquals('testing', 'content', $key);
$this->assertAttributeEquals(null, 'passphrase', $key);
}
}

View File

@@ -0,0 +1,39 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer\Rsa;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
class Sha256Test extends \PHPUnit\Framework\TestCase
{
/**
* @test
*
* @covers Lcobucci\JWT\Signer\Rsa\Sha256::getAlgorithmId
*/
public function getAlgorithmIdMustBeCorrect()
{
$signer = new Sha256();
$this->assertEquals('RS256', $signer->getAlgorithmId());
}
/**
* @test
*
* @covers Lcobucci\JWT\Signer\Rsa\Sha256::getAlgorithm
*/
public function getAlgorithmMustBeCorrect()
{
$signer = new Sha256();
$this->assertEquals(OPENSSL_ALGO_SHA256, $signer->getAlgorithm());
}
}

View File

@@ -0,0 +1,39 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer\Rsa;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
class Sha384Test extends \PHPUnit\Framework\TestCase
{
/**
* @test
*
* @covers Lcobucci\JWT\Signer\Rsa\Sha384::getAlgorithmId
*/
public function getAlgorithmIdMustBeCorrect()
{
$signer = new Sha384();
$this->assertEquals('RS384', $signer->getAlgorithmId());
}
/**
* @test
*
* @covers Lcobucci\JWT\Signer\Rsa\Sha384::getAlgorithm
*/
public function getAlgorithmMustBeCorrect()
{
$signer = new Sha384();
$this->assertEquals(OPENSSL_ALGO_SHA384, $signer->getAlgorithm());
}
}

View File

@@ -0,0 +1,39 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer\Rsa;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
class Sha512Test extends \PHPUnit\Framework\TestCase
{
/**
* @test
*
* @covers Lcobucci\JWT\Signer\Rsa\Sha512::getAlgorithmId
*/
public function getAlgorithmIdMustBeCorrect()
{
$signer = new Sha512();
$this->assertEquals('RS512', $signer->getAlgorithmId());
}
/**
* @test
*
* @covers Lcobucci\JWT\Signer\Rsa\Sha512::getAlgorithm
*/
public function getAlgorithmMustBeCorrect()
{
$signer = new Sha512();
$this->assertEquals(OPENSSL_ALGO_SHA512, $signer->getAlgorithm());
}
}

View File

@@ -0,0 +1,188 @@
<?php
namespace Lcobucci\JWT\Signer;
use InvalidArgumentException;
use Lcobucci\JWT\Keys;
use PHPUnit\Framework\TestCase;
use const OPENSSL_ALGO_SHA256;
use function openssl_pkey_get_private;
use function openssl_pkey_get_public;
use function openssl_sign;
use function openssl_verify;
final class RsaTest extends TestCase
{
use Keys;
/**
* @test
*
* @covers \Lcobucci\JWT\Signer\Rsa::createHash
* @covers \Lcobucci\JWT\Signer\Rsa::validateKey
* @covers \Lcobucci\JWT\Signer\Rsa::getKeyType
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\Signer\BaseSigner
*
* @uses \Lcobucci\JWT\Signer\Key
* @uses \Lcobucci\JWT\Signature
*/
public function createHashShouldReturnAValidOpensslSignature()
{
$payload = 'testing';
$signer = $this->getSigner();
$signature = $signer->sign($payload, self::$rsaKeys['private']);
$publicKey = openssl_pkey_get_public(self::$rsaKeys['public']->getContent());
self::assertInternalType('resource', $publicKey);
self::assertSame(1, openssl_verify($payload, $signature, $publicKey, OPENSSL_ALGO_SHA256));
}
/**
* @test
*
* @covers \Lcobucci\JWT\Signer\Rsa::createHash
* @covers \Lcobucci\JWT\Signer\Rsa::validateKey
* @covers \Lcobucci\JWT\Signer\Rsa::getKeyType
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\Signer\BaseSigner
*
* @uses \Lcobucci\JWT\Signer\Key
*/
public function createHashShouldRaiseAnExceptionWhenKeyIsInvalid()
{
$key = <<<KEY
-----BEGIN RSA PRIVATE KEY-----
MGECAQACEQC4MRKSVsq5XnRBrJoX6+rnAgMBAAECECO8SZkgw6Yg66A6SUly/3kC
CQDtPXZtCQWJuwIJAMbBu17GDOrFAggopfhNlFcjkwIIVjb7G+U0/TECCEERyvxP
TWdN
-----END RSA PRIVATE KEY-----
KEY;
$signer = $this->getSigner();
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('There was an error while creating the signature');
$signer->sign('testing', new Key($key));
}
/**
* @test
*
* @covers \Lcobucci\JWT\Signer\Rsa::createHash
* @covers \Lcobucci\JWT\Signer\Rsa::validateKey
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\Signer\BaseSigner
*
* @uses \Lcobucci\JWT\Signer\Key
*/
public function createHashShouldRaiseAnExceptionWhenKeyIsNotParseable()
{
$signer = $this->getSigner();
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('It was not possible to parse your key');
$signer->sign('testing', new Key('blablabla'));
}
/**
* @test
*
* @covers \Lcobucci\JWT\Signer\Rsa::createHash
* @covers \Lcobucci\JWT\Signer\Rsa::validateKey
* @covers \Lcobucci\JWT\Signer\Rsa::getKeyType
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\Signer\BaseSigner
*
* @uses \Lcobucci\JWT\Signer\Key
*/
public function createHashShouldRaiseAnExceptionWhenKeyTypeIsNotRsa()
{
$signer = $this->getSigner();
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('This key is not compatible with this signer');
$signer->sign('testing', self::$ecdsaKeys['private']);
}
/**
* @test
*
* @covers \Lcobucci\JWT\Signer\Rsa::doVerify
* @covers \Lcobucci\JWT\Signer\Rsa::validateKey
* @covers \Lcobucci\JWT\Signer\Rsa::getKeyType
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\Signer\BaseSigner
*
* @uses \Lcobucci\JWT\Signer\Key
*/
public function doVerifyShouldReturnTrueWhenSignatureIsValid()
{
$payload = 'testing';
$privateKey = openssl_pkey_get_private(self::$rsaKeys['private']->getContent());
self::assertInternalType('resource', $privateKey);
$signature = '';
openssl_sign($payload, $signature, $privateKey, OPENSSL_ALGO_SHA256);
$signer = $this->getSigner();
self::assertTrue($signer->verify($signature, $payload, self::$rsaKeys['public']));
}
/**
* @test
*
* @covers \Lcobucci\JWT\Signer\Rsa::doVerify
* @covers \Lcobucci\JWT\Signer\Rsa::validateKey
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\Signer\BaseSigner
*
* @uses \Lcobucci\JWT\Signer\Key
*/
public function doVerifyShouldRaiseAnExceptionWhenKeyIsNotParseable()
{
$signer = $this->getSigner();
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('It was not possible to parse your key');
$signer->verify('testing', 'testing', new Key('blablabla'));
}
/**
* @test
*
* @covers \Lcobucci\JWT\Signer\Rsa::doVerify
* @covers \Lcobucci\JWT\Signer\Rsa::validateKey
* @covers \Lcobucci\JWT\Signer\OpenSSL
* @covers \Lcobucci\JWT\Signer\BaseSigner
*
* @uses \Lcobucci\JWT\Signer\Key
*/
public function doVerifyShouldRaiseAnExceptionWhenKeyTypeIsNotRsa()
{
$signer = $this->getSigner();
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('It was not possible to parse your key');
$signer->verify('testing', 'testing', self::$ecdsaKeys['private']);
}
private function getSigner()
{
$signer = $this->getMockForAbstractClass(Rsa::class);
$signer->method('getAlgorithm')
->willReturn(OPENSSL_ALGO_SHA256);
$signer->method('getAlgorithmId')
->willReturn('RS256');
return $signer;
}
}

View File

@@ -0,0 +1,573 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT;
use DateInterval;
use DateTime;
use Lcobucci\JWT\Claim\Basic;
use Lcobucci\JWT\Claim\EqualsTo;
use Lcobucci\JWT\Claim\GreaterOrEqualsTo;
use Lcobucci\JWT\Claim\LesserOrEqualsTo;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/
class TokenTest extends \PHPUnit\Framework\TestCase
{
/**
* @test
*
* @covers Lcobucci\JWT\Token::__construct
*/
public function constructMustInitializeAnEmptyPlainTextTokenWhenNoArgumentsArePassed()
{
$token = new Token();
$this->assertAttributeEquals(['alg' => 'none'], 'headers', $token);
$this->assertAttributeEquals([], 'claims', $token);
$this->assertAttributeEquals(null, 'signature', $token);
$this->assertAttributeEquals(['', ''], 'payload', $token);
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
*
* @covers Lcobucci\JWT\Token::hasHeader
*/
public function hasHeaderMustReturnTrueWhenItIsConfigured()
{
$token = new Token(['test' => 'testing']);
$this->assertTrue($token->hasHeader('test'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
*
* @covers Lcobucci\JWT\Token::hasHeader
*/
public function hasHeaderMustReturnFalseWhenItIsNotConfigured()
{
$token = new Token(['test' => 'testing']);
$this->assertFalse($token->hasHeader('testing'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\Token::hasHeader
*
* @covers Lcobucci\JWT\Token::getHeader
*
* @expectedException \OutOfBoundsException
*/
public function getHeaderMustRaiseExceptionWhenHeaderIsNotConfigured()
{
$token = new Token(['test' => 'testing']);
$token->getHeader('testing');
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\Token::hasHeader
*
* @covers Lcobucci\JWT\Token::getHeader
*/
public function getHeaderMustReturnTheDefaultValueWhenIsNotConfigured()
{
$token = new Token(['test' => 'testing']);
$this->assertEquals('blah', $token->getHeader('testing', 'blah'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\Token::hasHeader
*
* @covers Lcobucci\JWT\Token::getHeader
* @covers Lcobucci\JWT\Token::getHeaderValue
*/
public function getHeaderMustReturnTheRequestedHeader()
{
$token = new Token(['test' => 'testing']);
$this->assertEquals('testing', $token->getHeader('test'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\Token::hasHeader
* @uses Lcobucci\JWT\Claim\Basic
*
* @covers Lcobucci\JWT\Token::getHeader
* @covers Lcobucci\JWT\Token::getHeaderValue
*/
public function getHeaderMustReturnValueWhenItIsAReplicatedClaim()
{
$token = new Token(['jti' => new EqualsTo('jti', 1)]);
$this->assertEquals(1, $token->getHeader('jti'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
*
* @covers Lcobucci\JWT\Token::getHeaders
*/
public function getHeadersMustReturnTheConfiguredHeader()
{
$token = new Token(['test' => 'testing']);
$this->assertEquals(['test' => 'testing'], $token->getHeaders());
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
*
* @covers Lcobucci\JWT\Token::getClaims
*/
public function getClaimsMustReturnTheConfiguredClaims()
{
$token = new Token([], ['test' => 'testing']);
$this->assertEquals(['test' => 'testing'], $token->getClaims());
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\Claim\Basic
*
* @covers Lcobucci\JWT\Token::hasClaim
*/
public function hasClaimMustReturnTrueWhenItIsConfigured()
{
$token = new Token([], ['test' => new Basic('test', 'testing')]);
$this->assertTrue($token->hasClaim('test'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\Claim\Basic
*
* @covers Lcobucci\JWT\Token::hasClaim
*/
public function hasClaimMustReturnFalseWhenItIsNotConfigured()
{
$token = new Token([], ['test' => new Basic('test', 'testing')]);
$this->assertFalse($token->hasClaim('testing'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\Token::hasClaim
* @uses Lcobucci\JWT\Claim\Basic
*
* @covers Lcobucci\JWT\Token::getClaim
*/
public function getClaimMustReturnTheDefaultValueWhenIsNotConfigured()
{
$token = new Token([], ['test' => new Basic('test', 'testing')]);
$this->assertEquals('blah', $token->getClaim('testing', 'blah'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\Token::hasClaim
* @uses Lcobucci\JWT\Claim\Basic
*
* @covers Lcobucci\JWT\Token::getClaim
*
* @expectedException \OutOfBoundsException
*/
public function getClaimShouldRaiseExceptionWhenClaimIsNotConfigured()
{
$token = new Token();
$token->getClaim('testing');
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\Token::hasClaim
* @uses Lcobucci\JWT\Claim\Basic
*
* @covers Lcobucci\JWT\Token::getClaim
*/
public function getClaimShouldReturnTheClaimValueWhenItExists()
{
$token = new Token([], ['testing' => new Basic('testing', 'test')]);
$this->assertEquals('test', $token->getClaim('testing'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
*
* @covers Lcobucci\JWT\Token::verify
*
* @expectedException BadMethodCallException
*/
public function verifyMustRaiseExceptionWhenTokenIsUnsigned()
{
$signer = $this->createMock(Signer::class);
$token = new Token();
$token->verify($signer, 'test');
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
*
* @covers Lcobucci\JWT\Token::verify
* @covers Lcobucci\JWT\Token::getPayload
*/
public function verifyShouldReturnFalseWhenTokenAlgorithmIsDifferent()
{
$signer = $this->createMock(Signer::class);
$signature = $this->createMock(Signature::class, [], [], '', false);
$signer->expects($this->any())
->method('getAlgorithmId')
->willReturn('HS256');
$signature->expects($this->never())
->method('verify');
$token = new Token(['alg' => 'RS256'], [], $signature);
$this->assertFalse($token->verify($signer, 'test'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
*
* @covers Lcobucci\JWT\Token::verify
* @covers Lcobucci\JWT\Token::getPayload
*/
public function verifyMustDelegateTheValidationToSignature()
{
$signer = $this->createMock(Signer::class);
$signature = $this->createMock(Signature::class, [], [], '', false);
$signer->expects($this->any())
->method('getAlgorithmId')
->willReturn('HS256');
$signature->expects($this->once())
->method('verify')
->with($signer, $this->isType('string'), 'test')
->willReturn(true);
$token = new Token(['alg' => 'HS256'], [], $signature);
$this->assertTrue($token->verify($signer, 'test'));
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\Token::validate
* @covers Lcobucci\JWT\Token::getValidatableClaims
*/
public function validateShouldReturnTrueWhenClaimsAreEmpty()
{
$token = new Token();
$this->assertTrue($token->validate(new ValidationData()));
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
* @uses Lcobucci\JWT\Claim\Basic::__construct
*
* @covers Lcobucci\JWT\Token::validate
* @covers Lcobucci\JWT\Token::getValidatableClaims
*/
public function validateShouldReturnTrueWhenThereAreNoValidatableClaims()
{
$token = new Token([], ['testing' => new Basic('testing', 'test')]);
$this->assertTrue($token->validate(new ValidationData()));
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\ValidationData
* @uses Lcobucci\JWT\Claim\Basic
* @uses Lcobucci\JWT\Claim\EqualsTo
*
* @covers Lcobucci\JWT\Token::validate
* @covers Lcobucci\JWT\Token::getValidatableClaims
*/
public function validateShouldReturnFalseWhenThereIsAtLeastOneFailedValidatableClaim()
{
$token = new Token(
[],
[
'iss' => new EqualsTo('iss', 'test'),
'testing' => new Basic('testing', 'test')
]
);
$data = new ValidationData();
$data->setIssuer('test1');
$this->assertFalse($token->validate($data));
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\ValidationData
* @uses Lcobucci\JWT\Claim\Basic
* @uses Lcobucci\JWT\Claim\EqualsTo
* @uses Lcobucci\JWT\Claim\LesserOrEqualsTo
* @uses Lcobucci\JWT\Claim\GreaterOrEqualsTo
*
* @covers Lcobucci\JWT\Token::validate
* @covers Lcobucci\JWT\Token::getValidatableClaims
*/
public function validateShouldReturnFalseWhenATimeBasedClaimFails()
{
$now = time();
$token = new Token(
[],
[
'iss' => new EqualsTo('iss', 'test'),
'iat' => new LesserOrEqualsTo('iat', $now),
'nbf' => new LesserOrEqualsTo('nbf', $now + 20),
'exp' => new GreaterOrEqualsTo('exp', $now + 500),
'testing' => new Basic('testing', 'test')
]
);
$data = new ValidationData($now + 10);
$data->setIssuer('test');
$this->assertFalse($token->validate($data));
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\ValidationData
* @uses Lcobucci\JWT\Claim\Basic
* @uses Lcobucci\JWT\Claim\EqualsTo
* @uses Lcobucci\JWT\Claim\LesserOrEqualsTo
* @uses Lcobucci\JWT\Claim\GreaterOrEqualsTo
*
* @covers Lcobucci\JWT\Token::validate
* @covers Lcobucci\JWT\Token::getValidatableClaims
*/
public function validateShouldReturnTrueWhenThereAreNoFailedValidatableClaims()
{
$now = time();
$token = new Token(
[],
[
'iss' => new EqualsTo('iss', 'test'),
'iat' => new LesserOrEqualsTo('iat', $now),
'exp' => new GreaterOrEqualsTo('exp', $now + 500),
'testing' => new Basic('testing', 'test')
]
);
$data = new ValidationData($now + 10);
$data->setIssuer('test');
$this->assertTrue($token->validate($data));
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\ValidationData
* @uses Lcobucci\JWT\Claim\Basic
* @uses Lcobucci\JWT\Claim\EqualsTo
* @uses Lcobucci\JWT\Claim\LesserOrEqualsTo
* @uses Lcobucci\JWT\Claim\GreaterOrEqualsTo
*
* @covers Lcobucci\JWT\Token::validate
* @covers Lcobucci\JWT\Token::getValidatableClaims
*/
public function validateShouldReturnTrueWhenLeewayMakesAllTimeBasedClaimsTrueAndOtherClaimsAreTrue()
{
$now = time();
$token = new Token(
[],
[
'iss' => new EqualsTo('iss', 'test'),
'iat' => new LesserOrEqualsTo('iat', $now),
'nbf' => new LesserOrEqualsTo('nbf', $now + 20),
'exp' => new GreaterOrEqualsTo('exp', $now + 500),
'testing' => new Basic('testing', 'test')
]
);
$data = new ValidationData($now + 10, 20);
$data->setIssuer('test');
$this->assertTrue($token->validate($data));
}
/**
* @test
*
* @covers Lcobucci\JWT\Token::isExpired
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\Token::getClaim
* @uses Lcobucci\JWT\Token::hasClaim
*/
public function isExpiredShouldReturnFalseWhenTokenDoesNotExpires()
{
$token = new Token(['alg' => 'none']);
$this->assertFalse($token->isExpired());
}
/**
* @test
*
* @covers Lcobucci\JWT\Token::isExpired
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\Token::getClaim
* @uses Lcobucci\JWT\Token::hasClaim
* @uses Lcobucci\JWT\Claim\Basic
* @uses Lcobucci\JWT\Claim\GreaterOrEqualsTo
*/
public function isExpiredShouldReturnFalseWhenTokenIsNotExpired()
{
$token = new Token(
['alg' => 'none'],
['exp' => new GreaterOrEqualsTo('exp', time() + 500)]
);
$this->assertFalse($token->isExpired());
}
/**
* @test
*
* @covers Lcobucci\JWT\Token::isExpired
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\Token::getClaim
* @uses Lcobucci\JWT\Token::hasClaim
* @uses Lcobucci\JWT\Claim\Basic
* @uses Lcobucci\JWT\Claim\GreaterOrEqualsTo
*/
public function isExpiredShouldReturnTrueAfterTokenExpires()
{
$token = new Token(
['alg' => 'none'],
['exp' => new GreaterOrEqualsTo('exp', time())]
);
$this->assertTrue($token->isExpired(new DateTime('+10 days')));
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
*
* @covers Lcobucci\JWT\Token::getPayload
*/
public function getPayloadShouldReturnAStringWithTheTwoEncodePartsThatGeneratedTheToken()
{
$token = new Token(['alg' => 'none'], [], null, ['test1', 'test2', 'test3']);
$this->assertEquals('test1.test2', $token->getPayload());
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\Token::getPayload
*
* @covers Lcobucci\JWT\Token::__toString
*/
public function toStringMustReturnEncodedDataWithEmptySignature()
{
$token = new Token(['alg' => 'none'], [], null, ['test', 'test']);
$this->assertEquals('test.test.', (string) $token);
}
/**
* @test
*
* @uses Lcobucci\JWT\Token::__construct
* @uses Lcobucci\JWT\Token::getPayload
*
* @covers Lcobucci\JWT\Token::__toString
*/
public function toStringMustReturnEncodedData()
{
$signature = $this->createMock(Signature::class, [], [], '', false);
$token = new Token(['alg' => 'none'], [], $signature, ['test', 'test', 'test']);
$this->assertEquals('test.test.test', (string) $token);
}
}

View File

@@ -0,0 +1,270 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT;
/**
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/
class ValidationDataTest extends \PHPUnit\Framework\TestCase
{
/**
* @test
*
* @covers Lcobucci\JWT\ValidationData::__construct
* @covers Lcobucci\JWT\ValidationData::setCurrentTime
*/
public function constructorShouldConfigureTheItems()
{
$expected = $this->createExpectedData();
$data = new ValidationData(1);
$this->assertAttributeSame($expected, 'items', $data);
}
/**
* @test
*
* @covers Lcobucci\JWT\ValidationData::__construct
* @covers Lcobucci\JWT\ValidationData::setCurrentTime
*/
public function constructorWithLeewayShouldConfigureTheItems()
{
$expected = $this->createExpectedData(null, null, null, null, 111, 111, 89);
$data = new ValidationData(100, 11);
$this->assertAttributeSame($expected, 'items', $data);
}
/**
* @test
*
* @dataProvider claimValues
*
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\ValidationData::setId
*/
public function setIdShouldChangeTheId($id)
{
$expected = $this->createExpectedData($id);
$data = new ValidationData(1);
$data->setId($id);
$this->assertAttributeSame($expected, 'items', $data);
}
/**
* @test
*
* @dataProvider claimValues
*
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\ValidationData::setIssuer
*/
public function setIssuerShouldChangeTheIssuer($iss)
{
$expected = $this->createExpectedData(null, null, $iss);
$data = new ValidationData(1);
$data->setIssuer($iss);
$this->assertAttributeSame($expected, 'items', $data);
}
/**
* @test
*
* @dataProvider claimValues
*
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\ValidationData::setAudience
*/
public function setAudienceShouldChangeTheAudience($aud)
{
$expected = $this->createExpectedData(null, null, null, $aud);
$data = new ValidationData(1);
$data->setAudience($aud);
$this->assertAttributeSame($expected, 'items', $data);
}
/**
* @test
*
* @dataProvider claimValues
*
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\ValidationData::setSubject
*/
public function setSubjectShouldChangeTheSubject($sub)
{
$expected = $this->createExpectedData(null, $sub);
$data = new ValidationData(1);
$data->setSubject($sub);
$this->assertAttributeSame($expected, 'items', $data);
}
/**
* @test
*
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\ValidationData::setCurrentTime
*/
public function setCurrentTimeShouldChangeTheTimeBasedValues()
{
$expected = $this->createExpectedData(null, null, null, null, 2);
$data = new ValidationData(1);
$data->setCurrentTime(2);
$this->assertAttributeSame($expected, 'items', $data);
}
/**
* @test
*
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\ValidationData::setCurrentTime
*/
public function setCurrentTimeShouldChangeTheTimeBasedValuesUsingLeeway()
{
$expected = $this->createExpectedData(null, null, null, null, 30, 30, 10);
$data = new ValidationData(15, 10);
$data->setCurrentTime(20);
$this->assertAttributeSame($expected, 'items', $data);
}
/**
* @test
*
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\ValidationData::has
*/
public function hasShouldReturnTrueWhenItemIsNotEmpty()
{
$data = new ValidationData(1);
$this->assertTrue($data->has('iat'));
}
/**
* @test
*
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\ValidationData::has
*/
public function hasShouldReturnFalseWhenItemIsEmpty()
{
$data = new ValidationData(1);
$this->assertFalse($data->has('jti'));
}
/**
* @test
*
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\ValidationData::has
*/
public function hasShouldReturnFalseWhenItemIsNotDefined()
{
$data = new ValidationData(1);
$this->assertFalse($data->has('test'));
}
/**
* @test
*
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\ValidationData::get
*/
public function getShouldReturnTheItemValue()
{
$data = new ValidationData(1);
$this->assertEquals(1, $data->get('iat'));
}
/**
* @test
*
* @uses Lcobucci\JWT\ValidationData::__construct
* @uses Lcobucci\JWT\ValidationData::setCurrentTime
*
* @covers Lcobucci\JWT\ValidationData::get
*/
public function getShouldReturnNullWhenItemIsNotDefined()
{
$data = new ValidationData(1);
$this->assertNull($data->get('test'));
}
/**
* @return array
*/
public function claimValues()
{
return [
[1],
['test']
];
}
/**
* @param string|null $id
* @param string|null $sub
* @param string|null $iss
* @param string|null $aud
* @param int $iat
* @param int|null $nbf
* @param int|null $exp
*
* @return array
*/
private function createExpectedData(
$id = null,
$sub = null,
$iss = null,
$aud = null,
$iat = 1,
$nbf = null,
$exp = null
) {
return [
'jti' => $id !== null ? (string) $id : null,
'iss' => $iss !== null ? (string) $iss : null,
'aud' => $aud !== null ? (string) $aud : null,
'sub' => $sub !== null ? (string) $sub : null,
'iat' => $iat,
'nbf' => $nbf !== null ? $nbf: $iat,
'exp' => $exp !== null ? $exp: $iat
];
}
}