Skip to content

Commit 14fd233

Browse files
Add docs from gofiber/fiber@4bf3695
1 parent ae19453 commit 14fd233

File tree

1 file changed

+84
-40
lines changed

1 file changed

+84
-40
lines changed

docs/core/api/middleware/csrf.md

Lines changed: 84 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,51 @@ id: csrf
44

55
# CSRF
66

7-
CSRF middleware for [Fiber](https://github.com/gofiber/fiber) that provides [Cross-site request forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery) protection by passing a csrf token via cookies. This cookie value will be used to compare against the client csrf token on requests, other than those defined as "safe" by [RFC9110#section-9.2.1](https://datatracker.ietf.org/doc/html/rfc9110.html#section-9.2.1) \(GET, HEAD, OPTIONS, or TRACE\). When the csrf token is invalid, this middleware will return the `fiber.ErrForbidden` error.
7+
The CSRF middleware for [Fiber](https://github.com/gofiber/fiber) provides protection against [Cross-Site Request Forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery) (CSRF) attacks using tokens. These tokens verify requests made using methods other than those defined as "safe" by [RFC9110#section-9.2.1](https://datatracker.ietf.org/doc/html/rfc9110.html#section-9.2.1) (Safe-Methods: GET, HEAD, OPTIONS, and TRACE). If a potential attack is detected this middleware will, by default, return a 403 Forbidden error.
88

9-
CSRF Tokens are generated on GET requests. You can retrieve the CSRF token with `c.Locals(contextKey)`, where `contextKey` is the string you set in the config (see Custom Config below).
9+
This middleware can be used with or without a user session and offers two token validation patterns. In addition, it implements strict referer checking for HTTPS requests, ensuring the security of your application. For HTTPS requests, even if a subdomain can set or modify cookies on your domain, it can't force a user to post to your application since that request won't come from your own exact domain.
1010

11-
When no `csrf_` cookie is set, or the token has expired, a new token will be generated and `csrf_` cookie set.
11+
## Token Generation
1212

13-
:::note
14-
This middleware uses our [Storage](https://github.com/gofiber/storage) package to support various databases through a single interface. The default configuration for this middleware saves data to memory, see the examples below for other databases.
15-
:::
13+
CSRF tokens are generated on 'safe' requests and when the existing token has expired or hasn't been set yet. If `SingleUseToken` is `true`, a new token is generated after each use. Retrieve the CSRF token using `c.Locals(contextKey)`, where `contextKey` is defined in the configuration.
1614

1715
## Security Considerations
1816

19-
This middleware is designed to protect against CSRF attacks. It does not protect against other attack vectors, such as XSS, and should be used in combination with other security measures.
17+
This middleware is designed to protect against CSRF attacks but does not protect against other attack vectors, such as XSS. It should be used in combination with other security measures.
2018

21-
:::warning
22-
Never use 'safe' methods to mutate data. For example, never use a GET request to delete a resource. This middleware will not protect against CSRF attacks on 'safe' methods.
19+
:::danger
20+
Never use 'safe' methods to mutate data, for example, never use a GET request to modify a resource. This middleware will not protect against CSRF attacks on 'safe' methods.
2321
:::
2422

25-
### The Double Submit Cookie Pattern (Default)
23+
### Token Validation Patterns
24+
25+
#### Double Submit Cookie Pattern (Default)
26+
27+
In the default configuration, the middleware generates and stores tokens using the `fiber.Storage` interface. These tokens are not associated with a user session, and a Double Submit Cookie pattern is used to validate the token. The token is stored in a cookie and sent as a header on requests. The middleware compares the cookie value with the header value to validate the token. This is a secure pattern that does not require a user session.
2628

27-
In the default configuration, the middleware will generate and store tokens using the `fiber.Storage` interface. These tokens are not associated with a user session, and, therefore, a Double Submit Cookie pattern is used to validate the token. This means that the token is stored in a cookie and also sent as a header on requests. The middleware will compare the cookie value with the header value to validate the token. This is a secure method of validating the token, as cookies are not accessible to JavaScript and, therefore, cannot be read by an attacker.
29+
When using this pattern, it's important to delete the token when the authorization status changes, see: [Token Lifecycle](#token-lifecycle) for more information.
2830

29-
:::warning
30-
When using this method, it is important that you set the `CookieSameSite` option to `Lax` or `Strict` and that the Extractor is not `CsrfFromCookie`, and KeyLookup is not `cookie:<name>`.
31+
:::caution
32+
When using this method, it's important to set the `CookieSameSite` option to `Lax` or `Strict` and ensure that the Extractor is not `CsrfFromCookie`, and KeyLookup is not `cookie:<name>`.
3133
:::
3234

33-
### The Synchronizer Token Pattern (Session)
35+
:::note
36+
When using this pattern, this middleware uses our [Storage](https://github.com/gofiber/storage) package to support various databases through a single interface. The default configuration for Storage saves data to memory. See [Custom Storage/Database](#custom-storagedatabase) for customizing the storage.
37+
:::
38+
39+
#### Synchronizer Token Pattern (Session)
40+
41+
When using this middleware with a user session, the middleware can be configured to store the token in the session. This method is recommended when using a user session, as it is generally more secure than the Double Submit Cookie Pattern.
3442

35-
When using this middleware with a user session, the middleware can be configured to store the token in the session. This method is recommended when using a user session as it is generally more secure than the Double Submit Cookie Pattern.
43+
When using this pattern it's important to regenerate the session when the authorization status changes, this will also delete the token. See: [Token Lifecycle](#token-lifecycle) for more information.
3644

37-
:::warning
38-
When using this method, pre-sessions are required and will be created if a session is not already present. This means that the middleware will create a session for every safe request, even if the request does not require a session. Therefore it is required that the existence of a session is not used to indicate that a user is logged in or authenticated, and that a session value is used to indicate this instead.
45+
:::caution
46+
When using this method, pre-sessions are required and will be created if a session is not already present. This means the middleware will create a session for every safe request, even if the request does not require a session. Therefore, the existence of a session should not be used to indicate that a user is logged in or authenticated; a session value should be used for this purpose.
3947
:::
4048

4149
### Defense In Depth
4250

43-
When using this middleware, it is recommended that you serve your pages over HTTPS, that the `CookieSecure` option is set to `true`, and that the `CookieSameSite` option is set to `Lax` or `Strict`. This will ensure that the cookie is only sent over HTTPS and that it is not sent on requests from external sites.
51+
When using this middleware, it's recommended to serve your pages over HTTPS, set the `CookieSecure` option to `true`, and set the `CookieSameSite` option to `Lax` or `Strict`. This ensures that the cookie is only sent over HTTPS and not on requests from external sites.
4452

4553
:::note
4654
Cookie prefixes __Host- and __Secure- can be used to further secure the cookie. However, these prefixes are not supported by all browsers and there are some other limitations. See [MDN#Set-Cookie#cookie_prefixes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#cookie_prefixes) for more information.
@@ -50,43 +58,44 @@ To use these prefixes, set the `CookieName` option to `__Host-csrf_` or `__Secur
5058

5159
### Referer Checking
5260

53-
For HTTPS requests, this middleware performs strict referer checking. This means that even if a subdomain can set or modify cookies on your domain, it cant force a user to post to your application since that request wont come from your own exact domain.
61+
For HTTPS requests, this middleware performs strict referer checking. Even if a subdomain can set or modify cookies on your domain, it can't force a user to post to your application since that request won't come from your own exact domain.
5462

55-
:::warning
63+
:::caution
5664
Referer checking is required for https requests protected by CSRF. All modern browsers will automatically include the Referer header in requests, including those made with the JS Fetch API. However, if you are using this middleware with a custom client you must ensure that the client sends a valid Referer header.
5765
:::
5866

67+
5968
### Token Lifecycle
6069

61-
Tokens are valid until they expire, or until they are deleted. By default, tokens are valid for 1 hour and each subsequent request will extend the expiration by 1 hour. This means that if a user makes a request every hour, the token will never expire. If a user makes a request after the token has expired, then a new token will be generated and the `csrf_` cookie will be set again. This means that the token will only expire if the user does not make a request for the duration of the expiration time.
70+
Tokens are valid until they expire or until they are deleted. By default, tokens are valid for 1 hour, and each subsequent request extends the expiration by 1 hour. The token only expires if the user doesn't make a request for the duration of the expiration time.
6271

6372
#### Token Reuse
6473

65-
By default tokens may be used multiple times. This means that the token will not be deleted after it has been used. If you would like to delete the token after it has been used, then you can set the `SingleUseToken` option to `true`. This will delete the token after it has been used, and a new token will be generated on the next request.
74+
By default, tokens may be used multiple times. If you want to delete the token after it has been used, you can set the `SingleUseToken` option to `true`. This will delete the token after it has been used, and a new token will be generated on the next request.
6675

67-
:::note
68-
Using `SingleUseToken` comes with usability tradeoffs, and therefore is not enabled by default. It can interfere with the user experience if the user has multiple tabs open, or if the user uses the back button.
76+
:::info
77+
Using `SingleUseToken` comes with usability trade-offs and is not enabled by default. It can interfere with the user experience if the user has multiple tabs open or uses the back button.
6978
:::
7079

7180
#### Deleting Tokens
7281

73-
When the authorization status changes, the CSRF token should be deleted and a new one generated. This can be done by calling `handler.DeleteToken(c)`. This will remove the token found in the request context from the storage and set the `csrf_` cookie to an empty value. The next 'safe' request will generate a new token and set the cookie again.
82+
When the authorization status changes, the CSRF token MUST be deleted, and a new one generated. This can be done by calling `handler.DeleteToken(c)`.
7483

7584
```go
7685
if handler, ok := app.AcquireCtx(ctx).Locals(ConfigDefault.HandlerContextKey).(*CSRFHandler); ok {
77-
if err := handler.DeleteToken(app.AcquireCtx(ctx)); err != nil {
78-
// handle error
79-
}
86+
if err := handler.DeleteToken(app.AcquireCtx(ctx)); err != nil {
87+
// handle error
88+
}
8089
}
8190
```
8291

83-
:::note
92+
:::tip
8493
If you are using this middleware with the fiber session middleware, then you can simply call `session.Destroy()`, `session.Regenerate()`, or `session.Reset()` to delete session and the token stored therein.
8594
:::
8695

8796
### BREACH
8897

89-
It is important to note that the token is sent as a header on every request, and if you include the token in a page that is vulnerable to [BREACH](https://en.wikipedia.org/wiki/BREACH), then an attacker may be able to extract the token. To mitigate this, you should take steps such as ensuring that your pages are served over HTTPS, that HTTP compression is disabled, and rate limiting requests.
98+
It's important to note that the token is sent as a header on every request. If you include the token in a page that is vulnerable to [BREACH](https://en.wikipedia.org/wiki/BREACH), an attacker may be able to extract the token. To mitigate this, ensure your pages are served over HTTPS, disable HTTP compression, and implement rate limiting for requests.
9099

91100
## Signatures
92101

@@ -96,7 +105,7 @@ func New(config ...Config) fiber.Handler
96105

97106
## Examples
98107

99-
Import the middleware package that is part of the Fiber web framework
108+
Import the middleware package that is part of the Fiber web framework:
100109

101110
```go
102111
import (
@@ -105,7 +114,7 @@ import (
105114
)
106115
```
107116

108-
After you initiate your Fiber app, you can use the following possibilities:
117+
After initializing your Fiber app, you can use the following code to initialize the middleware:
109118

110119
```go
111120
// Initialize default config
@@ -122,14 +131,10 @@ app.Use(csrf.New(csrf.Config{
122131
}))
123132
```
124133

125-
:::note
134+
:::info
126135
KeyLookup will be ignored if Extractor is explicitly set.
127136
:::
128137

129-
### Use with fiber/middleware/session (recommended)
130-
131-
It's recommended to use this middleware with [fiber/middleware/session](https://docs.gofiber.io/api/middleware/session) to store the CSRF token in the session. This is generally more secure than the default configuration.
132-
133138
## Config
134139

135140
| Property | Type | Description | Default |
@@ -157,7 +162,7 @@ It's recommended to use this middleware with [fiber/middleware/session](https://
157162
| Extractor | `func(*fiber.Ctx) (string, error)` | Extractor returns the CSRF token. If set, this will be used in place of an Extractor based on KeyLookup. | Extractor based on KeyLookup |
158163
| HandlerContextKey | `string` | HandlerContextKey is used to store the CSRF Handler into context. | "fiber.csrf.handler" |
159164

160-
## Default Config
165+
### Default Config
161166

162167
```go
163168
var ConfigDefault = Config{
@@ -173,7 +178,9 @@ var ConfigDefault = Config{
173178
}
174179
```
175180

176-
## Recommended Config (with session)
181+
### Recommended Config (with session)
182+
183+
It's recommended to use this middleware with [fiber/middleware/session](https://docs.gofiber.io/api/middleware/session) to store the CSRF token in the session. This is generally more secure than the default configuration.
177184

178185
```go
179186
var ConfigDefault = Config{
@@ -200,7 +207,44 @@ const (
200207
)
201208
```
202209

203-
### Custom Storage/Database
210+
## Sentinel Errors
211+
212+
The CSRF middleware utilizes a set of sentinel errors to handle various scenarios and communicate errors effectively. These can be used within a [custom error handler](#custom-error-handler) to handle errors returned by the middleware.
213+
214+
### Errors Returned to Error Handler
215+
216+
- `ErrTokenNotFound`: Indicates that the CSRF token was not found.
217+
- `ErrTokenInvalid`: Indicates that the CSRF token is invalid.
218+
- `ErrNoReferer`: Indicates that the referer was not supplied.
219+
- `ErrBadReferer`: Indicates that the referer is invalid.
220+
221+
If you are using the default error handler, it will return a 403 Forbidden error for any of these errors without providing any additional information to the client.
222+
223+
## Custom Error Handler
224+
225+
You can use a custom error handler to handle errors returned by the CSRF middleware. The error handler is executed when an error is returned from the middleware. The error handler is passed the error returned from the middleware and the fiber.Ctx.
226+
227+
Example, returning a JSON response for API requests and rendering an error page for other requests:
228+
229+
```go
230+
app.Use(csrf.New(csrf.Config{
231+
ErrorHandler: func(c *fiber.Ctx, err error) error {
232+
accepts := c.Accepts("html", "json")
233+
path := c.Path()
234+
if accepts == "json" || strings.HasPrefix(path, "/api/") {
235+
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{
236+
"error": "Forbidden",
237+
})
238+
}
239+
return c.Status(fiber.StatusForbidden).Render("error", fiber.Map{
240+
"Title": "Forbidden",
241+
"Status": fiber.StatusForbidden,
242+
}, "layouts/main")
243+
},
244+
}))
245+
```
246+
247+
## Custom Storage/Database
204248

205249
You can use any storage from our [storage](https://github.com/gofiber/storage/) package.
206250

0 commit comments

Comments
 (0)