andrewdyer/jwt-auth

A simple JWT authentication solution that you can integrate into the framework of your choice

v0.1.0 2018-11-16 13:31 UTC

README

Codacy Badge Latest Stable Version Latest Unstable Version License Total Downloads Daily Downloads Monthly Downloads composer.lock

A simple JWT authentication solution that you can integrate into the framework of your choice.

Index

License

Licensed under MIT. Totally free for private or commercial projects.

Requirements

  • PHP 7+
  • Composer

Installation

composer require andrewdyer/jwt-auth

Usage

$authService = new \App\Services\AuthService();

$firebaseProvider = new \Anddye\Providers\FirebaseProvider([
    'algorithm' => '',
    'secret'    => '',
]);

$jwtAuth = new \Anddye\Auth\JwtAuth($authService, $firebaseProvider, [
    'exp' => '',
    'iat' => '',
    'iss' => '',
    'jti' => '',
    'nbf' => '',
]);

Setting up an Auth Service

The auth service will be used to grab a user from the database based on their credentials. This can be done in many different ways, but for this example we will use Laravel Eloquent.

So first things first, we'll need to add a model and auth service to your project:

User Model

namespace App\Models;

use Anddye\Interfaces\JwtSubjectInterface;
use Illuminate\Database\Eloquent\Model;

class User extends Model implements JwtSubjectInterface
{
    protected $hidden = [
        'password'
    ];

    public function getJwtIdentifier()
    {
        return $this->id;
    }
}

Auth Service

namespace App\Services;

use Exception;
use App\Models\User;
use Anddye\Interfaces\AuthServiceInterface;
use Anddye\Interfaces\JwtSubjectInterface;

class AuthService implements AuthServiceInterface
{
    public function byCredentials(string $username, string $password): JwtSubjectInterface
    {
        if (!$user = User::where('username', $username)->first()) {
            throw new Exception('User not found!');
        }
        
        if (!password_verify($password, $user->password)) {
            throw new Exception('Password not valid!');
        }
        
        return $user;
    }

    public function byId(int $id): JwtSubjectInterface
    {
        if (!$user = User::find($id)) {
            throw new Exception('User not found!');
        }
        
        return $user;
    }
}

Remember, you can use whatever solution you like to get a user from the database, as long as the returned object is an instance of \Anddye\Interfaces\JwtSubjectInterface so we can grab a JWT identifier in order to build up the token sub. Once you have decided on your database solution, you can create a new instance of your auth service:

$authService = new \App\Services\AuthService();

Setting up the JWT Provider

The JWT provider is used to encode and decode the token. For this, we will use the \Anddye\Providers\FirebaseProvider, which takes an array of options. The only required option is secret but you can also set the algorithm.

$firebaseProvider = new \Anddye\Providers\FirebaseProvider([
    'algorithm' => '',
    'secret'    => '',
]);

As like the auth service, you can use whatever solution you want as a JWT provider - as long as it implements the \Anddye\Interfaces\JwtProviderInterface interface.

Supported Options

Option Type Description
algorithm string The signing algorithm. Supported algorithms are HS256, HS384, HS512 and RS256. The defaut value is HS256.
secret string The secret key. This is a require value.

Setting Up Default Claims

The claims are an array of information that we want to transmit with our token. Setting the claims is completely optional but recommended you configure them to meet your application requirements.

$claims = [
    'exp' => '',
    'iat' => '',
    'iss' => '',
    'jti' => '',
    'nbf' => '',
];

Supported Options

Option Type Description
exp integer Identifies the number of minutes after which the JWT must not be accepted for processing. Default value is 1 minute from the current time.
iat integer Identifies the time at which the JWT was issued. Default value is the current timestamp.
iss string Identifies principal that issued the JWT. E.g. http://example.com. Default value is a empty string.
jti string Case sensitive unique identifier of the token even among different issuers. Default value is a randomly generated string.
nbf integer Identifies the time on which the JWT will start to be accepted for processing. Default value is the current timestamp.

Attempt Auth

if (!$token = $jwtAuth->attempt($_POST['username'], $_POST['password'])) {
    // Invalid login credentials
    // Kill the page, return error or redirect etc 
    return ['error' => 'Invalid login credentials'];
}

// Valid login credentials
return ['token' => $token];

Validating a Token

$headers = apache_request_headers();
if(isset($headers['Authorization'])){
    try {
        $jwtAuth->authenticate($$headers['Authorization']);
        
        // Everything is awesome, authentication is successful...
        
    } catch (Exception $ex) {
        // Something has gone wrong, authentication is unsuccessful...
    }
} 

Support

If you are having general issues with this library, then please feel free to contact me on Twitter.

If you believe you have found an issue, please report it using the issue tracker, or better yet, fork the repository and submit a pull request.

If you're using this package, I'd love to hear your thoughts!

Useful Links