chore: update Postman collection and guide with policy endpoints

Postman collection now has 12 endpoints:
  - Health Check, List/Get/Bulk Create/Delete Users
  - List/Create/Get/Update/Delete Policy
  - Verify Policy (dry-run)
  - Get User Policies

POSTMAN_GUIDE.md updated with all endpoints, examples,
policy field reference, matching rules, and testing workflow.
This commit is contained in:
Claus Lohmar 2026-07-15 17:59:57 +00:00
parent 00165e9fef
commit 92f0e7ea25
2 changed files with 500 additions and 139 deletions

View file

@ -1,115 +1,182 @@
# Authelia API - Postman Collection
# Authelia API — Postman Collection Guide
This directory contains Postman files for testing and interacting with the Authelia API.
Postman files for testing and interacting with the Authelia API (user management + access control policies).
## Files
- `authelia-api.postman_collection.json` - Main Postman collection with all API endpoints
- `authelia-api.postman_environment.json` - Environment variables for easy configuration
- `src/test_bulk.json` - Example request body for bulk user creation
| File | Description |
|------|-------------|
| `authelia-api.postman_collection.json` | Collection with all 12 API endpoints |
| `authelia-api.postman_environment.json` | Environment variables (`base_url`, `bearer_token`) |
## Setup Instructions
## Setup
### 1. Import into Postman
1. Open Postman
2. Click **Import** button
3. Select both the collection and environment files
4. Click **Import**
1. Open Postman → **Import** → select both files → **Import**
### 2. Configure Environment
1. In Postman, select the **"Authelia API"** environment from the environment dropdown (top-right)
2. Click the eye icon next to the environment name
3. Set the following variables:
1. Select **"Authelia API"** environment from the dropdown (top-right)
2. Click the eye icon → set variables:
| Variable | Value | Description |
|----------|-------|-------------|
| `base_url` | `http://127.0.0.1:8080` | API base URL (default) |
| `bearer_token` | Your session.secret | **Required** - Get from Authelia config |
| Variable | Default | Description |
|----------|---------|-------------|
| `base_url` | `http://127.0.0.1:8080` | API address |
| `bearer_token` | *(your token)* | `session.secret` from Authelia config |
### 3. Get Your Bearer Token
The initial bearer token is your Authelia `session.secret`:
```bash
# Extract from Authelia configuration
grep -A2 "session:" /opt/authelia/configuration.yml | grep "secret:" | awk '{print $2}'
# Extract from Authelia configuration.yml
grep -A2 "session:" /config/configuration.yml | grep "secret:" | awk '{print $2}'
```
Example token: `5DdUKe12k6niaaekpTeB0H35A48xmTWBWJcI3AOoqPA=`
Example: `5DdUKe12k6niaaekpTeB0H35A48xmTWBWJcI3AOoqPA=`
**Security Note:** This token provides full API access. Keep it secure!
> **Security:** This token grants full API access. Keep it secure.
---
## API Endpoints
### Health Check
- **GET** `/api/health`
- No authentication required
- Returns API status and version
### User Management
### Bulk Create Users
- **POST** `/api/users/bulk`
- Requires Bearer token
- Creates multiple users with auto-generated passwords
- Example request body in `src/test_bulk.json`
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/health` | Health check *(no auth)* |
| `GET` | `/api/users` | List all users |
| `GET` | `/api/users/{username}` | Get single user |
| `POST` | `/api/users/bulk` | Bulk create users (max 1000) |
| `DELETE` | `/api/users/{username}` | Delete user |
### List Users
- **GET** `/api/users`
- Requires Bearer token
- Lists all users in the system
### Policy Management
### Delete User
- **DELETE** `/api/users/{username}`
- Requires Bearer token
- Deletes a user by username
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/policies` | List all policies |
| `POST` | `/api/policies` | Create policy |
| `GET` | `/api/policies/{policy_id}` | Get single policy |
| `PUT` | `/api/policies/{policy_id}` | Update policy |
| `DELETE` | `/api/policies/{policy_id}` | Delete policy |
| `POST` | `/api/policies/verify` | Dry-run policy matching |
| `GET` | `/api/users/{username}/policies` | Get policies for a user |
## Testing Workflow
---
1. **Health Check**: Verify API is running
2. **Bulk Create**: Add test users (see example below)
3. **List Users**: Confirm users were created
4. **Delete User**: Clean up test users
## Examples
### Example: Create Test Users
Use the pre-configured request in the collection, or modify the body:
### Create Policy
```json
POST /api/policies
Authorization: Bearer <token>
{
"name": "Admin Dashboard Restrictions",
"domain": ["*.example.com", "secure.example.com"],
"resources": ["^/admin/.*$"],
"methods": ["POST", "PUT", "DELETE"],
"subjects": ["group:admins", "user:admin"],
"policy": "two_factor"
}
```
**Response `201`:**
```json
{
"id": "pol_93f8s2",
"name": "Admin Dashboard Restrictions",
"domain": ["*.example.com", "secure.example.com"],
"resources": ["^/admin/.*$"],
"methods": ["POST", "PUT", "DELETE"],
"subjects": ["group:admins", "user:admin"],
"policy": "two_factor",
"created_at": "2026-07-15 12:00:00",
"updated_at": "2026-07-15 12:00:00"
}
```
### Verify Policy (Dry-run)
Test how a request would evaluate against your policies:
```json
POST /api/policies/verify
Authorization: Bearer <token>
{
"domain": "secure.example.com",
"path": "/admin/dashboard",
"method": "POST",
"username": "test.user1",
"groups": ["developers", "admins"]
}
```
**Response `200` (matched):**
```json
{
"matched": true,
"policy_id": "pol_93f8s2",
"policy_name": "Admin Dashboard Restrictions",
"action_required": "two_factor"
}
```
**Response `200` (no match):**
```json
{
"matched": false
}
```
### Get User Policies
Retrieve all policies applicable to a specific user:
```json
GET /api/users/john.doe/policies
Authorization: Bearer <token>
```
**Response `200`:**
```json
[
{
"policy_id": "pol_93f8s2",
"name": "Admin Dashboard Restrictions",
"match_reason": "Matched via group membership: admins",
"policy": "two_factor",
"domain": ["*.example.com"],
"resources": ["^/admin/.*$"]
}
]
```
### Create Users (Bulk)
```json
POST /api/users/bulk
Authorization: Bearer <token>
{
"users": [
{
"username": "test.user1",
"display_name": "Test User One",
"email": "test1@example.com",
"groups": ["users", "developers"]
},
{
"username": "test.user2",
"display_name": "Test User Two",
"email": "test2@example.com",
"groups": ["users"]
"username": "john.doe",
"display_name": "John Doe",
"email": "john.doe@example.com",
"groups": ["users", "admins"]
}
]
}
```
## Response Examples
### Health Check
```json
{
"status": "ok",
"version": "dev",
"time": "2026-04-02T00:00:00Z"
}
```
### Bulk Create Success
**Response `200`:**
```json
{
"success": true,
"created": 2,
"created": 1,
"users": [
{
"username": "john.doe",
@ -122,47 +189,107 @@ Use the pre-configured request in the collection, or modify the body:
}
```
### List Users
### Get Single User
```json
[
{
"username": "john.doe",
"display_name": "John Doe",
"email": "john.doe@example.com",
"groups": ["users", "admins"],
"disabled": false,
"created_at": "2026-04-02 00:00:00",
"updated_at": "2026-04-02 00:00:00"
}
]
GET /api/users/john.doe
Authorization: Bearer <token>
```
**Response `200`:**
```json
{
"username": "john.doe",
"display_name": "John Doe",
"email": "john.doe@example.com",
"groups": ["users", "admins"],
"disabled": false,
"created_at": "2026-07-15 12:00:00",
"updated_at": "2026-07-15 12:00:00"
}
```
### Delete User
```json
DELETE /api/users/john.doe
Authorization: Bearer <token>
```
**Response `200`:**
```json
{
"success": true,
"message": "User john.doe deleted"
}
```
### Health Check
```json
GET /api/health
```
**Response `200`:**
```json
{
"status": "ok",
"version": "dev",
"time": "2026-07-15T12:00:00Z"
}
```
---
## Policy Fields Reference
| Field | Required | Type | Description |
|-------|----------|------|-------------|
| `name` | ✅ | string | Human-readable identifier |
| `domain` | ✅ | `[]string` | Domain patterns (supports `*` wildcards) |
| `resources` | no | `[]string` | URL path regex patterns |
| `methods` | no | `[]string` | HTTP methods (empty = all) |
| `subjects` | no | `[]string` | `user:<name>` or `group:<name>` patterns |
| `policy` | ✅ | string | `bypass`, `one_factor`, `two_factor`, or `deny` |
### Matching Rules
- **Domain**: glob-style (`*.example.com` matches `secure.example.com`)
- **Resources**: regex matched against URL paths
- **Methods**: exact match (empty array = all methods pass)
- **Subjects**: matched against user's username and group memberships
- **Policy**: the required auth level if all criteria match
---
## Testing Workflow
```
1. Health Check → Verify API is running
2. Create Policy → Define an access control rule
3. Get Policies → Confirm it was created
4. Verify Policy → Dry-run a request against it
5. Create Users → Add test users (bulk)
6. Get User Policies → Check which policies apply to user
7. Clean up → Delete users and policies
```
---
## Troubleshooting
### 401 Unauthorized
- Check that `bearer_token` is set in environment
- Verify token matches Authelia `session.secret`
- Ensure `Authorization` header is present
| Error | Likely Cause | Fix |
|-------|-------------|-----|
| `401` | Missing/wrong Bearer token | Check `bearer_token` env var; verify it matches `session.secret` |
| `404` | User or policy not found | Check spelling; list first to confirm ID |
| `400` | Invalid request body | Validate JSON syntax; check required fields |
| Connection refused | API not running | `docker ps`; check `docker compose up -d` |
| Policy `400` | Invalid policy value | Must be one of: `bypass`, `one_factor`, `two_factor`, `deny` |
### Connection Refused
- Verify Authelia API is running: `systemctl status authelia-api`
- Check API port: Default is `127.0.0.1:8080`
- Ensure firewall allows local connections
---
### 400 Bad Request
- Validate JSON request body format
- Check required fields: `username`, `display_name`, `email`
- Ensure email contains '@' symbol
## Related
## Next Steps
1. Test API with actual user data
2. Configure SMTP for email onboarding (if needed)
3. Set up monitoring/alerting for API health
4. Consider rotating bearer tokens for production
## Related Resources
- [Authelia API Source Code](../src/)
- [Installation Guide](README.md)
- [OpenAPI Spec](openapi.yml) — Full API specification
- [Source Code](src/) — Go source
- [Authelia Documentation](https://www.authelia.com/)

View file

@ -1,7 +1,7 @@
{
"info": {
"name": "Authelia API API",
"description": "Postman collection for Authelia API REST API\n\nThis API provides a \"Source of Truth\" for Authelia user management with SQLite backend, bulk user onboarding, and automatic synchronization with Authelia's `users_database.yml` file.\n\n## Authentication\n- Use Bearer token authentication\n- Initial token: `session.secret` from Authelia configuration.yml\n- Header: `Authorization: Bearer <token>`\n\n## Base URL\n- Default: `http://127.0.0.1:8080`\n- Can be changed via `--listen` flag\n\n## Quick Start\n1. Install Authelia API using `install.sh`\n2. Start the service: `systemctl start authelia-api`\n3. Get your session.secret from `/opt/authelia/configuration.yml`\n4. Use this collection with the token as environment variable\n\n## Notes\n- All user passwords are auto-generated as secure placeholders\n- Changes trigger automatic sync to Authelia YAML file\n- SMTP onboarding emails available if configured",
"name": "Authelia API",
"description": "Postman collection for Authelia API — user management and access control policy management.\n\n## Authentication\n- Use Bearer token authentication\n- Initial token: `session.secret` from Authelia configuration.yml\n- Header: `Authorization: Bearer <token>`\n\n## Base URL\n- Default: `http://127.0.0.1:8080`\n\n## Quick Start\n1. Start the container: `docker compose up -d`\n2. Get Bearer token from Authelia config's `session.secret`\n3. Set `bearer_token` in environment\n4. Start with Health Check → try Bulk Create → manage policies\n\n## Notes\n- All user passwords are auto-generated\n- Changes trigger automatic sync to Authelia YAML file\n- SMTP onboarding emails available if configured",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
@ -20,7 +20,52 @@
"host": ["{{base_url}}"],
"path": ["api", "health"]
},
"description": "Health check endpoint to verify API is running. No authentication required."
"description": "Health check endpoint. No authentication required.\n\nReturns API status, version, and current timestamp."
},
"response": []
},
{
"name": "List Users",
"request": {
"method": "GET",
"header": [
{
"key": "Authorization",
"value": "Bearer {{bearer_token}}"
}
],
"url": {
"raw": "{{base_url}}/api/users",
"host": ["{{base_url}}"],
"path": ["api", "users"]
},
"description": "List all users in the system.\n\nReturns an array of user objects with username, display_name, email, groups, disabled status, and timestamps."
},
"response": []
},
{
"name": "Get User",
"request": {
"method": "GET",
"header": [
{
"key": "Authorization",
"value": "Bearer {{bearer_token}}"
}
],
"url": {
"raw": "{{base_url}}/api/users/:username",
"host": ["{{base_url}}"],
"path": ["api", "users", ":username"],
"variable": [
{
"key": "username",
"value": "john.doe",
"description": "Username to retrieve"
}
]
},
"description": "Get a single user by username.\n\n**Path Parameter:**\n- `username` — the username to look up\n\nReturns 404 if user not found."
},
"response": []
},
@ -52,26 +97,7 @@
"host": ["{{base_url}}"],
"path": ["api", "users", "bulk"]
},
"description": "Create multiple users in a single request. Passwords are automatically generated and returned in the response.\n\n**Limits:**\n- Max 1000 users per request\n- Username, display_name, and email are required\n- Email must contain '@' symbol\n\n**Response includes:**\n- `success`: boolean indicating if any users were created\n- `created`: count of successfully created users\n- `users`: array with status and placeholder_password for each user"
},
"response": []
},
{
"name": "List Users",
"request": {
"method": "GET",
"header": [
{
"key": "Authorization",
"value": "Bearer {{bearer_token}}"
}
],
"url": {
"raw": "{{base_url}}/api/users",
"host": ["{{base_url}}"],
"path": ["api", "users"]
},
"description": "List all users in the system with pagination support.\n\n**Query Parameters:**\n- `page`: page number (default: 1)\n- `page_size`: items per page (default: 50)\n\n**Note:** Pagination is implemented but currently returns all users. Future versions will support proper pagination."
"description": "Create multiple users in a single request. Passwords are auto-generated.\n\n**Limits:**\n- Max 1000 users per batch\n- `username`, `display_name`, `email` required\n\n**Response includes:**\n- `success`: boolean\n- `created`: count of successfully created users\n- `users`: array with `placeholder_password` and `status` per user"
},
"response": []
},
@ -91,13 +117,213 @@
"path": ["api", "users", ":username"],
"variable": [
{
"key": ":username",
"key": "username",
"value": "john.doe",
"description": "Username to delete"
}
]
},
"description": "Delete a user by username. Triggers automatic sync to update Authelia's YAML file.\n\n**Returns:**\n- `success`: boolean\n- `message`: confirmation message"
"description": "Delete a user by username. Triggers automatic YAML sync.\n\nReturns 404 if user not found."
},
"response": []
},
{
"name": "List Policies",
"request": {
"method": "GET",
"header": [
{
"key": "Authorization",
"value": "Bearer {{bearer_token}}"
}
],
"url": {
"raw": "{{base_url}}/api/policies",
"host": ["{{base_url}}"],
"path": ["api", "policies"]
},
"description": "List all access control policies.\n\nReturns an array of policy objects with id, name, domain, resources, methods, subjects, policy level, and timestamps."
},
"response": []
},
{
"name": "Create Policy",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Authorization",
"value": "Bearer {{bearer_token}}"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"name\": \"Admin Dashboard Restrictions\",\n \"domain\": [\"*.example.com\", \"secure.example.com\"],\n \"resources\": [\"^/admin/.*$\"],\n \"methods\": [\"POST\", \"PUT\", \"DELETE\"],\n \"subjects\": [\"group:admins\", \"user:admin\"],\n \"policy\": \"two_factor\"\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}/api/policies",
"host": ["{{base_url}}"],
"path": ["api", "policies"]
},
"description": "Create a new access control policy rule.\n\n**Required fields:** `name`, `domain` (array with at least 1 pattern), `policy`\n\n**Policy levels:** `bypass`, `one_factor`, `two_factor`, `deny`\n\n**Domain patterns** support wildcards: `*.example.com`\n\n**Resources** are regex patterns matched against URL paths.\n\n**Subjects** can be `user:<username>` or `group:<groupname>`.\n\nReturns the created policy with a generated `id` (e.g. `pol_93f8s2`)."
},
"response": []
},
{
"name": "Get Policy",
"request": {
"method": "GET",
"header": [
{
"key": "Authorization",
"value": "Bearer {{bearer_token}}"
}
],
"url": {
"raw": "{{base_url}}/api/policies/:policy_id",
"host": ["{{base_url}}"],
"path": ["api", "policies", ":policy_id"],
"variable": [
{
"key": "policy_id",
"value": "pol_93f8s2",
"description": "Policy ID (e.g. pol_93f8s2)"
}
]
},
"description": "Get a single policy by its unique ID.\n\nReturns 404 if policy not found."
},
"response": []
},
{
"name": "Update Policy",
"request": {
"method": "PUT",
"header": [
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Authorization",
"value": "Bearer {{bearer_token}}"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"name\": \"Admin Dashboard Restrictions\",\n \"domain\": [\"*.example.com\"],\n \"resources\": [\"^/admin/.*$\"],\n \"methods\": [\"POST\", \"PUT\", \"DELETE\"],\n \"subjects\": [\"group:admins\"],\n \"policy\": \"two_factor\"\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}/api/policies/:policy_id",
"host": ["{{base_url}}"],
"path": ["api", "policies", ":policy_id"],
"variable": [
{
"key": "policy_id",
"value": "pol_93f8s2",
"description": "Policy ID to update"
}
]
},
"description": "Fully replace an existing policy rule. All required fields must be provided.\n\nReturns 404 if policy not found."
},
"response": []
},
{
"name": "Delete Policy",
"request": {
"method": "DELETE",
"header": [
{
"key": "Authorization",
"value": "Bearer {{bearer_token}}"
}
],
"url": {
"raw": "{{base_url}}/api/policies/:policy_id",
"host": ["{{base_url}}"],
"path": ["api", "policies", ":policy_id"],
"variable": [
{
"key": "policy_id",
"value": "pol_93f8s2",
"description": "Policy ID to delete"
}
]
},
"description": "Delete a policy by its ID.\n\nReturns 404 if policy not found."
},
"response": []
},
{
"name": "Verify Policy (Dry-run)",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Authorization",
"value": "Bearer {{bearer_token}}"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"domain\": \"secure.example.com\",\n \"path\": \"/admin/dashboard\",\n \"method\": \"POST\",\n \"username\": \"test.user1\",\n \"groups\": [\"developers\", \"admins\"]\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}/api/policies/verify",
"host": ["{{base_url}}"],
"path": ["api", "policies", "verify"]
},
"description": "Dry-run policy evaluation — simulate a request and see which policy matches.\n\n**Required:** `domain`, `path`\n**Optional:** `method` (defaults to GET), `username`, `groups`\n\nReturns whether a policy matched, and if so the policy ID, name, and required action level."
},
"response": []
},
{
"name": "Get User Policies",
"request": {
"method": "GET",
"header": [
{
"key": "Authorization",
"value": "Bearer {{bearer_token}}"
}
],
"url": {
"raw": "{{base_url}}/api/users/:username/policies",
"host": ["{{base_url}}"],
"path": ["api", "users", ":username", "policies"],
"variable": [
{
"key": "username",
"value": "john.doe",
"description": "Username to evaluate policies for"
}
]
},
"description": "Get all policies that apply to a specific user. Evaluates both direct username matches (`user:john.doe`) and group membership matches (`group:admins`, `group:users`).\n\nReturns an array of policy matches with match reason (direct or via group).\n\nReturns 404 if user not found."
},
"response": []
}
@ -122,7 +348,7 @@
"script": {
"type": "text/javascript",
"exec": [
"// Pre-request script can be used to set dynamic variables",
"// Pre-request script — set dynamic variables here if needed",
"console.log('Request:', pm.request);"
]
}
@ -132,12 +358,12 @@
"script": {
"type": "text/javascript",
"exec": [
"// Test script to validate responses",
"pm.test('Status code is 200 or 201', function () {",
"// Shared test scripts",
"pm.test('Status code is 2xx', function () {",
" pm.expect(pm.response.code).to.be.oneOf([200, 201, 204]);",
"});",
"",
"// For health check, ensure status is ok",
"// Health check assertions",
"if (pm.request.url.toString().includes('/health')) {",
" pm.test('Health check returns ok', function () {",
" var jsonData = pm.response.json();",
@ -145,14 +371,22 @@
" });",
"}",
"",
"// For bulk create, check response structure",
"if (pm.request.url.toString().includes('/bulk')) {",
" pm.test('Bulk create returns success field', function () {",
"// Bulk create assertions",
"if (pm.request.url.toString().includes('/users/bulk')) {",
" pm.test('Bulk create has expected fields', function () {",
" var jsonData = pm.response.json();",
" pm.expect(jsonData).to.have.property('success');",
" pm.expect(jsonData).to.have.property('created');",
" pm.expect(jsonData).to.have.property('users');",
" });",
"}",
"",
"// Policy verify assertions",
"if (pm.request.url.toString().includes('/policies/verify')) {",
" pm.test('Verify response has matched field', function () {",
" var jsonData = pm.response.json();",
" pm.expect(jsonData).to.have.property('matched');",
" });",
"}"
]
}