Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
miladrahimi committed Jun 2, 2018
0 parents commit 9101e34
Show file tree
Hide file tree
Showing 72 changed files with 3,682 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/vendor
/composer.lock
/.idea
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2018 Milad Rahimi

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.
222 changes: 222 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
# PHP-JWT
A PHP implementation of JWT (JSON Web Token) generator, parser, verifier, and validator

## Overview
PHP JWT is a package written in PHP programming language for encoding (generating), decoding (parsing), verifying
and validating JWTs (JSON Web Tokens).

## Documentation

### Installation
Add the package to your project composer packages with the following command:

```
composer require miladrahimi/larajwt:0.2.*
```

Now, you are ready to use the package!

### What is JWT
If you are unfamiliar with JWT you can read [Wikipedia](https://en.wikipedia.org/wiki/JSON_Web_Token) or
[JWT.io](https://jwt.io) website.

### Getting Started
The following snippet demonstrates how to generate a JWT with the HS256 algorithm and a custom secret key.

```
use MiladRahimi\Jwt\Cryptography\Algorithms\Hmac\HS256;
use MiladRahimi\Jwt\JwtGenerator;
use MiladRahimi\Jwt\JwtParser;
// ...
$key = 'some random key';
$signer = new HS256($key);
$generator = new JwtGenerator($signer);
$jwt = $generator->generate(['sub' => 1, 'jti' => 2]);
$parser = new JwtParser($signer);
$claims = $parser->parse($jwt);
```

### HMAC Algorithms
If you want to use a single key to both generate and parse tokens,
you should use HMAC algorithms (HS256, HS384, and HS512).
These algorithms use the same key to sign and verifying tokens.

```
use MiladRahimi\Jwt\Cryptography\Algorithms\Hmac\HS512;
use MiladRahimi\Jwt\JwtGenerator;
use MiladRahimi\Jwt\JwtParser;
// ...
$key = 'some random key';
$signer = $verifyer = new HS512($key);
$generator = new JwtGenerator($signer);
$jwt = $generator->generate(['sub' => 1, 'jti' => 2]);
$parser = new JwtParser($verifyer);
$claims = $parser->parse($jwt);
```

### RSA Algorithms
If you want to use asymmetric keys to generate and parse tokens,
you should use RSA algorithms (RS256, RS384, and RS512).
These algorithms use pair (public/private) keys and consequently,
different signer and verifier which the signer uses the private key and the verifier uses the public key.

```
use MiladRahimi\Jwt\Cryptography\Algorithms\Rsa\Signers\RS256 as RS256Signer;
use MiladRahimi\Jwt\Cryptography\Algorithms\Rsa\Verifiers\RS256 as RS256Verifier;
use MiladRahimi\Jwt\Cryptography\Keys\PrivateKey;
use MiladRahimi\Jwt\Cryptography\Keys\PublicKey;
use MiladRahimi\Jwt\JwtGenerator;
use MiladRahimi\Jwt\JwtParser;
// ...
$privateKey = new PrivateKey('keys/private.pem');
$publicKey = new PublicKey('keys/public.pem');
$signer = new RS256Signer($privateKey);
$verifier = new RS256Verifier($publicKey);
$generator = new JwtGenerator($signer);
$jwt = $generator->generate(['sub' => 1, 'jti' => 2]);
$parser = new JwtParser($verifier);
$claims = $parser->parse($jwt);
```

You can read [this instruction](https://en.wikibooks.org/wiki/Cryptography/Generate_a_keypair_using_OpenSSL)
web page to learn how to generate a pair (public/private) key.

### Token Generating
You can generate JWTs with `JwtGenerator::generate()` method.
This method needs a signer algorithm to sign tokens.
As you can see in preceding sections, you can use HMAC-based or RSA-based signers for generating tokens.
HMAC signers need a symmetric key. HMAC verifiers use the same key to verify the token, that's why we call it symmetric.
RSA signers need a private key to sign.
Both HMAC and RSA signers throw an `InvalidKeyException` exception if the provided key is not valid.

```
use MiladRahimi\Jwt\Cryptography\Algorithms\Rsa\Signers\RS256;
use MiladRahimi\Jwt\Cryptography\Keys\PrivateKey;
use MiladRahimi\Jwt\JwtGenerator;
use MiladRahimi\Jwt\Exceptions\InvalidKeyException;
// ...
try {
$privateKey = new PrivateKey('keys/private.pem');
} catch(InvalidKeyException $e) {
// Your key is invalid.
}
$signer = new RS256($privateKey);
$generator = new JwtGenerator($signer);
$jwt = $generator->generate(['sub' => 1, 'jti' => 2]);
```

### Verification and Validation
Before extracting claims from tokens, the tokens must be verified and validated.
First, we verify the token by its signature so that we make sure that it is generated by the original issuer.
After signature verification, we must validate claims,
some public claims that should be validated are 'exp', 'iat', and 'nbf', of course,
you can add your custom claim validations.

The `parse()` method verifies and validates claims automatically.
If you don't need to parse the token and only need to verify and validate it, you can use `validate()` method.
If you don't need to validate the token and only need to verify its signature you can use `verifySignature()` method.

The `parse()` method verifies and validates claims automatically.
If you don't need to parse the token and only need to verify and validate it, you can use `validate()` method.
If you don't need to validate the token and only need to verify its signature you can use `verifySignature()` method.
All methods throw `InvalidSignatureException` exception when the token signature is invalid.
The `validate()` and `parse()` method throw `ValidationException` when the token claims are invalid
and `InvalidJsonException` exception when cannot parse JSON, `InvalidTokenException`
when the token format is invalid (it's not three part).
All these exceptions are also children of `InvalidTokenException` so
if you don't care about the failure reason you can only catch this exception.

```
use MiladRahimi\Jwt\Cryptography\Algorithms\Hmac\HS512;
use MiladRahimi\Jwt\JwtGenerator;
use MiladRahimi\Jwt\JwtParser;
use MiladRahimi\Jwt\Exceptions\InvalidTokenException
// ...
$jwt = // read from header...
$verifyer = new HS512('some random key');
$parser = new JwtParser($verifyer);
try {
$parser->validate($jwt);
// token is valid...
} catch (InvalidTokenException $e) {
// token is not valid...
}
```

### Custom Validation
The `JwtParser` use the default validator (`DefaultValidator`) to validate tokens in `parse()` and `validate()` methods.
This validator would care about `exp`, `iat` and `nbf` claims if they were in the payload.
You can create an instance of `DefaultValidator` or `Validator` (empty with no rule) and add your own rules like this:

```
use MiladRahimi\Jwt\Cryptography\Algorithms\Hmac\HS512;
use MiladRahimi\Jwt\JwtGenerator;
use MiladRahimi\Jwt\JwtParser;
use MiladRahimi\Jwt\Exceptions\InvalidTokenException
use MiladRahimi\Jwt\Validator\Rules\Required\Exists;
use MiladRahimi\Jwt\Validator\Rules\Required\ConsistsOf;
use MiladRahimi\Jwt\Validator\Rules\Required\NewerThan;
// ...
$jwt = // read from header...
$verifyer = new HS512('some random key');
$validator = new DefaultValidator();
$validator->addRule('iss', new Exists());
$validator->addRule('aud', new ConsistsOf('Company'));
$validator->addRule('future-time', new NewerThan(time()));
$parser = new JwtParser($verifyer, $validator);
try {
$claims = $parser->parse($jwt);
// token is valid...
} catch (InvalidTokenException $e) {
// token is not valid...
}
```

As you can see in the snippet above, you can instantiate a validator and add your own rules to it.
To add a new rule, you must pass the claim name you are setting rule for and the rule
which is an object from the rule classes.
there are two categories of rules named optional and required.
The optional rules would be checked only when the claim did exist but
the required rules would fail the validation if the claim did not exist.

### Contribute

Any contribution will be appreciated :D

## License
This package is released under the [MIT License](http://opensource.org/licenses/mit-license.php).
36 changes: 36 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "miladrahimi/php-jwt",
"description": "A PHP implementation of JWT (JSON Web Token) generator, parser, verifier, and validator",
"keywords": [
"JWT",
"JSON Web Token",
"Token",
"Parser",
"Encoder",
"Decoder",
"Verifier",
"Validator"
],
"homepage": "https://github.com/miladrahimi/php-jwt",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Milad Rahimi",
"email": "info@miladrahimi.com"
}
],
"require": {
"php": ">=7.0",
"ext-openssl": "*"
},
"require-dev": {
"phpunit/phpunit": "^6"
},
"autoload": {
"psr-4": {
"MiladRahimi\\Jwt\\": "src/MiladRahimi/Jwt/",
"MiladRahimi\\Jwt\\Tests\\": "tests/"
}
}
}
39 changes: 39 additions & 0 deletions src/MiladRahimi/Jwt/Base64/Base64Parser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php
/**
* Created by PhpStorm.
* User: Milad Rahimi <info@miladrahimi.com>
* Date: 5/13/2018 AD
* Time: 23:47
*/

namespace MiladRahimi\Jwt\Base64;

class Base64Parser implements Base64ParserInterface
{
/**
* Encode data by Base64 algorithm
*
* @param string $data
* @return string
*/
public function encode(string $data): string
{
return str_replace('=', '', strtr(base64_encode($data), '+/', '-_'));
}

/**
* Decode Base64-encoded data to plain text
*
* @param string $data
* @return string
*/
public function decode(string $data): string
{
if ($remainder = strlen($data) % 4) {
$paddingLength = 4 - $remainder;
$data .= str_repeat('=', $paddingLength);
}

return base64_decode(strtr($data, '-_', '+/'));
}
}
28 changes: 28 additions & 0 deletions src/MiladRahimi/Jwt/Base64/Base64ParserInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php
/**
* Created by PhpStorm.
* User: Milad Rahimi <info@miladrahimi.com>
* Date: 5/14/2018 AD
* Time: 00:39
*/

namespace MiladRahimi\Jwt\Base64;

interface Base64ParserInterface
{
/**
* Encode data by Base64 algorithm
*
* @param string $data
* @return string
*/
public function encode(string $data): string;

/**
* Decode Base64-encoded data to plain text
*
* @param string $data
* @return string
*/
public function decode(string $data): string;
}
Loading

0 comments on commit 9101e34

Please sign in to comment.