|
48 | 48 | - ⚡️ Fully async
|
49 | 49 | - 🚀 Pydantic V2 and SQLAlchemy 2.0
|
50 | 50 | - 🔐 User authentication with JWT
|
| 51 | +- Cookie based refresh token |
51 | 52 | - 🏬 Easy redis caching
|
52 | 53 | - 👜 Easy client-side caching
|
53 | 54 | - 🚦 ARQ integration for task queue
|
|
92 | 93 | 9. [More Advanced Caching](#59-more-advanced-caching)
|
93 | 94 | 10. [ARQ Job Queues](#510-arq-job-queues)
|
94 | 95 | 11. [Rate Limiting](#511-rate-limiting)
|
95 |
| - 12. [Running](#512-running) |
| 96 | + 12. [JWT Authentication](#512-jwt-authentication) |
| 97 | + 13. [Running](#512-running) |
96 | 98 | 6. [Running in Production](#6-running-in-production)
|
97 | 99 | 1. [Uvicorn Workers with Gunicorn](#61-uvicorn-workers-with-gunicorn)
|
98 | 100 | 2. [Running With NGINX](#62-running-with-nginx)
|
@@ -156,6 +158,7 @@ And then create in `.env`:
|
156 | 158 | SECRET_KEY= # result of openssl rand -hex 32
|
157 | 159 | ALGORITHM= # pick an algorithm, default HS256
|
158 | 160 | ACCESS_TOKEN_EXPIRE_MINUTES= # minutes until token expires, default 30
|
| 161 | +REFRESH_TOKEN_EXPIRE_DAYS= # days until token expires, default 7 |
159 | 162 | ```
|
160 | 163 |
|
161 | 164 | Then for the first admin user:
|
@@ -1251,7 +1254,47 @@ Note that for flexibility (since this is a boilerplate), it's not necessary to p
|
1251 | 1254 | > [!WARNING]
|
1252 | 1255 | > If a user does not have a `tier` or the tier does not have a defined `rate limit` for the path and the token is still passed to the request, the default `limit` and `period` will be used, this will be saved in `app/logs`.
|
1253 | 1256 |
|
1254 |
| -### 5.12 Running |
| 1257 | +### 5.12 JWT Authentication |
| 1258 | +#### 5.12.1 Details |
| 1259 | +The JWT in this boilerplate is created in the following way: |
| 1260 | +1. **JWT Access Tokens:** how you actually access protected resources is passing this token in the request header. |
| 1261 | +2. **Refresh Tokens:** you use this type of token to get an `access token`, which you'll use to access protected resources. |
| 1262 | + |
| 1263 | +The `access token` is short lived (default 30 minutes) to reduce the damage of a potential leak. The `refresh token`, on the other hand, is long lived (default 7 days), and you use it to renew your `access token` without the need to provide username and password every time it expires. |
| 1264 | + |
| 1265 | +Since the `refresh token` lasts for a longer time, it's stored as a cookie in a secure way: |
| 1266 | + |
| 1267 | +```python |
| 1268 | +# app/api/v1/login |
| 1269 | + |
| 1270 | +... |
| 1271 | +response.set_cookie( |
| 1272 | + key="refresh_token", |
| 1273 | + value=refresh_token, |
| 1274 | + httponly=True, # Prevent access through JavaScript |
| 1275 | + secure=True, # Ensure cookie is sent over HTTPS only |
| 1276 | + samesite='Lax', # Default to Lax for reasonable balance between security and usability |
| 1277 | + max_age=<number_of_seconds> # Set a max age for the cookie |
| 1278 | +) |
| 1279 | +... |
| 1280 | +``` |
| 1281 | + |
| 1282 | +You may change it to suit your needs. The possible options for `samesite` are: |
| 1283 | +- `Lax`: Cookies will be sent in top-level navigations (like clicking on a link to go to another site), but not in API requests or images loaded from other sites. |
| 1284 | +- `Strict`: Cookies will be sent in top-level navigations (like clicking on a link to go to another site), but not in API requests or images loaded from other sites. |
| 1285 | +- `None`: Cookies will be sent with both same-site and cross-site requests. |
| 1286 | + |
| 1287 | +#### 5.12.2 Usage |
| 1288 | +What you should do with the client is: |
| 1289 | +- `Login`: Send credentials to `/api/v1/login`. Store the returned access token in memory for subsequent requests. |
| 1290 | +- `Accessing Protected Routes`: Include the access token in the Authorization header. |
| 1291 | +- `Token Renewal`: On access token expiry, the front end should automatically call `/api/v1/refresh` for a new token. |
| 1292 | +- `Login Again`: If refresh token is expired, credentials should be sent to `/api/v1/login` again, storing the new access token in memory. |
| 1293 | +- `Logout`: Call /api/v1/logout to end the session securely. |
| 1294 | + |
| 1295 | +This authentication setup in the provides a robust, secure, and user-friendly way to handle user sessions in your API applications. |
| 1296 | + |
| 1297 | +### 5.13 Running |
1255 | 1298 | If you are using docker compose, just running the following command should ensure everything is working:
|
1256 | 1299 | ```sh
|
1257 | 1300 | docker compose up
|
|
0 commit comments