Skip to content

REST API Authentication

REST API Authentication

This section covers the authentication mechanism for the TimeTagger REST API, including generating API tokens,securing requests, and handling authentication in Node-RED flows. Learning this section will enable you to:

  • Understand TimeTagger’s API token authentication model
  • Generate and manage API tokens
  • Implement token-based authentication in HTTP requests
  • Troubleshoot common authentication issues

Before starting this section, ensure you have:

  • TimeTagger installed and running (see 05-05)
  • Node-RED accessible and configured
  • Basic understanding of HTTP headers
  • TimeTagger admin credentials

TimeTagger uses a simple token-based authentication system:

Client Request → Include Token → Server Validates → Grant/Deny Access

Unlike OAuth or JWT, TimeTagger tokens:

  • Do not expire (unless manually revoked)
  • Are single strings (no refresh token flow)
  • Grant full API access (no scope/permission levels)
  • Are tied to a user account (admin or regular user)

Advantages for IoT Systems:

FeatureBenefit
No expirationToken can be hardcoded in ESP32/Node-RED
No refresh flowSimplifies implementation on microcontrollers
Single tokenOne token for all API operations
RevocableCan disable access by regenerating token

All API requests use the following base URL:

http://<server-address>:8820/api/v2/

Example endpoints:

EndpointMethodPurpose
/api/v2/infoGETServer information
/api/v2/recordsGETRetrieve records
/api/v2/recordsPOSTCreate new records
/api/v2/recordsPUTUpdate existing records
/api/v2/recordsDELETEDelete (hide) records

Web UI Method:

