|
1 | | -<h1 align="center">JWT Auth</h1> |
| 1 | +# JWT-Auth |
2 | 2 |
|
3 | | -<p align="center">A simple framework-agnostic JSON Web Token authentication solution.</p> |
| 3 | +A simple framework-agnostic JSON Web Token authentication solution. |
4 | 4 |
|
5 | | -<p align="center"> |
6 | | - <a href="https://packagist.org/packages/andrewdyer/jwt-auth"><img src="https://poser.pugx.org/andrewdyer/jwt-auth/downloads?style=for-the-badge" alt="Total Downloads"></a> |
7 | | - <a href="https://packagist.org/packages/andrewdyer/jwt-auth"><img src="https://poser.pugx.org/andrewdyer/jwt-auth/v?style=for-the-badge" alt="Latest Stable Version"></a> |
8 | | - <a href="https://packagist.org/packages/andrewdyer/jwt-auth"><img src="https://poser.pugx.org/andrewdyer/jwt-auth/license?style=for-the-badge" alt="License"></a> |
9 | | -</p> |
10 | | - |
11 | | -## License |
12 | | -Licensed under MIT. Totally free for private or commercial projects. |
| 5 | +[](https://packagist.org/packages/andrewdyer/jwt-auth) [](https://packagist.org/packages/andrewdyer/jwt-auth) [](https://packagist.org/packages/andrewdyer/jwt-auth) [](https://packagist.org/packages/andrewdyer/jwt-auth) [](https://packagist.org/packages/andrewdyer/jwt-auth) |
13 | 6 |
|
14 | 7 | ## Installation |
15 | | -```text |
| 8 | + |
| 9 | +```bash |
16 | 10 | composer require andrewdyer/jwt-auth |
17 | 11 | ``` |
18 | 12 |
|
19 | | -## Usage |
| 13 | +## Getting Started |
| 14 | + |
| 15 | +### Define the JWT Subject |
| 16 | + |
| 17 | +Create a class (e.g., `User`) that implements the `JWTSubject` interface. This class must provide a method `getJWTIdentifier` to return the user’s unique identifier. |
| 18 | + |
20 | 19 | ```php |
21 | | -// Create a new auth provider instance |
22 | | -$authProvider = new App\Providers\AuthProvider(); |
23 | | - |
24 | | -// Create a new jwt provider instance |
25 | | -$jwtProvider = new App\Providers\JwtProvider(); |
26 | | - |
27 | | -// Build up jwt claims |
28 | | -$claimsFactory = new Anddye\JwtAuth\ClaimsFactory::build([ |
29 | | - 'exp' => 1582243200, // Friday, 21 February 2020 00:00:00 |
30 | | - 'iat' => 1582193571, // Thursday, 20 February 2020 10:12:51 |
31 | | - 'iss' => 'https://example.com', |
32 | | - 'jti' => 'fVcx9BJHqh', |
33 | | - 'nbj' => '1582193571', // Thursday, 20 February 2020 10:12:51 |
34 | | -]); |
| 20 | +namespace App\Models; |
35 | 21 |
|
36 | | -// Bring everything together to create a jwt auth instance |
37 | | -$jwtAuth = new JwtAuth($authProvider, $jwtProvider, $claimsFactory); |
| 22 | +use Anddye\JWTAuth\Interfaces\JWTSubject; |
| 23 | + |
| 24 | +class User implements JWTSubject |
| 25 | +{ |
| 26 | + public function getJWTIdentifier(): int |
| 27 | + { |
| 28 | + return 1; |
| 29 | + } |
| 30 | +} |
38 | 31 | ``` |
39 | 32 |
|
40 | | -### Auth Provider |
| 33 | +> **Note:** This example is simplified for demonstration purposes. In a real-world application, you would typically use a proper user model, such as one provided by your framework. Ensure the `getJWTIdentifier` method returns a unique user identifier appropriate for your system. |
| 34 | +
|
| 35 | +### Create an Authentication Provider |
| 36 | + |
| 37 | +Create an authentication provider class that implements `AuthProviderInterface`. This class will handle credential validation and user retrieval by ID. |
| 38 | + |
41 | 39 | ```php |
42 | 40 | namespace App\Providers; |
43 | 41 |
|
44 | | -use Anddye\JwtAuth\Providers\AuthProviderInterface; |
| 42 | +use Anddye\JWTAuth\Interfaces\AuthProviderInterface; |
| 43 | +use App\Models\User; |
45 | 44 |
|
46 | 45 | class AuthProvider implements AuthProviderInterface |
47 | 46 | { |
48 | 47 | public function byCredentials(string $username, string $password) |
49 | 48 | { |
50 | | - // TODO: Validate username / password and return an instance of `Anddye\JwtAuth\Contracts\JwtSubject` |
| 49 | + if ($username === 'admin' && $password === 'secret') { |
| 50 | + return new User(); |
| 51 | + } |
| 52 | + |
| 53 | + return null; |
51 | 54 | } |
52 | 55 |
|
53 | 56 | public function byId(int $id) |
54 | 57 | { |
55 | | - // TODO: Find a user by id and return an instance of `Anddye\JwtAuth\Contracts\JwtSubject` if exists |
| 58 | + if ($id === 1) { |
| 59 | + return new User(); |
| 60 | + } |
| 61 | + |
| 62 | + return null; |
56 | 63 | } |
57 | 64 | } |
58 | 65 | ``` |
59 | 66 |
|
60 | | -### JWT Provider |
| 67 | +> **Note:** This example uses hardcoded credentials for demonstration purposes. In a real-world application, you should validate credentials securely by checking against a database and using hashed passwords (e.g., via libraries like `bcrypt` or `password_hash`). Ensure you follow best practices for secure authentication. |
| 68 | +
|
| 69 | +### Create a JWT Provider |
| 70 | + |
| 71 | +Create a JWT provider class that implements `JWTProviderInterface`. This class should handle encoding and decoding JWT tokens. |
| 72 | + |
61 | 73 | ```php |
62 | | -namespace Anddye\JwtAuth\Tests\Stubs\Providers; |
| 74 | +namespace App\Providers; |
63 | 75 |
|
64 | | -use Anddye\JwtAuth\Providers\JwtProviderInterface; |
| 76 | +use Anddye\JWTAuth\Interfaces\JWTProviderInterface; |
65 | 77 |
|
66 | | -class JwtProvider implements JwtProviderInterface |
| 78 | +class JWTProvider implements JWTProviderInterface |
67 | 79 | { |
68 | 80 | public function decode(string $token) |
69 | 81 | { |
70 | | - // TODO: Decode JWT token somehow |
| 82 | + return json_decode(base64_decode($token), true); |
71 | 83 | } |
72 | 84 |
|
73 | 85 | public function encode(array $claims): string |
74 | 86 | { |
75 | | - // TODO: Encode claims and create a JWT token somehow |
| 87 | + return base64_encode(json_encode($claims)); |
76 | 88 | } |
77 | 89 | } |
78 | 90 | ``` |
79 | 91 |
|
80 | | -### Claims Factory |
81 | | -| Option | Type | Description | |
82 | | -| --- | --- | --- | |
83 | | -| exp | int | Time after which the JWT expires. | |
84 | | -| iat | int | Time at which the JWT was issued. | |
85 | | -| iss | string | Issuer of the JWT. | |
86 | | -| jti | string | Unique identifier; can be used to prevent the JWT from being replayed. | |
87 | | -| nbj | int | Time before which the JWT must not be accepted for processing. | |
| 92 | +> **Note:** This examples used `base64_encode` and `base64_decode` for simplicity. For real-world usage, consider using a proper JWT library such as [firebase/php-jwt](https://github.com/firebase/php-jwt) for better security. |
| 93 | +
|
| 94 | +### Generate JWT Claims |
| 95 | + |
| 96 | +The `ClaimsFactory` class helps create a JWT claims instance. The `build` method accepts an array of claims and returns an instance of `ClaimsInterface`. |
88 | 97 |
|
89 | 98 | ```php |
90 | | -$claimsFactory = new Anddye\JwtAuth\ClaimsFactory(); |
91 | | -$claimsFactory->setExp(1582243200); // Friday, 21 February 2020 00:00:00 |
92 | | -$claimsFactory->setIat(1582193571); // Thursday, 20 February 2020 10:12:51 |
93 | | -$claimsFactory->setIss('https://example.com'); |
94 | | -$claimsFactory->setJti('fVcx9BJHqh'); |
95 | | -$claimsFactory->setNbj(1582193571); // Thursday, 20 February 2020 10:12:51 |
| 99 | +use Anddye\JWTAuth\Factory\ClaimsFactory; |
| 100 | + |
| 101 | +$claims = ClaimsFactory::build([ |
| 102 | + 'iss' => 'https://example.com', // Issuer of the JWT |
| 103 | + 'aud' => 'https://example.com', // Audience of the JWT |
| 104 | + 'exp' => 1582243200, // Expiration time (Unix timestamp) |
| 105 | + 'nbf' => 1582193571, // Not before time (Unix timestamp) |
| 106 | + 'iat' => 1582193571, // Issued at time (Unix timestamp) |
| 107 | + 'jti' => 'fVcx9BJHqh', // Unique identifier |
| 108 | +]); |
96 | 109 | ``` |
97 | 110 |
|
98 | | -### Attempt with credentials |
| 111 | +> **Note:** This example uses hardcoded Unix timestamps for demonstration purposes. Consider using libraries like [nesbot/carbon](https://github.com/briannesbitt/carbon) or PHP's native `DateTime` class to generate timestamps dynamically. This helps improve readability and ensures accurate date handling. |
| 112 | +
|
| 113 | +### Initialize the JWT Authenticator |
| 114 | + |
| 115 | +Create a new instance of the `JWTAuth` class. This requires an instance of `AuthProviderInterface`, `JWTProviderInterface`, and `ClaimsInterface`. |
| 116 | + |
99 | 117 | ```php |
100 | | -if (!$token = $jwtAuth->attempt($username, $password)) { |
101 | | - // TODO: Handle failed attempt with credentials |
| 118 | +use App\Providers\AuthProvider; |
| 119 | +use App\Providers\JWTProvider; |
| 120 | +use Anddye\JWTAuth\JWTAuth; |
| 121 | + |
| 122 | +$authProvider = new AuthProvider(); |
| 123 | + |
| 124 | +$jwtProvider = new JWTProvider(); |
| 125 | + |
| 126 | +$jwtAuth = new JWTAuth($authProvider, $jwtProvider, $claims); |
| 127 | +``` |
| 128 | + |
| 129 | +## Usage |
| 130 | + |
| 131 | +### Attempt Authentication |
| 132 | + |
| 133 | +Authenticate a user by providing their credentials. If successful, a JWT token will be returned. |
| 134 | + |
| 135 | +```php |
| 136 | +$token = $jwtAuth->attempt('admin', 'secret'); |
| 137 | + |
| 138 | +if ($token) { |
| 139 | + echo "Token: " . $token; |
102 | 140 | } else { |
103 | | - // TODO: Handle successful attempt with credentials |
| 141 | + echo "Invalid credentials"; |
104 | 142 | } |
105 | 143 | ``` |
106 | 144 |
|
107 | | -### Authenticate with token |
| 145 | +### Authenticate a Token |
| 146 | + |
| 147 | +Validate a JWT token and retrieve the associated user (subject). |
| 148 | + |
108 | 149 | ```php |
109 | | -if (!$actor = $jwtAuth->authenticate($token)->getActor()) { |
110 | | - // TODO: Handle failed authentication with token |
| 150 | +$subject = $jwtAuth->authenticate('your-jwt-token-here'); |
| 151 | + |
| 152 | +if ($subject) { |
| 153 | + echo "User authenticated!"; |
111 | 154 | } else { |
112 | | - // TODO: Handle successful authentication with token |
| 155 | + echo "Invalid token"; |
113 | 156 | } |
114 | 157 | ``` |
115 | 158 |
|
116 | | -## Support |
117 | | -If you're using this package, I'd love to hear your thoughts! Feel free to contact me on [Twitter](https://twitter.com/andyer92). |
118 | | - |
119 | | -Need to see an example? Check out [this tutorial](https://github.com/andrewdyer/jwt-auth/wiki/Slim-3-Example) on how to integrate this library into a [Slim 3](http://www.slimframework.com/docs/v3/) project. |
| 159 | +## License |
120 | 160 |
|
121 | | -Found a bug? Please report it using the [issue tracker](https://github.com/andrewdyer/jwt-auth/issues), or better yet, fork the repository and submit a pull request. |
| 161 | +Licensed under MIT. Totally free for private or commercial projects. |
0 commit comments