Skip to content

Authentication ​

This guide covers authentication mechanisms for the Smart City TVMS API.

Overview ​

The API uses JWT (JSON Web Tokens) for authentication. Tokens are issued upon successful login and must be included in subsequent requests.

Authentication Flow ​

┌──────────────┐         ┌──────────────┐         ┌──────────────┐
│    Client    │         │     API      │         │   Database   │
└──────┬───────┘         └──────┬───────┘         └──────┬───────┘
       │                        │                        │
       │  POST /trpc/auth.login │                        │
       │───────────────────────▶│                        │
       │  { email, password }   │                        │
       │                        │  Verify credentials    │
       │                        │───────────────────────▶│
       │                        │                        │
       │                        │◀───────────────────────│
       │                        │  User data             │
       │                        │                        │
       │◀───────────────────────│                        │
       │  { token, user }       │                        │
       │                        │                        │
       │  GET /trpc/sensors.getAll                       │
       │  Authorization: Bearer {token}                  │
       │───────────────────────▶│                        │
       │                        │  Verify JWT            │
       │                        │                        │
       │◀───────────────────────│                        │
       │  { sensors: [...] }    │                        │
       │                        │                        │

Obtaining a Token ​

Login Request ​

bash
curl -X POST "https://api.itms.solutions/trpc/auth.login" \
  -H "Content-Type: application/json" \
  -d '{
    "json": {
      "email": "admin@itms.solutions",
      "password": "Admin@123"
    }
  }'

Login Response ​

json
{
  "result": {
    "data": {
      "json": {
        "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImFkbWluLTAwMSIsImVtYWlsIjoiYWRtaW5AaXRtcy5zb2x1dGlvbnMiLCJyb2xlIjoiQURNSU4iLCJmaXJzdE5hbWUiOiJTeXN0ZW0iLCJsYXN0TmFtZSI6IkFkbWluaXN0cmF0b3IiLCJleHAiOjE3MzE3NjAwMDB9.xxxxx",
        "user": {
          "id": "admin-001",
          "email": "admin@itms.solutions",
          "firstName": "System",
          "lastName": "Administrator",
          "role": "ADMIN"
        }
      }
    }
  }
}

Using the Token ​

Include the token in the Authorization header for all protected requests:

bash
curl -X GET "https://api.itms.solutions/trpc/sensors.getAllSensors" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Token Structure ​

The JWT contains the following claims:

json
{
  "id": "admin-001",
  "email": "admin@itms.solutions",
  "role": "ADMIN",
  "firstName": "System",
  "lastName": "Administrator",
  "exp": 1731760000
}
ClaimDescription
idUser's unique identifier
emailUser's email address
roleUser's role (ADMIN, OPERATOR, VIEWER)
firstNameUser's first name
lastNameUser's last name
expToken expiration timestamp (Unix)

Token Expiration ​

  • Tokens expire 24 hours after issuance
  • Use auth.refreshToken to obtain a new token before expiration
  • Expired tokens return 401 Unauthorized

Refreshing a Token ​

bash
curl -X POST "https://api.itms.solutions/trpc/auth.refreshToken" \
  -H "Authorization: Bearer YOUR_CURRENT_TOKEN"

Response:

json
{
  "result": {
    "data": {
      "json": {
        "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
        "expiresIn": 86400,
        "user": {
          "id": "admin-001",
          "email": "admin@itms.solutions",
          "firstName": "System",
          "lastName": "Administrator",
          "role": "ADMIN"
        }
      }
    }
  }
}

User Roles ​

RoleAccess Level
ADMINFull access to all endpoints
OPERATORCan manage sensors, view reports
VIEWERRead-only access

Protected vs Public Endpoints ​

Public Endpoints (No Auth Required) ​

  • auth.login - Login
  • auth.logout - Logout
  • system.health - Health check
  • system.getLicense - License info
  • system.getSettings - System settings
  • system.timezone.getTimezoneSettings - Timezone settings

Protected Endpoints (Auth Required) ​

  • auth.me - Get current user
  • auth.refreshToken - Refresh token
  • sensors.create - Create sensor
  • sensors.update - Update sensor
  • sensors.delete - Delete sensor
  • reports.getAnalytics - Get analytics
  • reports.getReports - Get reports
  • storage.getStats - Storage stats

Error Handling ​

Invalid Credentials ​

json
{
  "error": {
    "json": {
      "message": "Invalid credentials",
      "code": -32001,
      "data": {
        "code": "UNAUTHORIZED",
        "httpStatus": 401
      }
    }
  }
}

Missing Token ​

json
{
  "error": {
    "json": {
      "message": "No token provided",
      "code": -32001,
      "data": {
        "code": "UNAUTHORIZED",
        "httpStatus": 401
      }
    }
  }
}

Expired Token ​

json
{
  "error": {
    "json": {
      "message": "Invalid or expired token",
      "code": -32001,
      "data": {
        "code": "UNAUTHORIZED",
        "httpStatus": 401
      }
    }
  }
}

Best Practices ​

  1. Store tokens securely - Use httpOnly cookies or secure storage
  2. Refresh proactively - Refresh tokens before they expire
  3. Handle expiration - Redirect to login on 401 errors
  4. Use HTTPS - Always transmit tokens over HTTPS
  5. Clear on logout - Remove tokens from storage on logout

Client Implementation Example ​

JavaScript/TypeScript ​

typescript
// Login and store token
async function login(email: string, password: string) {
  const response = await fetch('https://api.itms.solutions/trpc/auth.login', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ json: { email, password } }),
  });

  const data = await response.json();
  const token = data.result.data.json.token;

  localStorage.setItem('authToken', token);
  return data.result.data.json.user;
}

// Make authenticated request
async function fetchSensors() {
  const token = localStorage.getItem('authToken');

  const response = await fetch('https://api.itms.solutions/trpc/sensors.getAllSensors', {
    headers: {
      'Authorization': `Bearer ${token}`,
    },
  });

  return response.json();
}

// Refresh token
async function refreshToken() {
  const token = localStorage.getItem('authToken');

  const response = await fetch('https://api.itms.solutions/trpc/auth.refreshToken', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
    },
  });

  const data = await response.json();
  const newToken = data.result.data.json.token;

  localStorage.setItem('authToken', newToken);
  return newToken;
}

tRPC Client ​

typescript
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
import superjson from 'superjson';

const client = createTRPCProxyClient({
  transformer: superjson,
  links: [
    httpBatchLink({
      url: 'https://api.itms.solutions/trpc',
      headers() {
        const token = localStorage.getItem('authToken');
        return {
          authorization: token ? `Bearer ${token}` : '',
        };
      },
    }),
  ],
});

// Login
const { token, user } = await client.auth.login.mutate({
  email: 'admin@itms.solutions',
  password: 'Admin@123',
});

// Authenticated request
const sensors = await client.sensors.getAllSensors.query();

SCS Smart City - Traffic, Gateway, Camera, and NVR Platform