Authentication & Authorization
Checkmate supports two authentication methods: Session Cookies for web applications and API Tokens for programmatic access.
Authentication Methods
Session-Based Authentication
Used primarily by the web interface. After logging in via Google OAuth, a session cookie is automatically set.
Cookie Name: user_session
Best for:
- Web applications
- Browser-based tools
- Interactive use
API Token Authentication
Used for scripts, automation, and third-party integrations.
Best for:
- CI/CD pipelines
- Automation scripts
- Third-party integrations
- Mobile apps
Getting Started
- API Token (Recommended)
- Session Cookie
Step 1: Generate a Token
First, log in to Checkmate via the web interface, then generate a token:
curl -X POST http://localhost:3000/api/v1/token/generate \
-b cookies.txt \
-H "Content-Type: application/json" \
-d '{
"userId": 1
}'
Response:
{
"data": {
"token": "abc123xyz789...",
"userId": 1,
"createdAt": "2024-01-15T10:30:00Z"
},
"status": 201
}
Save your token securely! It cannot be retrieved later. If lost, generate a new one.
Step 2: Use the Token
Include the token in the Authorization header:
curl -X GET "http://localhost:3000/api/v1/projects?orgId=1&page=1&pageSize=10" \
-H "Authorization: Bearer abc123xyz789..." \
-H "Content-Type: application/json"
Step 3: Revoke Token (Optional)
When no longer needed:
curl -X DELETE http://localhost:3000/api/v1/token/delete \
-H "Authorization: Bearer abc123xyz789..." \
-H "Content-Type: application/json" \
-d '{
"tokenId": 123
}'
Step 1: Login via Browser
Navigate to the login page:
http://localhost:3000/login
Step 2: Authenticate with Google
Click "Sign in with Google" and complete the OAuth flow.
Step 3: Save Cookies
For cURL, save the session cookie:
# Login and save cookies
curl -c cookies.txt -L http://localhost:3000/login
Step 4: Use Cookies
Include cookies in subsequent requests:
# Use saved cookies
curl -b cookies.txt \
http://localhost:3000/api/v1/projects?orgId=1&page=1&pageSize=10
Code Examples
- JavaScript
- Python
- cURL
- Node.js
const API_TOKEN = 'your_api_token_here';
const BASE_URL = 'http://localhost:3000';
// Fetch projects
async function getProjects() {
const response = await fetch(
`${BASE_URL}/api/v1/projects?orgId=1&page=1&pageSize=10`,
{
method: 'GET',
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json'
}
}
);
return await response.json();
}
// Create a test
async function createTest(testData) {
const response = await fetch(
`${BASE_URL}/api/v1/test/create`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(testData)
}
);
return await response.json();
}
import requests
API_TOKEN = 'your_api_token_here'
BASE_URL = 'http://localhost:3000'
headers = {
'Authorization': f'Bearer {API_TOKEN}',
'Content-Type': 'application/json'
}
# Fetch projects
def get_projects():
response = requests.get(
f'{BASE_URL}/api/v1/projects',
headers=headers,
params={'orgId': 1, 'page': 1, 'pageSize': 10}
)
return response.json()
# Create a test
def create_test(test_data):
response = requests.post(
f'{BASE_URL}/api/v1/test/create',
headers=headers,
json=test_data
)
return response.json()
# Example usage
if __name__ == '__main__':
projects = get_projects()
print(projects)
# Set your token
export CHECKMATE_TOKEN="your_api_token_here"
# Fetch projects
curl -X GET "http://localhost:3000/api/v1/projects?orgId=1&page=1&pageSize=10" \
-H "Authorization: Bearer $CHECKMATE_TOKEN" \
-H "Content-Type: application/json"
# Create a test
curl -X POST http://localhost:3000/api/v1/test/create \
-H "Authorization: Bearer $CHECKMATE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Verify user login",
"projectId": 1,
"sectionId": 5,
"priorityId": 2
}'
const axios = require('axios');
const API_TOKEN = process.env.CHECKMATE_TOKEN;
const BASE_URL = 'http://localhost:3000';
const api = axios.create({
baseURL: BASE_URL,
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json'
}
});
// Fetch projects
async function getProjects() {
try {
const { data } = await api.get('/api/v1/projects', {
params: { orgId: 1, page: 1, pageSize: 10 }
});
return data;
} catch (error) {
console.error('Error fetching projects:', error.response?.data);
throw error;
}
}
// Create a test
async function createTest(testData) {
try {
const { data } = await api.post('/api/v1/test/create', testData);
return data;
} catch (error) {
console.error('Error creating test:', error.response?.data);
throw error;
}
}
Authorization (RBAC)
Checkmate uses Role-Based Access Control (RBAC) powered by Casbin. Each user is assigned one of three roles:
User Roles
| Role | Permissions | Description |
|---|---|---|
| Reader | Read-only | View projects, tests, and runs |
| User | Read & Write | Create/update tests, runs, labels, sections |
| Admin | Full Access | All User permissions + delete operations, user management |
Permission Examples
// Reader ✅ Can do
GET /api/v1/projects
GET /api/v1/project/tests
// Reader ❌ Cannot do
POST /api/v1/test/create
DELETE /api/v1/test/delete
// User ✅ Can do
POST /api/v1/test/create
PUT /api/v1/test/update
POST /api/v1/run/create
// User ❌ Cannot do
DELETE /api/v1/project/delete
PUT /api/v1/user/update-role
// Admin ✅ Can do everything
DELETE /api/v1/test/delete
PUT /api/v1/user/update-role
POST /api/v1/token/generate
Authorization Flow
- Client sends request with authentication (token or cookie)
- Server validates identity by checking token/session
- Server checks permissions using RBAC policies
- Casbin evaluates
(role, resource, action)tuple - Request allowed or denied with appropriate HTTP status
Error Responses
401 Unauthorized
{
"error": "Unauthorized - Please login",
"status": 401
}
Causes:
- Missing or invalid authentication token
- Expired session cookie
- Token has been revoked
Solution: Generate a new token or log in again.
403 Forbidden
{
"error": "User does not have access",
"status": 403
}
Causes:
- User role doesn't have permission for this operation
- Attempting admin-only action as User/Reader
Solution: Contact an admin to update your role or use an endpoint appropriate for your role.
Security Best Practices
Follow these best practices to keep your API secure.
✅ Do's
-
Store tokens securely
# Good: Environment variable
export CHECKMATE_TOKEN="your_token"
# Good: .env file (gitignored)
CHECKMATE_TOKEN=your_token -
Use HTTPS in production
- Session cookies automatically set
Secureflag - Prevents token interception
- Session cookies automatically set
-
Rotate tokens regularly
- Generate new tokens periodically
- Delete unused tokens
-
Use minimal permissions
- Use Reader role for read-only operations
- Only grant Admin when necessary
-
Implement retry logic
async function fetchWithRetry(url, options, retries = 3) {
try {
return await fetch(url, options);
} catch (error) {
if (retries > 0 && error.status === 429) {
await new Promise(r => setTimeout(r, 1000));
return fetchWithRetry(url, options, retries - 1);
}
throw error;
}
}
❌ Don'ts
-
Never commit tokens to git
// Bad: Hardcoded token
const token = "abc123xyz"; // Don't do this! -
Don't share tokens
- Each user/application should have their own token
- Makes it easier to track and revoke access
-
Don't log tokens
// Bad: Token in logs
console.log('Token:', API_TOKEN); -
Don't use tokens in URLs
// Bad: Token in query parameter
fetch(`/api/projects?token=${API_TOKEN}`)
// Good: Token in header
fetch('/api/projects', {
headers: { 'Authorization': `Bearer ${API_TOKEN}` }
})
Testing Authentication
Test Token Authentication
# 1. Generate token
TOKEN=$(curl -X POST http://localhost:3000/api/v1/token/generate \
-b cookies.txt \
-H "Content-Type: application/json" \
-d '{"userId": 1}' | jq -r '.data.token')
# 2. Use token
curl -H "Authorization: Bearer $TOKEN" \
http://localhost:3000/api/v1/user/details
# 3. Expected: Your user details
Test Session Cookie
# 1. Login and save cookies
curl -c cookies.txt -L http://localhost:3000/login
# 2. Use cookies
curl -b cookies.txt http://localhost:3000/api/v1/user/details
# 3. Expected: Your user details
Test Authorization (RBAC)
# Try admin-only endpoint with non-admin user
curl -H "Authorization: Bearer your_reader_token" \
http://localhost:3000/api/v1/all-users
# Expected: 403 Forbidden