Skip to main content

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

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
}
Security Warning

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
}'

Code Examples

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();
}

Authorization (RBAC)

Checkmate uses Role-Based Access Control (RBAC) powered by Casbin. Each user is assigned one of three roles:

User Roles

RolePermissionsDescription
ReaderRead-onlyView projects, tests, and runs
UserRead & WriteCreate/update tests, runs, labels, sections
AdminFull AccessAll 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

  1. Client sends request with authentication (token or cookie)
  2. Server validates identity by checking token/session
  3. Server checks permissions using RBAC policies
  4. Casbin evaluates (role, resource, action) tuple
  5. 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

Secure Your Tokens

Follow these best practices to keep your API secure.

✅ Do's

  1. Store tokens securely

    # Good: Environment variable
    export CHECKMATE_TOKEN="your_token"

    # Good: .env file (gitignored)
    CHECKMATE_TOKEN=your_token
  2. Use HTTPS in production

    • Session cookies automatically set Secure flag
    • Prevents token interception
  3. Rotate tokens regularly

    • Generate new tokens periodically
    • Delete unused tokens
  4. Use minimal permissions

    • Use Reader role for read-only operations
    • Only grant Admin when necessary
  5. 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

  1. Never commit tokens to git

    // Bad: Hardcoded token
    const token = "abc123xyz"; // Don't do this!
  2. Don't share tokens

    • Each user/application should have their own token
    • Makes it easier to track and revoke access
  3. Don't log tokens

    // Bad: Token in logs
    console.log('Token:', API_TOKEN);
  4. 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
# 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

Next Steps