1. Log into TimeTagger web UI (http://localhost:8820)
2. Click on your username (top-right corner)
3. Select "Account" from the dropdown
4. Find "API Token" section
5. Copy the token string
┌─────────────────────────────────────┐
│ Account Settings │
├─────────────────────────────────────┤
│ Username: admin │
│ │
│ API Token │
│ ┌─────────────────────────────┐ │
│ │ eyJhbGciOiJIUzI1NiIs... │ │
│ └─────────────────────────────┘ │
│ [Copy] [Reset Token] │
│ │
│ API Token enables access to the │
│ server for 3rd party applications. │
│ Tokens do not expire. │
│ Resetting token revokes access │
│ for all applications. │
└─────────────────────────────────────┘

API Method (if already authenticated):

Terminal window
# Using curl with existing token
curl -s http://localhost:8820/api/v2/info \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
# Response:
# {"ok": true, "version": "2024.1", ...}

Test the token before using it in Node-RED:

Terminal window
# Test using curl
curl -s -X GET "http://localhost:8820/api/v2/info" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
# Expected response (success):
# {"ok":true,"version":"24.12","user":"admin",...}
# Expected response (failure):
# {"ok":false,"error":"Unauthorized"}

Step 3: Configure Authentication in Node-RED

Section titled “Step 3: Configure Authentication in Node-RED”

Node-RED Function Node for Authentication:

// auth-config.js — Place in a Function node
// This configures authentication for TimeTagger API requests
const authToken = "eyJhbGciOiJIUzI1NiIs..."; // Replace with your actual token
msg.headers = {
"Authorization": "Bearer " + authToken,
"Content-Type": "application/json"
};
return msg;

Reusable Authentication Module:

Create a subflow or use a global context for cleaner code:

// In a function node, set the auth token globally once
if (!global.get("timetaggerAuth")) {
global.set("timetaggerAuth", {
token: "eyJhbGciOiJIUzI1NiIs...",
baseUrl: "http://timetagger:80/api/v2"
});
}

For environment-level security, store the token in Docker environment variables:

Docker Compose approach:

services:
nodered:
image: nodered/node-red:latest
environment:
- TIMETAGGER_TOKEN=eyJhbGciOiJIUzI1NiIs...
- TIMETAGGER_URL=http://timetagger:80/api/v2

Node-RED flow to read environment variables:

// In a function node at startup
const token = process.env.TIMETAGGER_TOKEN;
const url = process.env.TIMETAGGER_URL;
if (token && url) {
global.set("timetaggerAuth", {
token: token,
baseUrl: url
});
node.warn("TimeTagger auth configured from environment");
} else {
node.error("TimeTagger auth not configured in environment");
}

Implement proper error handling for authentication failures:

handle-auth-error.js
// Use this after HTTP request nodes to handle 401 responses
if (msg.statusCode === 401) {
node.warn("TimeTagger authentication failed - check API token");
msg.authError = true;
msg.errorDetail = "Token invalid or expired. Regenerate in TimeTagger Account settings.";
} else if (msg.statusCode === 403) {
node.warn("TimeTagger access denied");
msg.authError = true;
msg.errorDetail = "Token does not have sufficient permissions.";
} else if (msg.statusCode >= 400) {
node.warn("TimeTagger HTTP error: " + msg.statusCode);
msg.authError = true;
msg.errorDetail = "HTTP " + msg.statusCode;
}
return msg;

Verify the authentication is working:

Terminal window
# 1. Test with correct token
curl -s -X GET "http://localhost:8820/api/v2/info" \
-H "Authorization: Bearer VALID_TOKEN"
# Expected: JSON with user info
# {"ok":true,"version":"24.12","user":"admin"}
# 2. Test with invalid token
curl -s -X GET "http://localhost:8820/api/v2/info" \
-H "Authorization: Bearer INVALID_TOKEN"
# Expected: 401 Unauthorized
# {"ok":false,"error":"Unauthorized"}
# 3. Test without token
curl -s -X GET "http://localhost:8820/api/v2/info"
# Expected: 401 Unauthorized
# {"ok":false,"error":"Unauthorized"}

Node-RED Test Flow:

[Inject] → [Function: Set Auth Header] → [HTTP Request] → [Debug]
[http://localhost:8820/api/v2/info]
  1. Create an Inject node (timestamp trigger)
  2. Create a Function node with auth header code
  3. Create an HTTP Request node (GET to /api/v2/info)
  4. Connect to Debug node
  5. Deploy and trigger

Expected Debug Output:

{
"ok": true,
"version": "24.12",
"user": "admin",
"now": 1715942400,
"from_epoch": 0,
"to_epoch": 0
}

Symptom: HTTP 401 response despite using the correct token

Possible Causes:

  • Token contains extra whitespace
  • Token was reset/regenerated
  • Using token from a different instance

Solution:

Terminal window
# 1. Regenerate token in TimeTagger Account settings
# 2. Copy token exactly (no leading/trailing spaces)
# 3. Update all applications with new token
# Test token character by character
echo -n "YOUR_TOKEN" | wc -c

Symptom: Browser console shows CORS errors when making API calls from Node-RED

Cause: TimeTagger’s CORS policy blocks cross-origin requests

Solution: Use Node-RED’s server-side HTTP request node (not browser-based) or configure proxy:

// Always use Node-RED's http-request node (server-side)
// NOT the browser's fetch() or XMLHTTPRequest

Symptom: Token visible in logs or error messages

Solution:

// Sanitize token in log output
function sanitize(str) {
if (str && str.length > 10) {
return str.substring(0, 6) + "..." + str.substring(str.length - 4);
}
return str;
}
node.warn("Using token: " + sanitize(authToken));
// Output: "Using token: eyJhb...Is..."
  • Recommended: Store API tokens in environment variables, not in flow code
  • Recommended: Use Docker secrets for production deployments
  • Recommended: Regenerate tokens periodically (e.g., every 6 months)
  • Avoid: Hardcoding tokens in GitHub repositories or shared flows
  • Avoid: Sharing tokens between different environments (dev/staging/prod)
  1. TimeTagger uses simple token authentication — no OAuth, no expiration
  2. API tokens are obtained from Account settings in the TimeTagger web UI
  3. Token is passed via Authorization header: Bearer <token>
  4. Node-RED can use environment variables for secure token storage
  5. 401 response indicates token issues — regenerate if needed

Writing Date: 2026-05-17
Based on Source File: 校正版/10 Time recording witht RFID und TimeTagger.md
Target Audience: Alibaba.com IoT Pre-sales Engineer
Status: ✅ Completed