1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
|
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
- [Auth Proxy](#auth-proxy)
- [Try the Demo](#try-the-demo)
- [Why I Built This](#why-i-built-this)
- [Features](#features)
- [Security and Authentication Details](#security-and-authentication-details)
- [CSRF Protection](#csrf-protection)
- [Password Encryption](#password-encryption)
- [Authentication Flow](#authentication-flow)
- [1. Web UI (Session-Based)](#1-web-ui-session-based)
- [2. API (JWT-Based)](#2-api-jwt-based)
- [Session Management](#session-management)
- [Web UI Sessions](#web-ui-sessions)
- [API Sessions (Stateless with JWT)](#api-sessions-stateless-with-jwt)
- [Getting Started](#getting-started)
- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Configuration](#configuration)
- [Example `.env` file:](#example-env-file)
- [Frontend Selection](#frontend-selection)
- [PHP Frontend Setup](#php-frontend-setup)
- [Database Setup Examples](#database-setup-examples)
- [PostgreSQL](#postgresql)
- [MySQL / MariaDB](#mysql--mariadb)
- [Usage](#usage)
- [Issuing API Tokens (Bearer Tokens)](#issuing-api-tokens-bearer-tokens)
- [Proxying to Protected Backend APIs](#proxying-to-protected-backend-apis)
- [Admin API Endpoints](#admin-api-endpoints)
- [List Users](#list-users)
- [Create User](#create-user)
- [Update User Role](#update-user-role)
- [Update User Status](#update-user-status)
- [Delete User](#delete-user)
- [Configuration Details](#configuration-details)
- [demo](#demo)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<img width="1366" height="526" alt="image" src="https://github.com/user-attachments/assets/eab0085e-00d9-434a-b8eb-6c174fa59f5d" />
# Auth Proxy
This is a simple authenticating reverse proxy written in Go. It provides a flexible authentication layer that can be placed in front of any backend web service.
It handles user registration, login, and session management, and proxies authenticated requests to the configured backend. It also includes an administration dashboard for user management.
## Try the Demo
```bash
chmod +x run-demo.sh
bash run-demo.sh
```
## Why I Built This
I'm also the developer of [puremania](https://github.com/haturatu/puremania), and I wanted to avoid adding complex authentication logic to that project.
While integrating authentication into every application is good for security, it's a hassle to manage separate IDs and passwords for each one. This is a common problem for self-hosting enthusiasts who need a centralized way to control access.
This project aims to solve that by acting as a central authentication service. By referencing the same database, user information can be shared across different applications.
## Features
- **Authentication**: Provides login, logout, and registration pages.
- **Reverse Proxy**: Proxies authenticated users to a backend service.
- **Admin Dashboard**: A simple UI to manage users (update roles, activate/deactivate, delete).
- **Flexible Database Support**: Works with PostgreSQL, MySQL, and SQLite.
- **Pluggable Frontend**: Supports multiple frontend modes (JS-driven or PHP).
- **Security Hardening**:
- **Brute-force Protection**: Locks user accounts after a configurable number of failed login attempts. This protection applies to both the web UI login and the `/api/auth/token` endpoint.
- **User Creation Rate Limiting**: Prevents the same IP from creating too many users in a short period.
- **Configurable Password Policies**: Enforce password strength requirements. See details below.
- **Secure Session Cookies**: Uses `HttpOnly` secure cookies for session management.
- **Highly Configurable**: Nearly all aspects, including database connections, security policies, and internal URL paths, can be configured via an `.env` file.
- **Structured Logging**: Detailed application and security logs using `slog`.
- **CLI for Admin Creation**: A command-line tool to easily create initial admin users.
## Security and Authentication Details
### CSRF Protection
The proxy includes CSRF (Cross-Site Request Forgery) protection to prevent malicious attacks. This is implemented using the `gorilla/csrf` library.
When a user visits a page with a form, a unique CSRF token is generated and embedded in the form. When the form is submitted, the server checks if the token matches the one stored in the user's session. If they don't match, the request is rejected.
This protection is enabled by default. You can configure it using the following environment variables:
- `CSRF_SECRET_KEY`: A long, random secret key used to sign the CSRF tokens.
- `CSRF_TRUSTED_ORIGINS`: A comma-separated list of trusted origins. If your frontend is hosted on a different domain than the proxy, you must add the frontend's origin to this list.
- `CSRF_SAME_SITE`: The `SameSite` attribute for the CSRF cookie. It can be set to `lax` (default), `strict`, or `none`. If you set it to `none`, you must also set `ENV=production` to enable secure cookies.
### Password Encryption
User passwords are never stored in plaintext. They are securely hashed using the **bcrypt** algorithm, a strong, adaptive hashing function designed specifically for passwords. When a user logs in, the provided password is
hashed and then compared to the stored hash, preventing plaintext password exposure even if the database is compromised.
### Authentication Flow
The proxy supports two distinct authentication flows for different use cases:
#### 1. Web UI (Session-Based)
This flow is designed for users interacting with the application through a web browser.
1. A user submits their username and password via the login page.
2. The server validates the credentials against the database.
3. On success, a cryptographically secure, random token is generated and stored in the database, associated with the user.
4. This token is sent to the user's browser in a secure, `HttpOnly` cookie named `auth_token`, establishing a session.
#### 2. API (JWT-Based)
This flow is designed for programmatic clients and services.
1. A client sends a `POST` request with the user's username and password to the `/api/auth/token` endpoint.
2. The server validates the credentials.
3. On success, it generates and returns two tokens:
* A short-lived **JWT Access Token** containing user claims (ID, role) and an expiration time. This token is signed to prevent tampering.
* A long-lived **Refresh Token** that is stored in the database and can be used to obtain a new access token.
### Session Management
#### Web UI Sessions
For subsequent requests from a browser, the `auth_token` cookie is automatically sent to the server. A middleware validates this token by looking it up in the database. If the token is valid and has not expired, the request is authenticated and allowed to proceed. When a user logs out, the session token is deleted from the database, effectively invalidating the session.
#### API Sessions (Stateless with JWT)
For API requests, the client must include the JWT Access Token in the `Authorization: Bearer <token>` header. A middleware on the server validates the token's signature and expiration time. This process is stateless, meaning it does not require a database lookup for every request, making it highly efficient. If the access token has expired, the client can use the refresh token to request a new access token without re-authenticating.
**Note on Authentication Precedence:** When an API endpoint is protected (i.e., `PROTECT_API=true`), the middleware first looks for an `Authorization: Bearer` header. If this header is not present, it will fall back to validating the `auth_token` session cookie. This allows users who are logged into the web UI to also authenticate to the API using their browser session, but it means that API endpoints are accessible via either a valid JWT or a valid session cookie.
### Transport Layer Security (HTTPS)
For production environments, it is **critical** to run this proxy behind a TLS-terminating reverse proxy (like Nginx, Caddy, or a cloud load balancer).
This application does not handle HTTPS termination itself. By default, it communicates over HTTP. If you deploy it without a secure proxy in front, sensitive data like user passwords sent during login could be intercepted in a Man-in-the-Middle (MITM) attack.
Ensure that all traffic between clients and this proxy is encrypted via HTTPS.
## Getting Started
### Prerequisites
- Go 1.21 or later
- (Optional) A running PHP-FPM service if you intend to use the PHP frontend.
- (Optional) PostgreSQL or MySQL database server.
### Installation
1. **Clone the repository:**
```sh
git clone https://github.com/haturatu/auth-proxy/tree/main
cd auth-proxy
```
2. **Install dependencies:**
```sh
go mod tidy
```
3. **Build the binaries:**
```sh
go build -o auth-proxy-server ./cmd/server && go build -o admin-cli ./cmd/admin-cli
```
### Configuration
Configuration is managed via a `.env` file in the root of the project. Create a file named `.env` and add the necessary variables.
# Example `.env` file:
```dotenv
# --- Server Settings ---
# The port for the proxy server to listen on
LISTEN_PORT=8080
# --- Required ---
# The URL of the backend service you want to protect
TARGET_URL=http://localhost:8081
# A long, random string for securing session cookies and JWTs
# For production, generate a new key using: openssl rand -base64 45
SESSION_SECRET=my-super-secret-key
# (Required) A 32-byte random key for CSRF protection.
# Generate with: openssl rand -base64 32
CSRF_SECRET_KEY=
# --- Database ---
# Use ONE of the following options:
# Option 1: PostgreSQL or MySQL (Recommended)
# Example: postgres://user:password@host:port/dbname?sslmode=disable
# Example: mysql://user:password@tcp(host:port)/dbname?charset=utf8mb4&parseTime=true
DATABASE_URL=mysql://test:test@127.0.0.1:3306/auth
# Option 2: SQLite (Default if DATABASE_URL is not set)
# DATABASE_PATH=./auth.db
# --- Frontend & Proxy ---
# Frontend mode: "js" (default) or "php"
FRONTEND_TYPE=js
# If true, protects the frontend path with session authentication
PROTECT_FRONTEND=false
# If true, protects the API path with bearer token authentication
PROTECT_API=false
# Base path for frontend routes to be protected
FRONT_PATH=/
# Base path for API routes to be protected
API_PATH=/api/
# --- Security Policies ---
# Brute-force protection settings
MAX_LOGIN_ATTEMPTS=5
LOCKOUT_DURATION_MINUTES=10
# User creation rate limit settings
USER_CREATION_RATE_LIMIT_MAX_REQUESTS=5
USER_CREATION_RATE_LIMIT_WINDOW_SECONDS=3600
# Password policy (none, standard, enhanced, strict)
PASSWORD_POLICY=standard
# --- Token Durations ---
# Duration for the web session cookie
TOKEN_DURATION_HOURS=24
# Duration for the API JWT access token
ACCESS_TOKEN_DURATION_MINUTES=15
# Duration for the API JWT refresh token
REFRESH_TOKEN_DURATION_DAYS=7
# --- Optional: Path Overrides ---
# Uncomment and change these to avoid URL conflicts with your backend application.
# AUTH_PATH_LOGIN=/login
# AUTH_PATH_REGISTER=/register
# AUTH_PATH_LOGOUT=/logout
# AUTH_PATH_ACCOUNT=/account
# AUTH_PATH_ACCOUNT_PASSWORD=/account/password
# AUTH_PATH_ADMIN=/admin
# AUTH_PATH_ADMIN_USERS_API=/api/admin/users
# AUTH_ASSETS_PATH=/assets
```
### Frontend Selection
You can choose between two frontend modes using the `FRONTEND_TYPE` environment variable:
- **`js` (or empty)**: This is the default mode. The server renders the basic HTML templates, and all authentication logic (rendering forms, handling user input) is expected to be managed by your frontend JavaScript code, which will interact with the Go backend's API endpoints.
- **`php`**: To use the PHP-based views, you must have a running PHP-FPM service. This mode proxies GET requests for authentication pages to your PHP-FPM service, while POST requests (like login submissions) are handled by the Go backend.
#### PHP Frontend Setup
If you choose `FRONTEND_TYPE=php`, follow these steps:
1. **Set Frontend Type in `.env`**:
```dotenv
FRONTEND_TYPE=php
```
2. **Configure PHP-FPM Connection in `.env`**:
You need to provide the path to the PHP-FPM socket and the document root.
- `PHP_FPM_SOCKET`: The path to the PHP-FPM socket file (e.g., `/run/php-fpm/php-fpm.sock`).
- `PHP_DOC_ROOT`: The **absolute path** to the directory containing the PHP view files (e.g., `login.php`). This path must be accessible *by the PHP-FPM process*.
3. **Copy PHP Files and Set Permissions**:
The user that the PHP-FPM service runs as needs read access to the PHP template files.
First, determine the PHP-FPM user. You can often find this in your PHP-FPM pool configuration file (e.g., `/etc/php/8.3/fpm/pool.d/www.conf`) or by checking the running processes:
```sh
# Example command to find the PHP-FPM user
ps aux | grep php-fpm
```
Common users are `www-data`, `http`, or `apache`.
Next, copy the `templates/php` directory to a location accessible by PHP-FPM (e.g., `/var/www/html/auth-proxy`) and set the correct ownership.
```sh
# Example setup, assuming the user is 'http'
sudo cp -r templates/php /var/www/html/auth-proxy/php
sudo chown -R http:http /var/www/html/auth-proxy
```
Finally, update your `.env` file with the correct paths:
```dotenv
# --- PHP Frontend Settings ---
FRONTEND_TYPE=php
PHP_FPM_SOCKET=/run/php-fpm/php-fpm.sock
PHP_DOC_ROOT=/var/www/html/auth-proxy/php
```
### Database Setup Examples
If you are using PostgreSQL or MySQL, you will need to create a database and a user for the proxy.
#### PostgreSQL
Run these commands in `psql`:
```sql
-- Create a dedicated database
CREATE DATABASE auth_proxy;
-- Create a dedicated user
CREATE USER auth_user WITH PASSWORD 'your_strong_password';
-- Grant privileges on the database to the user
GRANT ALL PRIVILEGES ON DATABASE auth_proxy TO auth_user;
```
Your `DATABASE_URL` in the `.env` file would then be:
`DATABASE_URL=postgres://auth_user:your_strong_password@localhost:5432/auth_proxy?sslmode=disable`
#### MySQL / MariaDB
Run these commands in the MySQL client:
```sql
-- Create a dedicated database
CREATE DATABASE auth_proxy CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- Create a dedicated user
CREATE USER 'auth_user'@'localhost' IDENTIFIED BY 'your_strong_password';
-- Grant privileges on the database to the user
GRANT ALL PRIVILEGES ON auth_proxy.* TO 'auth_user'@'localhost';
-- Apply the changes
FLUSH PRIVILEGES;
```
Your `DATABASE_URL` in the `.env` file would then be:
`DATABASE_URL=mysql://auth_user:your_strong_password@tcp(127.0.0.1:3306)/auth_proxy?parseTime=true`
## Usage
1. **Create an Admin User**:
Before starting the server, create your first admin user using the `admin-cli` tool. Make sure your `.env` file is configured correctly, as the CLI uses it to connect to the database.
The `--username` and `--password` flags are required.
*Successful command:*
```sh
./admin-cli --username <your-admin-username> --password <your-strong-password>
```
*Example of missing flags:*
```sh
$ ./admin-cli
time=2025-10-12T04:28:09.014+09:00 level=ERROR msg="Both --username and --password flags are required"
```
2. **Run the Proxy Server**:
```sh
./auth-proxy-server
```
The server will start on port `:8080` by default.
3. **Access the Application**:
- Open your browser and navigate to `http://localhost:8080`.
- You will be redirected to the login page.
- Log in with the admin credentials you created.
- Once authenticated, you will be seamlessly proxied to the `TARGET_URL`.
- You can access the admin dashboard at `http://localhost:8080/admin` (or your configured path).
## Issuing API Tokens (Bearer Tokens)
In addition to session-based authentication for web browsers, the proxy can issue JWT (JSON Web Tokens) for programmatic API access. These tokens can be used as Bearer Tokens in the `Authorization` header to authenticate requests to protected backend APIs.
To obtain an access token and a refresh token, send a `POST` request to the `/api/auth/token` endpoint with the user's credentials in the JSON body.
**Example using `curl`:**
```sh
curl -X POST -H "Content-Type: application/json" -d '{
"username": "your-username",
"password": "your-password"
}' http://localhost:8080/api/auth/token
```
**Successful Response:**
If the credentials are valid, the server will respond with a JSON object containing an `access_token` and a `refresh_token`.
```json
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJyb2xlIjoiYWRtaW4iLCJleHAiOjE2Njc4OTg5ODl9.abcdef123456...",
"refresh_token": "def456..."
}
```
The `access_token` is a short-lived JWT that should be sent in the `Authorization` header for API requests:
```
Authorization: Bearer <access_token>
```
The `refresh_token` is a long-lived token that can be used to obtain a new access token once the old one expires. To do this, send a `POST` request to the `/auth/refresh` endpoint.
**Note:** The token lifetimes can be configured in your `.env` file. See the configuration table for details.
### Proxying to Protected Backend APIs
When `PROTECT_API=true`, any request to a path under `API_PATH` (e.g., `/api/`) that is not one of the internal administrative endpoints will be authenticated and then proxied to your backend `TARGET_URL`.
This allows you to protect your own backend APIs using the same authentication mechanism. Authentication is verified using either a valid `Authorization: Bearer` token or, as a fallback, a valid web session cookie.
**Example `curl` to a protected backend API:**
```sh
ACCESS_TOKEN="your_access_token"
curl -H "Authorization: Bearer $ACCESS_TOKEN" http://localhost:8080/api/config
```
**Example successful response from the backend:**
```json
{"success":true,"data":{"StorageDir":"/home/haturatu","MountDirs":[],"MaxFileSize":10000,"SpecificDirs":["/home/haturatu/git"],"Aria2cEnabled":true}}
```
## Admin API Endpoints
For administrative tasks, the proxy provides several API endpoints that can be accessed programmatically. All of these endpoints require a valid Bearer Token from a user with the `admin` role.
The base path for these endpoints is `/api/admin/users`, which can be customized with the `AUTH_PATH_ADMIN_USERS_API` environment variable.
### List Users
- **Endpoint**: `GET /api/admin/users`
- **Description**: Retrieves a list of all users in the system.
- **Example**:
```sh
ACCESS_TOKEN="your_admin_access_token"
curl -H "Authorization: Bearer $ACCESS_TOKEN" http://localhost:8080/api/admin/users
```
### Create User
- **Endpoint**: `POST /api/admin/users`
- **Description**: Creates a new user.
- **Body**:
```json
{
"username": "newuser",
"password": "a-strong-password",
"role": "user"
}
```
- **Example**:
```sh
ACCESS_TOKEN="your_admin_access_token"
curl -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"username": "newuser", "password": "Password123", "role": "user"}' \
http://localhost:8080/api/admin/users
```
### Update User Role
- **Endpoint**: `POST /api/admin/users/{id}/role`
- **Description**: Updates the role of a specific user by their ID.
- **Body**:
```json
{
"role": "admin"
}
```
- **Example**:
```sh
USER_ID=2
ACCESS_TOKEN="your_admin_access_token"
curl -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"role": "admin"}' \
http://localhost:8080/api/admin/users/$USER_ID/role
```
### Update User Status
- **Endpoint**: `POST /api/admin/users/{id}/status`
- **Description**: Activates or deactivates a user by their ID.
- **Body**:
```json
{
"is_active": false
}
```
- **Example**:
```sh
USER_ID=2
ACCESS_TOKEN="your_admin_access_token"
curl -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"is_active": false}' \
http://localhost:8080/api/admin/users/$USER_ID/status
```
### Delete User
- **Endpoint**: `DELETE /api/admin/users/{id}`
- **Description**: Deletes a user by their ID.
- **Example**:
```sh
USER_ID=2
ACCESS_TOKEN="your_admin_access_token"
curl -X DELETE -H "Authorization: Bearer $ACCESS_TOKEN" \
http://localhost:8080/api/admin/users/$USER_ID
```
## Configuration Details
| Environment Variable | Description | Default Value |
| --- | --- | --- |
| `TARGET_URL` | **(Required)** The URL of the backend service to proxy to. | - |
| `SESSION_SECRET` | **(Required)** A long, random secret key for encrypting session cookies and signing JWTs. | `default-secret-key-for-dev` |
| `DATABASE_URL` | The connection string for PostgreSQL or MySQL. If set, this overrides `DATABASE_PATH`. | - |
| `DATABASE_PATH` | The file path for the SQLite database. Used only if `DATABASE_URL` is not set. | `./auth.db` |
| `LOG_LEVEL` | Sets the logging level. Can be `DEBUG`, `INFO`, `WARN`, `ERROR`. | `INFO` |
| `LISTEN_PORT` | The port for the proxy server to listen on. | `8080` |
| `FRONTEND_TYPE` | Switches the frontend rendering mode. Can be `js` or `php`. | `js` |
| `PHP_FPM_SOCKET` | The file path to the PHP-FPM socket. Used only when `FRONTEND_TYPE` is `php`. | `/run/php-fpm/php-fpm.sock` |
| `PHP_DOC_ROOT` | The absolute path to the PHP files directory. Used only when `FRONTEND_TYPE` is `php`. | - |
| `MAX_LOGIN_ATTEMPTS` | Number of failed login attempts before an account is locked. | `5` |
| `LOCKOUT_DURATION_MINUTES` | Duration in minutes for how long an account remains locked. | `10` |
| `USER_CREATION_RATE_LIMIT_MAX_REQUESTS` | Max number of user registrations allowed from a single IP within the time window. | `5` |
| `USER_CREATION_RATE_LIMIT_WINDOW_SECONDS` | The time window in seconds for the user creation rate limit. | `3600` (1 hour) |
| `PASSWORD_POLICY` | Sets the password strength requirements (`none`, `standard`, `enhanced`, `strict`). | `standard` |
| `TOKEN_DURATION_HOURS` | The duration in hours for the web session cookie. | `24` |
| `ACCESS_TOKEN_DURATION_MINUTES` | The duration in minutes for a JWT access token for API clients. | `15` |
| `REFRESH_TOKEN_DURATION_DAYS` | The duration in days for a JWT refresh token for API clients. | `7` |
| `PROTECT_FRONTEND` | If `true`, proxies all frontend paths through session authentication. | `false` |
| `PROTECT_API` | If `true`, proxies all API paths through bearer token authentication. | `false` |
| `FRONT_PATH` | The base path for frontend routes to be protected by `PROTECT_FRONTEND`. | `/` |
| `API_PATH` | The base path for API routes to be protected by `PROTECT_API`. | `/api/` |
| `REGISTER` | If set to `false`, disables new user registration. | `true` |
| `AUTH_PATH_*` | A set of variables to customize the internal URLs for login, admin, etc. | Various, e.g., `/login`|
| `AUTH_ASSETS_PATH` | The URL path for serving internal static assets (CSS, JS). | `/assets` |
| `ENV` | The runtime environment. Set to `production` to enable secure cookies. | - |
| `CSRF_SECRET_KEY` | **(Required)** A 32-byte random key for CSRF protection. Generate with `openssl rand -base64 32`. | - |
| `CSRF_TRUSTED_ORIGINS` | A comma-separated list of trusted origins for CSRF protection. | - |
| `CSRF_SAME_SITE` | The SameSite attribute for the CSRF cookie. Can be `lax`, `strict`, or `none`. | `lax` |
## demo
<img width="1366" height="461" alt="image" src="https://github.com/user-attachments/assets/17632b15-b0a3-4cc7-bafa-7392a209bcc7" />
<img width="1366" height="461" alt="image" src="https://github.com/user-attachments/assets/bea8beb4-485b-4fac-9015-bf2c9d3490ac" />
|