Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support php5.5 #8

Merged
merged 8 commits into from
Jul 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,18 @@ git:

language: php
php:
- 5.5
- 5.6
- 7.0
- 7.1
- 7.2

install:
- composer install --prefer-dist

before_script:
- for P in src tests; do find $P -type f -name '*.php' -exec php -l {} \;; done

script:
- vendor/bin/phpunit --coverage-text --coverage-clover=coverage.xml

Expand Down
9 changes: 5 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "adhocore/jwt",
"description": "Ultra lightweight JSON web token (JWT) library for PHP7.",
"description": "Ultra lightweight JSON web token (JWT) library for PHP5.5+.",
"type": "library",
"keywords": [
"jwt", "jwt-php", "auth", "json-web-token", "token"
Expand All @@ -15,17 +15,18 @@
"autoload": {
"psr-4": {
"Ahc\\Jwt\\": "src/"
}
},
"files": ["src/functions.php"]
},
"autoload-dev": {
"psr-4": {
"Ahc\\Jwt\\Test\\": "tests/"
}
},
"require": {
"php": ">=7.0"
"php": ">=5.5"
},
"require-dev": {
"phpunit/phpunit": "^6.0.0"
"phpunit/phpunit": "^4.8 || ^5.7 || ^6.5"
}
}
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)


- Lightweight JSON Web Token (JWT) library for PHP7.
- Lightweight JSON Web Token (JWT) library for PHP5.5 or newer.

