Skip to content

Commit 4f7d155

Browse files
authored
Merge pull request #184 from codeigniter4/throttle-filter
Provide a rate limiting filter.
2 parents 5259a70 + 94b4ee3 commit 4f7d155

File tree

7 files changed

+150
-71
lines changed

7 files changed

+150
-71
lines changed

docs/0 - install.md

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1-
# Installation
1+
# Installation
22

3-
Installation is done through [Composer](https://getcomposer.org). The example assumes you have it installed globally.
3+
Installation is done through [Composer](https://getcomposer.org). The example assumes you have it installed globally.
44
If you have it installed as a phar, or othewise you will need to adjust the way you call composer itself.
55

66
```
77
> composer require codeigniter4/shield
88
```
99

1010
This requires the [CodeIgniter Settings](https://github.com/codeigniter4/settings) package, which uses a database
11-
table to store configuration options. As such, you should run the migrations.
11+
table to store configuration options. As such, you should run the migrations.
1212

1313
```
1414
> php spark migrate --all
1515
```
1616

1717
## Initial Setup
1818

19-
There are a few setup items to do before you can start using Shield in
20-
your project.
19+
There are a few setup items to do before you can start using Shield in
20+
your project.
2121

2222
1. Copy the `Auth.php` and `AuthGroups.php` from `vendor/codeigniter4/shield/src/Config/` into your project's config folder and update the namespace to `Config`. You will also need to have these classes extend the original classes. See the example below. These files contain all of the settings, group, and permission information for your application and will need to be modified to meet the needs of your site.
2323

@@ -38,7 +38,7 @@ class Auth extends ShieldAuth
3838
}
3939
```
4040

41-
2. **Helper Setup** The `auth` and `setting` helpers need to be included in almost every page. The simplest way to do this is to add them to the `BaseController::initController` method:
41+
2. **Helper Setup** The `auth` and `setting` helpers need to be included in almost every page. The simplest way to do this is to add them to the `BaseController::initController` method:
4242

4343
```php
4444
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
@@ -52,14 +52,14 @@ public function initController(RequestInterface $request, ResponseInterface $res
5252

5353
This requires that all of your controllers extend the `BaseController`, but that's a good practice anyway.
5454

55-
3. **Routes Setup** The default auth routes can be setup with a single call in `app/Config/Routes.php`:
55+
3. **Routes Setup** The default auth routes can be setup with a single call in `app/Config/Routes.php`:
5656

5757
```php
5858
service('auth')->routes($routes);
5959
```
6060

6161
4. (If you are running CodeIgniter v4.2.0 or higher you can skip this step). Add the new password validation rules
62-
by editing `app/Config/Validation.php`:
62+
by editing `app/Config/Validation.php`:
6363

6464
```php
6565
use CodeIgniter\Shield\Authentication\Passwords\ValidationRules as PasswordRules;
@@ -73,6 +73,44 @@ public $ruleSets = [
7373
];
7474
```
7575
76+
## Controller Filters
77+
78+
Shield provides 3 [Controller Filters](https://codeigniter.com/user_guide/incoming/filters.html) you can
79+
use to protect your routes, `session`, `tokens`, and `chained`. The first two cover the `Session` and
80+
`AccessTokens` authenticators, respectively. The `chained` filter will check both authenticators in sequence
81+
to see if the user is logged in through either of authenticators, allowing a single API endpoint to
82+
work for both an SPA using session auth, and a mobile app using access tokens.
83+
84+
These filters are already loaded for you by the registrar class located at `src/Config/Registrar.php`.
85+
86+
```php
87+
public $aliases = [
88+
// ...
89+
'session' => \CodeIgniter\Shield\Filters\SessionAuth::class,
90+
'tokens' => \CodeIgniter\Shield\Filters\TokenAuth::class,
91+
'chain' => \CodeIgniter\Shield\Filters\ChainAuth::class,
92+
'auth-rates' => \CodeIgniter\Shield\Filters\AuthRates::class,
93+
];
94+
```
95+
96+
These can be used in any of the normal filter config settings, or within the routes file.
97+
98+
### Rate Limiting
99+
100+
To help protect your authentication forms from being spammed by bots, it is recommended that you use
101+
the `auth-rates` filter on all of your authentication routes. This can be done with the following
102+
filter setup:
103+
104+
```php
105+
public $filters = [
106+
'auth-rates' => [
107+
'before' => [
108+
'login*', 'register', 'auth/*'
109+
]
110+
]
111+
];
112+
```
113+
76114
## Further Customization
77115
78116
### Route Configuration
@@ -92,10 +130,10 @@ $routes->get('register', '\App\Controllers\Auth\RegisterController::registerView
92130
93131
### Extending the Controllers
94132
95-
Shield has the following controllers that can be extended to handle
96-
various parts of the authentication process:
133+
Shield has the following controllers that can be extended to handle
134+
various parts of the authentication process:
97135
98-
- **ActionController** handles the after login and after-registration actions that can be ran, like Two Factor Authentication and Email Verification.
136+
- **ActionController** handles the after login and after-registration actions that can be ran, like Two Factor Authentication and Email Verification.
99137
100138
- **LoginController** handles the login process.
101139
@@ -105,7 +143,7 @@ various parts of the authentication process:
105143
override the message that is displayed to a user to describe what is happening, if you'd like to provide more information than simply swapping out the view used.
106144
107145
It is not recommended to copy the entire controller into app and change it's namespace. Instead, you should create a new controller that extends
108-
the existing controller and then only override the methods needed. This allows the other methods to always stay up to date with any security
146+
the existing controller and then only override the methods needed. This allows the other methods to always stay up to date with any security
109147
updates that might happen in the controllers.
110148
111149
```php
@@ -119,7 +157,7 @@ class LoginController extends ShieldLogin
119157
{
120158
public function logoutAction()
121159
{
122-
// new functionality
160+
// new functionality
123161
}
124162
}
125163
```

docs/2 - authentication.md

Lines changed: 35 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Authentication
22

3-
Shield provides a flexible, secure, authentication system for your web apps and API's.
3+
Shield provides a flexible, secure, authentication system for your web apps and API's.
44

55
## Available Authenticators
66

@@ -26,7 +26,7 @@ public $defaultAuthenticator = 'session';
2626

2727
## Auth Helper
2828

29-
The auth functionality is designed to be used with the `auth_helper` that comes with Shield. This
29+
The auth functionality is designed to be used with the `auth_helper` that comes with Shield. This
3030
helper method provides the `auth()` command which returns a convenient interface to the most frequently
3131
used functionality within the auth libraries. This must be loaded before it can be used.
3232

@@ -37,7 +37,7 @@ helper('auth');
3737
auth()->user();
3838

3939
// get the current user's id
40-
user_id()
40+
user_id()
4141
// or
4242
auth()->id()
4343
```
@@ -50,13 +50,13 @@ has the following methods:
5050

5151
### isOK()
5252

53-
Returns a boolean value stating whether the check was successful or not.
53+
Returns a boolean value stating whether the check was successful or not.
5454

5555
### reason()
5656

5757
Returns a message that can be displayed to the user when the check fails.
5858

59-
### extraInfo()
59+
### extraInfo()
6060

6161
Can return a custom bit of information. These will be detailed in the method descriptions below.
6262

@@ -65,7 +65,7 @@ Can return a custom bit of information. These will be detailed in the method des
6565

6666
The Session authenticator stores the user's authentication within the user's session, and on a secure cookie
6767
on their device. This is the standard password-based login used in most web sites. It supports a
68-
secure remember me feature, and more. This can also be used to handle authentication for
68+
secure remember me feature, and more. This can also be used to handle authentication for
6969
single page applications (SPAs).
7070

7171
### attempt()
@@ -75,11 +75,11 @@ on the auth class, passing in their credentials.
7575

7676
```php
7777
$credentials = [
78-
'email' => $this->request->getPost('email'),
78+
'email' => $this->request->getPost('email'),
7979
'password' => $this->request->getPost('password')
8080
];
8181

82-
$loginAttempt = auth()->attempt($credentials);
82+
$loginAttempt = auth()->attempt($credentials);
8383

8484
if (! $loginAttempt->isOK()) {
8585
return redirect()->back()->with('error', $loginAttempt->reason());
@@ -97,11 +97,11 @@ if($result->isOK()) {
9797
}
9898
```
9999

100-
If the attempt fails a `failedLogin` event is triggered with the credentials array as
100+
If the attempt fails a `failedLogin` event is triggered with the credentials array as
101101
the only parameter. Whether or not they pass, a login attempt is recorded in the `auth_logins` table.
102102

103103
If `allowRemembering` is `true` in the `Auth` config file, you can tell the Session authenticator
104-
to set a secure remember-me cookie.
104+
to set a secure remember-me cookie.
105105

106106
```php
107107
$loginAttempt = auth()->remember()->attempt($credentials);
@@ -114,11 +114,11 @@ method.
114114

115115
```php
116116
$credentials = [
117-
'email' => $this->request->getPost('email'),
117+
'email' => $this->request->getPost('email'),
118118
'password' => $this->request->getPost('password')
119119
];
120120

121-
$validCreds? = auth()->check($credentials);
121+
$validCreds? = auth()->check($credentials);
122122

123123
if (! $validCreds->isOK()) {
124124
return redirect()->back()->with('error', $loginAttempt->reason());
@@ -140,7 +140,7 @@ if (auth()->loggedIn()) {
140140
### logout()
141141

142142
You can call the `logout()` method to log the user out of the current session. This will destroy and
143-
regenerate the current session, purge any remember-me tokens current for this user, and trigger a
143+
regenerate the current session, purge any remember-me tokens current for this user, and trigger a
144144
`logout` event.
145145

146146
```php
@@ -149,52 +149,52 @@ auth()->logout();
149149

150150
### forget()
151151

152-
The `forget` method will purge all remember-me tokens for the current user, making it so they
152+
The `forget` method will purge all remember-me tokens for the current user, making it so they
153153
will not be remembered on the next visit to the site.
154154

155155
## Access Token Authenticator
156156

157157
The Access Token authenticator supports the use of revoke-able API tokens without using OAuth. These are commonly
158-
used to provide third-party developers access to your API. These tokens typically have a very long
159-
expiration time, often years.
158+
used to provide third-party developers access to your API. These tokens typically have a very long
159+
expiration time, often years.
160160

161161
These are also suitable for use with mobile applications. In this case, the user would register/sign-in
162162
with their email/password. The application would create a new access token for them, with a recognizable
163163
name, like John's iPhone 12, and return it to the mobile application, where it is stored and used
164164
in all future requests.
165165

166-
### Access Token/API Authentication
166+
### Access Token/API Authentication
167167

168-
Using access tokens requires that you either use/extend `CodeIgniter\Shield\Models\UserModel` or
168+
Using access tokens requires that you either use/extend `CodeIgniter\Shield\Models\UserModel` or
169169
use the `CodeIgniter\Shield\Authentication\Traits\HasAccessTokens` on your own user model. This trait
170170
provides all of the custom methods needed to implement access tokens in your application. The necessary
171-
database table, `auth_access_tokens`, is created in Shield's only migration class, which must be ran
171+
database table, `auth_access_tokens`, is created in Shield's only migration class, which must be ran
172172
before first using any of the features of Shield.
173173

174174
### Generating Access Tokens
175175

176-
Access tokens are created through the `generateAccessToken()` method on the user. This takes a name to
177-
give to the token as the first argument. The name is used to display it to the user so they can
178-
differentiate between multiple tokens.
176+
Access tokens are created through the `generateAccessToken()` method on the user. This takes a name to
177+
give to the token as the first argument. The name is used to display it to the user so they can
178+
differentiate between multiple tokens.
179179

180180
```php
181181
$token = $user->generateAccessToken('Work Laptop');
182-
```
182+
```
183183

184184
This creates the token using a cryptographically secure random string. The token
185-
is hashed (sha256) before saving it to the database. The method returns an instance of
185+
is hashed (sha256) before saving it to the database. The method returns an instance of
186186
`CodeIgniters\Shield\Authentication\Entities\AccessToken`. The only time a plain text
187187
version of the token is available is in the `AccessToken` returned immediately after creation.
188-
**The plain text version should be displayed to the user immediately so they can copy it for
189-
their use.** If a user loses it, they cannot see the raw version anymore, but they can generate
188+
**The plain text version should be displayed to the user immediately so they can copy it for
189+
their use.** If a user loses it, they cannot see the raw version anymore, but they can generate
190190
a new token to use.
191191

192192
```php
193193
$token = $user->generateAccessToken('Work Laptop');
194194

195195
// Only available immediately after creation.
196196
echo $token->raw_token;
197-
```
197+
```
198198

199199
### Revoking Access Tokens
200200

@@ -205,9 +205,9 @@ access token as the only argument. Revoking simply deletes the record from the d
205205
$user->revokeAccessToken($token);
206206
```
207207

208-
Typically, the plain text token is retrieved from the request's headers as part of the authentication
208+
Typically, the plain text token is retrieved from the request's headers as part of the authentication
209209
process. If you need to revoke the token for another user as an admin, and don't have access to the
210-
token, you would need to get the user's access tokens and delete them manually.
210+
token, you would need to get the user's access tokens and delete them manually.
211211

212212
You can revoke all access tokens with the `revokeAllAccessTokens()` method.
213213

@@ -217,7 +217,7 @@ $user->revokeAllAccessTokens($token);
217217

218218
### Retrieving Access Tokens
219219

220-
The following methods are available to help you retrieve a user's access tokens:
220+
The following methods are available to help you retrieve a user's access tokens:
221221

222222
```php
223223
// Retrieve a single token by plain text token
@@ -232,9 +232,9 @@ $tokens = $user->accessTokens();
232232

233233
### Access Token Lifetime
234234

235-
Tokens will expire after a specified amount of time has passed since they have been used.
235+
Tokens will expire after a specified amount of time has passed since they have been used.
236236
By default, this is set to 1 year. You can change this value by setting the `accessTokenLifetime`
237-
value in the `Auth` config file. This is in seconds so that you can use the
237+
value in the `Auth` config file. This is in seconds so that you can use the
238238
[time constants](https://codeigniter.com/user_guide/general/common_functions.html#time-constants)
239239
CodeIgniter provides.
240240

@@ -244,7 +244,7 @@ public $unusedTokenLifetime = YEAR;
244244

245245
### Access Token Scopes
246246

247-
Each token can be given one or more scopes they can be used within. These can be thought of as
247+
Each token can be given one or more scopes they can be used within. These can be thought of as
248248
permissions the token grants to the user. Scopes are provided when the token is generated and
249249
cannot be modified afterword.
250250

@@ -257,9 +257,9 @@ same as:
257257

258258
```php
259259
$token = $user->gererateAccessToken('Work Laptop', ['*']);
260-
```
260+
```
261261

262-
During authentication, the token the user used is stored on the user. Once authenticated, you
262+
During authentication, the token the user used is stored on the user. Once authenticated, you
263263
can use the `tokenCan()` and `tokenCant()` methods on the user to determine if they have access
264264
to the specified scope.
265265

@@ -272,23 +272,3 @@ if ($user->tokenCant('forums.manage')) {
272272
// do something....
273273
}
274274
```
275-
276-
## Controller Filters
277-
278-
Shield provides 3 [Controller Filters](https://codeigniter.com/user_guide/incoming/filters.html) you can
279-
use to protect your routes, `session`, `tokens`, and `chained`. The first two cover the `Session` and `AccessTokens` authenticators, respectively. The `chained` filter will check both authenticators in sequence
280-
to see if the user is logged in through either of authenticators, allowing a single API endpoint to
281-
work for both an SPA using session auth, and a mobile app using access tokens.
282-
283-
These filters are already loaded for you by the registrar class located at `src/Config/Registrar.php`.
284-
285-
```php
286-
public $aliases = [
287-
// ...
288-
'session' => \CodeIgniter\Shield\Filters\SessionAuth::class,
289-
'tokens' => \CodeIgniter\Shield\Filters\TokenAuth::class,
290-
'chain' => \CodeIgniter\Shield\Filters\ChainAuth::class,
291-
];
292-
```
293-
294-
These can be used in any of the normal filter config settings, or within the routes file.

0 commit comments

Comments
 (0)