Skip to content

Commit 4e9a850

Browse files
author
Diego Hernandes
committed
initial
0 parents  commit 4e9a850

File tree

10 files changed

+1019
-0
lines changed

10 files changed

+1019
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
composer.lock
2+
/vendor

composer.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "kino/laravel-jwt",
3+
"description": "Dead simple JWT Auth Provider for Laravel 5.4+",
4+
"type": "library",
5+
"license": "MIT",
6+
"authors": [
7+
{
8+
"name": "Diego Hernandes",
9+
"email": "[email protected]"
10+
}
11+
],
12+
"autoload": {
13+
"psr-4": {
14+
"Kino\\Auth\\JWT\\": "src/"
15+
}
16+
},
17+
"minimum-stability": "stable",
18+
"require": {
19+
"php": ">=7.0.0",
20+
"ext-openssl": "*",
21+
"lcobucci/jwt": "^3.2",
22+
"illuminate/support": ">=5.4.0"
23+
}
24+
}

config/jwt.php

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
3+
/*
4+
|--------------------------------------------------------------------------
5+
| GENERAL WARNING. DO NOT USE THIS PACKAGE WITHOUT READING THIS.
6+
|--------------------------------------------------------------------------
7+
|
8+
| It's 2017. JWT are a (not so much) new and simple way of authenticating your
9+
| users either you're building a SPA + API or Mobile + API app.
10+
|
11+
| It's great you took interest in this package, but you should take real care
12+
| about the following things:
13+
|
14+
| As I was saying. It's 2017. JWT SHOULD NOT BE USED on a API WITHOUT HTTPS.
15+
| By HTTP, I mean TLS 1.1+.
16+
| SSL 3.0 and lower are proven insecure actually a couple of years ago.
17+
|
18+
| With that in mind, enjoy this. It was made with love with minimalism in mind.
19+
*/
20+
21+
return [
22+
23+
/*
24+
|--------------------------------------------------------------------------
25+
| JWT Secret
26+
|--------------------------------------------------------------------------
27+
|
28+
| This package uses HMAC-SHA265 as default signature mechanism.
29+
| HMAC-256 is pretty secure and straightforward when using a 32 bytes long key.
30+
| Since this package aims to be really simple, the crypt algorithm and key length
31+
| will be hardcoded instead of configurable.
32+
|
33+
| This will be like this by design, it will provide strong security for any API
34+
| while preventing people from making a mess and turning JWT less secure.
35+
|
36+
| NOTICE: ONLY USE KEYS GENERATED BY THE COMMAND
37+
|
38+
| php artisan jwt:generate
39+
|
40+
| If you don't, don't blame me latter.
41+
|
42+
| P.S. Don't blame me in any case :).
43+
*/
44+
45+
'secret' => env('JWT_SECRET', null),
46+
47+
/*
48+
|--------------------------------------------------------------------------
49+
| JWT Time to live (TTL)
50+
|--------------------------------------------------------------------------
51+
|
52+
| Use an Integer value in minutes.
53+
|
54+
| This will set how long will take for a key to be considered expired.
55+
| In other words, this is the amount of time, in minutes, that will be
56+
| added to the current time that the token is being issue and set
57+
| ont the 'exp' claim.
58+
|
59+
*/
60+
'ttl' => 60,
61+
62+
/*
63+
|--------------------------------------------------------------------------
64+
| Expired Token Refresh Limit
65+
|--------------------------------------------------------------------------
66+
|
67+
| Use an Integer value in minutes.
68+
|
69+
| This will set how long after the expiration date a token can be refreshed.
70+
| You can set it to 0 if you DO NOT want expired tokens to refreshed.
71+
|
72+
| The default limit of 7200 (minutes) takes in account mobile apps where the
73+
| logged used may take a few days before using your "app" again.
74+
|
75+
| In those cases, the token would have been expired but a new one could still
76+
| be issued, unless the limit configured here has already passed.
77+
|
78+
| If you're considering a not secure client platform, short values here reduces
79+
| the odds of a leaked token be used to generate a new one.
80+
|
81+
*/
82+
83+
'refresh_limit' => 7200
84+
85+
/*
86+
| That's it. there's nothing more to configure.
87+
|
88+
| Things like cache for blacklist and user model provider will be read from
89+
| your default configurations.
90+
|
91+
| Blacklisted tokens will be stored within your cache driver for the following time:
92+
|
93+
| ttl + refresh_limit.
94+
|
95+
| After this time has been passed, the token cannot be refresh anyway so it will automatically
96+
| be purged from your cache.
97+
|
98+
*/
99+
100+
];