## Installation
```
Expand Down
22 changes: 11 additions & 11 deletions src/JWT.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Ahc\Jwt;

/**
* JSON Web Token (JWT) implementation in PHP7.
* JSON Web Token (JWT) implementation in PHP5.5+.
*
* @author Jitendra Adhikari <jiten.adhikary@gmail.com>
* @license MIT
Expand Down Expand Up @@ -68,7 +68,7 @@ class JWT
* @param int $leeway Leeway for clock skew. Shouldnot be more than 2 minutes (120s).
* @param string $pass The passphrase (only for RS* algos).
*/
public function __construct($key, string $algo = 'HS256', int $maxAge = 3600, int $leeway = 0, string $pass = null)
public function __construct($key, $algo = 'HS256', $maxAge = 3600, $leeway = 0, $pass = null)
{
$this->validateConfig($key, $algo, $maxAge, $leeway);

Expand All @@ -91,7 +91,7 @@ public function __construct($key, string $algo = 'HS256', int $maxAge = 3600, in
*
* @return self
*/
public function registerKeys(array $keys): self
public function registerKeys(array $keys)
{
$this->keys = \array_merge($this->keys, $keys);

Expand All @@ -106,14 +106,14 @@ public function registerKeys(array $keys): self
*
* @return string URL safe JWT token.
*/
public function encode(array $payload, array $header = []) : string
public function encode(array $payload, array $header = [])
{
$header = ['typ' => 'JWT', 'alg' => $this->algo] + $header;

$this->validateKid($header);

if (!isset($payload['iat']) && !isset($payload['exp'])) {
$payload['exp'] = ($this->timestamp ?? \time()) + $this->maxAge;
$payload['exp'] = ($this->timestamp ?: \time()) + $this->maxAge;
}

$header = $this->urlSafeEncode($header);
Expand All @@ -130,7 +130,7 @@ public function encode(array $payload, array $header = []) : string
*
* @return array
*/
public function decode(string $token) : array
public function decode($token)
{
if (\substr_count($token, '.') < 2) {
throw new JWTException('Invalid token: Incomplete segments', static::ERROR_TOKEN_INVALID);
Expand All @@ -156,7 +156,7 @@ public function decode(string $token) : array
*
* @param int|null $timestamp
*/
public function setTestTimestamp(int $timestamp = null) : JWT
public function setTestTimestamp($timestamp = null)
{
$this->timestamp = $timestamp;

Expand All @@ -170,7 +170,7 @@ public function setTestTimestamp(int $timestamp = null) : JWT
*
* @return string
*/
protected function sign(string $input) : string
protected function sign($input)
{
// HMAC SHA.
if (\substr($this->algo, 0, 2) === 'HS') {
Expand All @@ -194,7 +194,7 @@ protected function sign(string $input) : string
*
* @return bool
*/
protected function verify(string $input, string $signature) : bool
protected function verify($input, $signature)
{
$algo = $this->algos[$this->algo];

Expand All @@ -221,7 +221,7 @@ protected function verify(string $input, string $signature) : bool
*
* @return string
*/
protected function urlSafeEncode($data) : string
protected function urlSafeEncode($data)
{
if (\is_array($data)) {
$data = \json_encode($data, JSON_UNESCAPED_SLASHES);
Expand All @@ -241,7 +241,7 @@ protected function urlSafeEncode($data) : string
*
* @return array|\stdClass|string
*/
protected function urlSafeDecode(string $data, bool $asJson = true)
protected function urlSafeDecode($data, $asJson = true)
{
if (!$asJson) {
return \base64_decode(\strtr($data, '-_', '+/'));
Expand Down
6 changes: 3 additions & 3 deletions src/ValidatesJWT.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ trait ValidatesJWT
*
* @codeCoverageIgnore
*/
protected function validateConfig($key, string $algo, int $maxAge, int $leeway)
protected function validateConfig($key, $algo, $maxAge, $leeway)
{
if (empty($key)) {
throw new JWTException('Signing key cannot be empty', static::ERROR_KEY_EMPTY);
Expand Down Expand Up @@ -71,7 +71,7 @@ protected function validateKid(array $header)
*/
protected function validateTimestamps(array $payload)
{
$timestamp = $this->timestamp ?? \time();
$timestamp = $this->timestamp ?: \time();
$checks = [
['exp', $this->leeway /* */ , static::ERROR_TOKEN_EXPIRED, 'Expired'],
['iat', $this->maxAge - $this->leeway, static::ERROR_TOKEN_EXPIRED, 'Expired'],
Expand Down Expand Up @@ -100,7 +100,7 @@ protected function validateKey()
$key = 'file://' . $key;
}

$this->key = \openssl_get_privatekey($key, $this->passphrase ?? '');
$this->key = \openssl_get_privatekey($key, $this->passphrase ?: '');
}

if (!\is_resource($this->key)) {
Expand Down
23 changes: 23 additions & 0 deletions src/functions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

// @codeCoverageIgnoreStart
if (!\function_exists('hash_equals')) {
// PHP5.5 compat.
// @see http://php.net/manual/en/function.hash-equals.php#115635
function hash_equals($str1, $str2)
{
if (\strlen($str1) !== \strlen($str2)) {
return false;
}

$ret = 0;
$res = $str1 ^ $str2;

for ($i = \strlen($res) - 1; $i >= 0; $i--) {
$ret |= ord($res[$i]);
}

return !$ret;
}
}
// @codeCoverageIgnoreEnd
41 changes: 22 additions & 19 deletions tests/JWTTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
namespace Ahc\Jwt\Test;

use Ahc\Jwt\JWT;
use Ahc\Jwt\JWTException;

/** @coversDefaultClass \Ahc\Jwt\JWT */
class JWTTest extends \PHPUnit\Framework\TestCase
{
/** @dataProvider data1 */
public function test_decode_encoded_token(string $key, string $algo, int $age, int $leeway, array $payload, array $header = [])
public function test_decode_encoded_token($key, $algo, $age, $leeway, array $payload, array $header = [])
{
$jwt = new JWT($key, $algo, $age, $leeway);
$token = $jwt->encode($payload, $header);
Expand All @@ -26,26 +25,28 @@ public function test_decode_encoded_token(string $key, string $algo, int $age, i
$this->assertSame($payload, $decoded);
}

/**
* @expectedException \Ahc\Jwt\JWTException
*/
public function test_json_fail()
{
$this->expectException(JWTException::class);

$jwt = new JWT('very^secre7');

try {
$jwt->encode([random_bytes(10)]);
$jwt->encode([base64_decode('mF6u28o4K2cD3w==')]);
} catch (\Exception $e) {
$this->assertSame($e->getCode(), JWT::ERROR_JSON_FAILED, $e->getMessage());

throw $e;
}
}

/** @dataProvider data2 */
public function test_decode_fail(string $key, string $algo, int $age, int $leeway, int $offset, int $error, $token)
/**
* @dataProvider data2
* @expectedException \Ahc\Jwt\JWTException
*/
public function test_decode_fail($key, $algo, $age, $leeway, $offset, $error, $token)
{
$this->expectException(JWTException::class);

$jwt = new JWT($key, $algo, $age, $leeway);
$token = is_string($token) ? $token : $jwt->encode($token);

Expand All @@ -63,7 +64,7 @@ public function test_decode_fail(string $key, string $algo, int $age, int $leewa
}

/** @dataProvider data1 */
public function test_rs_decode_encoded(string $key, string $algo, int $age, int $leeway, array $payload, array $header = [])
public function test_rs_decode_encoded($key, $algo, $age, $leeway, array $payload, array $header = [])
{
$key = __DIR__ . '/stubs/priv.key';
$jwt = new JWT($key, str_replace('HS', 'RS', $algo), $age, $leeway);
Expand All @@ -81,11 +82,12 @@ public function test_rs_decode_encoded(string $key, string $algo, int $age, int
$this->assertSame($payload, $decoded);
}

/** @dataProvider data3 */
public function test_rs_invalid_key(string $method, string $key, $arg)
/**
* @dataProvider data3
* @expectedException \Ahc\Jwt\JWTException
*/
public function test_rs_invalid_key($method, $key, $arg)
{
$this->expectException(JWTException::class);

$jwt = new JWT($key, 'RS256');

try {
Expand All @@ -109,19 +111,20 @@ public function test_kid()
return $jwt;
}

/**
* @expectedException \Ahc\Jwt\JWTException
* @expectedExceptionMessage Invalid token: Unknown key ID
*/
public function test_kid_invalid()
{
// keys can be sent as array too
$jwt = new JWT(['key1' => 'secret1', 'key2' => 'secret2'], 'HS256');

$this->expectException(JWTException::class);
$this->expectExceptionMessage('Invalid token: Unknown key ID');

// Use key3
$jwt->encode(['a' => 1, 'exp' => time() + 1000], ['kid' => 'key3']);
}

public function data1() : array
public function data1()
{
return [
['secret', 'HS256', rand(10, 1000), rand(1, 10), [
Expand Down Expand Up @@ -152,7 +155,7 @@ public function data1() : array
];
}

public function data2() : array
public function data2()
{
return [
['topsecret', 'HS256', 5, 0, 0, JWT::ERROR_TOKEN_INVALID, 'a.b'],
Expand Down