Ir al contenido

REST API Authentication

Esta página aún no está disponible en tu idioma.

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


Building a commercial IoT product?

We provide ESP32 ODM design-to-manufacturing services. From prototype to production — the team behind this tutorial can build it with you.

Talk to us →