src/Auth/Guard.php

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
<?php
2+
3+
namespace Kino\Auth\JWT\Auth;
4+
5+
use Illuminate\Auth\GuardHelpers;
6+
use Illuminate\Contracts\Auth\Authenticatable;
7+
use Illuminate\Http\Request;
8+
use Illuminate\Support\Str;
9+
use Kino\Auth\JWT\Contracts\Auth\Guard as GuardContract;
10+
11+
/**
12+
* JWT Guard class.
13+
*
14+
* This class is responsible for actually authenticating requests that
15+
* comes with a token (or denying those without a token or with a
16+
* invalid one).
17+
*/
18+
class Guard implements GuardContract
19+
{
20+
// this trait bootstrap some common guard methods
21+
// so we just need to implement a few ones.
22+
use GuardHelpers;
23+
24+
/**
25+
* @var \Illuminate\Contracts\Foundation\Application
26+
*/
27+
protected $app;
28+
29+
/**
30+
* Guard / Provider name.
31+
*
32+
* @var string
33+
*/
34+
protected $name;
35+
36+
/**
37+
* The currently authenticated user.
38+
*
39+
* @var \Illuminate\Contracts\Auth\Authenticatable
40+
*/
41+
protected $user;
42+
43+
/**
44+
* The user provider implementation.
45+
*
46+
* @var \Illuminate\Contracts\Auth\UserProvider
47+
*/
48+
protected $provider;
49+
50+
51+
/**
52+
* The token manager implementation.
53+
*
54+
* @var \Kino\Auth\JWT\Contracts\Token\Manager
55+
*/
56+
protected $manager;
57+
58+
/**
59+
* Used to allow checks just after logout.
60+
*
61+
* In a JWT scenario, logged out means there was an explicit action
62+
* to log out the user and the token has been blacklisted.
63+
*
64+
* @var bool
65+
*/
66+
protected $loggedOut = false;
67+
68+
/**
69+
* JWT Guard constructor.
70+
*
71+
* @param \Illuminate\Contracts\Foundation\Application $app
72+
* @param string $name
73+
* @param \Illuminate\Contracts\Auth\UserProvider $provider
74+
* @param \Kino\Auth\JWT\Contracts\Token\Manager $manager
75+
*/
76+
public function __construct($app, $name, $provider, $manager)
77+
{
78+
// assign constructor arguments into instance scope.
79+
$this->app = $app;
80+
$this->name = $name;
81+
$this->provider = $provider;
82+
$this->manager = $manager;
83+
}
84+
85+
public function validate(array $credentials = [])
86+
{
87+
// TODO: Implement validate() method.
88+
}
89+
90+
/**
91+
* Attempt to authenticate a user using the given credentials.
92+
*
93+
* @param array $credentials
94+
* @param bool $remember
95+
* @return bool
96+
*/
97+
public function attempt(array $credentials = [], $remember = false)
98+
{
99+
// $this->fireAttemptEvent($credentials, $remember);
100+
//
101+
// $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);
102+
//
103+
// // If an implementation of UserInterface was returned, we'll ask the provider
104+
// // to validate the user against the given credentials, and if they are in
105+
// // fact valid we'll log the users into the application and return true.
106+
// if ($this->hasValidCredentials($user, $credentials)) {
107+
// $this->login($user, $remember);
108+
//
109+
// return true;
110+
// }
111+
//
112+
// // If the authentication attempt fails we will fire an event so that the user
113+
// // may be notified of any suspicious attempts to access their account from
114+
// // an unrecognized user. A developer may listen to this event as needed.
115+
// $this->fireFailedEvent($user, $credentials);
116+
//
117+
// return false;
118+
}
119+
120+
/**
121+
* Login a given user. It means, generate a new token for a user.
122+
*
123+
* @param Authenticatable $user
124+
* @param array $customClaims
125+
* @return mixed
126+
*/
127+
public function login(Authenticatable $user, array $customClaims = [])
128+
{
129+
// try to generate a new token for the user.
130+
$token = $this->manager->issue($user, $customClaims);
131+
132+
if ($token) {
133+
// set current user as authenticated.
134+
$this->setUser($user);
135+
// returns the recently generated token.
136+
return $token;
137+
}
138+
139+
// no token could be generated.
140+
}
141+
142+
public function user()
143+
{
144+
// if the user was explicitly marked as logged out.
145+
if ($this->loggedOut) {
146+
// just return null.
147+
return null;
148+
}
149+
150+
/** @var Request $request */
151+
$request = $this->app->request;
152+
153+
// if there is no Authorization header on the request.
154+
if (!$request->headers->has('Authorization')) {
155+
// also return null since no user can be determined.
156+
return null;
157+
}
158+
159+
// gets the authorization header from the request.
160+
$header = $request->headers->get('Authorization');
161+
162+
// gets the token part of the authorization header, as string.
163+
$tokenString = Str::replaceFirst('Bearer ', '', $header);
164+
165+
// parse the string token into a Token object
166+
$token = $this->manager->parseToken($tokenString);
167+
168+
// if the received token is not actually valid.
169+
if (!$this->manager->validToken($token)) {
170+
// also return null since the token
171+
// signature could not be determined.
172+
return null;
173+
}
174+
175+
// if the token has expired.
176+
if ($this->manager->expired($token)) {
177+
// you got right?
178+
return null;
179+
}
180+
181+
// retrieves the user ID from the token.
182+
$id = $token->getClaim('sub');
183+
184+
// use the users provider to find the token subject (user)
185+
// but it's id (subject)
186+
$user = $this->provider->retrieveById($id);
187+
188+
// if the user has not been found.
189+
if (!$user) {
190+
// abort!
191+
return null;
192+
}
193+
194+
// set the current user on the scope.
195+
$this->setUser($user);
196+
197+
// return the scope user.
198+
return $this->user;
199+
}
200+
201+
/**
202+
* Log the user out of the application.
203+
*
204+
* @return void
205+
*/
206+
public function logout()
207+
{
208+
$user = $this->user();
209+
210+
// blacklist the user token.
211+
212+
$this->loggedOut = true;
213+
}
214+
}

0 commit comments

Comments
 (0)