Keri sisuni

Autentimine

SMSBAT ChatHub API kasutab kahetasemelist JWT märgipõhist autentimissüsteemi koos ettevõtte märkide ja operaatori märkidega.

Autentimisvoog

graph TD
    A[Login Credentials] --> B[Get Company Token]
    B --> C[Use Company Token]
    C --> D[Get Operator Token]
    D --> E[Use Operator Token]
    E --> F[Validate Token]

Ettevõtte tunnus

Ettevõtte märgid pakuvad organisatsiooni tasemel juurdepääsu ChatHubi API-le.

Hankige ettevõtte tunnus

Lõpp-punkt: POST /api/ettevõte/get-token

Taotlus:

curl -X POST https://chatapi.smsbat.com/api/company/get-token \
  -H "Content-Type: application/json" \
  -d '{
    "login": "your-company-login",
    "password": "your-company-password"
  }'

Taotluse sisu:

{
  "login": "string",
  "password": "string"
}

Vastus:

"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"

Vastuseks on JWT märgistring.

Kasutage ettevõtte märki

Lisage API taotlustesse ettevõtte tunnus, kasutades ühte kahest meetodist.

1. meetod: volituse päis (soovitatav)

curl -X GET https://chatapi.smsbat.com/api/company/organization \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

2. meetod: X-Authorization-Key päis

curl -X GET https://chatapi.smsbat.com/api/company/organization \
  -H "X-Authorization-Key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Operaator Token

Operaatortokenid pakuvad kasutajapõhist juurdepääsu organisatsiooni üksikutele operaatoritele.

Hankige operaatori tunnus

Lõpp-punkt: "POST /api/operator/get-token".

Taotlus:

curl -X POST https://chatapi.smsbat.com/api/operator/get-token \
  -H "Authorization: Bearer {company-token}" \
  -H "Content-Type: application/json" \
  -d '{
    "id": 123,
    "expiresAt": "2025-12-31T23:59:59Z"
  }'

Taotluse sisu:

{
  "id": 0,
  "expiresAt": "2025-01-20T14:33:34.147Z"
}

Parameetrid:

Parameeter Tüüp Nõutav Kirjeldus
"id" täisarv Jah Operaator ID
aegub string (ISO 8601) Jah Žetooni aegumiskuupäev ja kellaaeg (maksimaalselt 24 tunni pärast)

Tähtis. Tokeni maksimaalne kasutusiga on 24 tundi. Parameeter „expiresAt” ei tohi olla pikem kui 24 tundi tulevikus.

Vastus:

"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcGVyYXRvcl9pZCI6MTIzLCJleHAiOjE3Mzc0MTI3OTl9.example_signature"

Kasutage operaatorimärki

Lisage API taotlustesse operaatori luba:

curl -X GET https://chatapi.smsbat.com/api/operator \
  -H "Authorization: Bearer {operator-token}"

Token Validation

Enne selle kasutamist veenduge, et märk on endiselt kehtiv.

Lõpp-punkt: "POST /api/operator/validate-token".

Taotlus:

curl -X POST https://chatapi.smsbat.com/api/operator/validate-token \
  -H "Authorization: Bearer {company-token}" \
  -H "Content-Type: application/json" \
  -d '{
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  }'

Taotluse sisu:

{
  "token": "string"
}

Vastus (kehtiv tunnus):

{
  "isValid": true,
  "operatorId": 123,
  "clientId": 0,
  "expiresAt": "2025-12-31T23:59:59Z",
  "error": null
}

Vastus (kehtetu tunnus):

{
  "isValid": false,
  "error": "Invalid token"
}

Tokeni aegumine

Ettevõtte märgid

  • API-s puudub selgesõnaline aegumine
  • Võtke oma kontohalduriga ühendust, et saada teavet märgi elutsükli eeskirjade kohta
  • Turvalisuse huvides vahetage märke perioodiliselt

Operaatori märgid

  • Aegumine määratud loa taotlemisel (parameeter "expiresAt")
  • Enne kasutamist kinnitage märgid
  • taotlege uusi märke enne aegumist

Rakendusnäited

Python

import requests
from datetime import datetime, timedelta

class ChatHubAuth:
    def __init__(self, base_url):
        self.base_url = base_url
        self.company_token = None
        self.operator_tokens = {}

    def get_company_token(self, login, password):
        """Get company authentication token"""
        response = requests.post(
            f"{self.base_url}/api/company/get-token",
            json={"login": login, "password": password}
        )
        response.raise_for_status()
        self.company_token = response.json()
        return self.company_token

    def get_operator_token(self, operator_id, expires_days=30):
        """Get operator token with expiration"""
        expires_at = (
            datetime.utcnow() + timedelta(days=expires_days)
        ).isoformat() + "Z"

        response = requests.post(
            f"{self.base_url}/api/operator/get-token",
            headers={"Authorization": f"Bearer {self.company_token}"},
            json={"id": operator_id, "expiresAt": expires_at}
        )
        response.raise_for_status()

        token = response.json()
        self.operator_tokens[operator_id] = token
        return token

    def validate_token(self, token):
        """Validate if token is still valid"""
        response = requests.post(
            f"{self.base_url}/api/operator/validate-token",
            headers={"Authorization": f"Bearer {self.company_token}"},
            json={"token": token}
        )
        response.raise_for_status()
        return response.json()

# Usage
auth = ChatHubAuth("https://chatapi.smsbat.com")

# Get company token
company_token = auth.get_company_token("login", "password")

# Get operator token
operator_token = auth.get_operator_token(operator_id=123, expires_days=30)

# Validate token
is_valid = auth.validate_token(operator_token)
print(f"Token valid: {is_valid['valid']}")

JavaScript (Node.js)

const axios = require('axios');

class ChatHubAuth {
  constructor(baseUrl) {
    this.baseUrl = baseUrl;
    this.companyToken = null;
    this.operatorTokens = {};
  }

  async getCompanyToken(login, password) {
    const response = await axios.post(
      `${this.baseUrl}/api/company/get-token`,
      { login, password }
    );

    this.companyToken = response.data;
    return this.companyToken;
  }

  async getOperatorToken(operatorId, expiresDays = 30) {
    const expiresAt = new Date(
      Date.now() + expiresDays * 24 * 60 * 60 * 1000
    ).toISOString();

    const response = await axios.post(
      `${this.baseUrl}/api/operator/get-token`,
      { id: operatorId, expiresAt },
      {
        headers: {
          Authorization: `Bearer ${this.companyToken}`
        }
      }
    );

    const token = response.data;
    this.operatorTokens[operatorId] = token;
    return token;
  }

  async validateToken(token) {
    const response = await axios.post(
      `${this.baseUrl}/api/operator/validate-token`,
      { token },
      {
        headers: {
          Authorization: `Bearer ${this.companyToken}`
        }
      }
    );

    return response.data;
  }
}

// Usage
const auth = new ChatHubAuth('https://chatapi.smsbat.com');

async function authenticate() {
  // Get company token
  const companyToken = await auth.getCompanyToken('login', 'password');

  // Get operator token
  const operatorToken = await auth.getOperatorToken(123, 30);

  // Validate token
  const validation = await auth.validateToken(operatorToken);
  console.log('Token valid:', validation.isValid);
}

authenticate();

PHP

<?php

class ChatHubAuth {
    private $baseUrl;
    private $companyToken;
    private $operatorTokens = [];

    public function __construct($baseUrl) {
        $this->baseUrl = $baseUrl;
    }

    public function getCompanyToken($login, $password) {
        $ch = curl_init($this->baseUrl . '/api/company/get-token');

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json'
        ]);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
            'login' => $login,
            'password' => $password
        ]));

        $response = curl_exec($ch);
        curl_close($ch);

        $this->companyToken = json_decode($response);
        return $this->companyToken;
    }

    public function getOperatorToken($operatorId, $expiresDays = 30) {
        $expiresAt = date(
            'Y-m-d\TH:i:s\Z',
            time() + ($expiresDays * 24 * 60 * 60)
        );

        $ch = curl_init($this->baseUrl . '/api/operator/get-token');

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Authorization: Bearer ' . $this->companyToken
        ]);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
            'id' => $operatorId,
            'expiresAt' => $expiresAt
        ]));

        $response = curl_exec($ch);
        curl_close($ch);

        $token = json_decode($response);
        $this->operatorTokens[$operatorId] = $token;
        return $token;
    }

    public function validateToken($token) {
        $ch = curl_init($this->baseUrl . '/api/operator/validate-token');

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Authorization: Bearer ' . $this->companyToken
        ]);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
            'token' => $token
        ]));

        $response = curl_exec($ch);
        curl_close($ch);

        return json_decode($response, true);
    }
}

// Usage
$auth = new ChatHubAuth('https://chatapi.smsbat.com');

// Get company token
$companyToken = $auth->getCompanyToken('login', 'password');

// Get operator token
$operatorToken = $auth->getOperatorToken(123, 30);

// Validate token
$validation = $auth->validateToken($operatorToken);
echo "Token valid: " . ($validation['isValid'] ? 'Yes' : 'No');

Parimad tavad

Tokenite salvestusruum

  • ✅ Hoidke žetoone turvaliselt (krüpteeritud andmebaas, saladuste haldur)
  • ✅ Ärge kunagi lisage žetoone versioonikontrollile
  • ✅ Kasutage mandaatide jaoks keskkonnamuutujaid
  • ❌ Ärge hoidke märke lihttekstina
  • ❌ Ärge avaldage kliendipoolses koodis märke

Token Rotation

  • Vahetage ettevõtte märke perioodiliselt (iga 3–6 kuu järel)
  • Määrake operaatori žetoonidele mõistlik aegumistähtaeg (7–30 päeva)
  • Rakendage märgi automaatne värskendamine enne aegumist
  • Tühistage märgid, kui operaatorid lahkuvad

Vigade käsitlemine

async function authenticateWithRetry(login, password, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      return await getCompanyToken(login, password);
    } catch (error) {
      if (error.response?.status === 401) {
        throw new Error('Invalid credentials');
      }

      if (i === retries - 1) throw error;

      // Wait before retry
      await new Promise(resolve =>
        setTimeout(resolve, Math.pow(2, i) * 1000)
      );
    }
  }
}

Token Validation

Kontrollige märgid alati enne kriitilisi toiminguid:

async function performSecureOperation(token, operation) {
  // Validate token first
  const validation = await validateToken(token);

  if (!validation.isValid) {
    throw new Error('Token expired or invalid');
  }

  // Proceed with operation
  return await operation();
}

Turvakaalutlused

Ainult HTTPS

Kasutage autentimistaotluste saatmisel alati HTTPS-i:

// ✅ Correct
const baseUrl = 'https://chatapi.smsbat.com';

// ❌ Wrong - never use HTTP for authentication
const baseUrl = 'http://api.chathub.smsbat.com';

Märgi ulatus

Kasutage iga toimingu jaoks sobivat tunnust:

  • Ettevõtte tunnus: organisatsiooni juhtimine, operaatori loomine
  • Operaatori tunnus: vestlustoimingud, sõnumite käsitlemine

Rate Limiting

Rakendage autentimistaotluste kiiruse piirang:

class RateLimitedAuth {
  constructor() {
    this.lastRequest = 0;
    this.minInterval = 1000; // 1 second between requests
  }

  async getToken(login, password) {
    const now = Date.now();
    const timeSinceLastRequest = now - this.lastRequest;

    if (timeSinceLastRequest < this.minInterval) {
      await new Promise(resolve =>
        setTimeout(resolve, this.minInterval - timeSinceLastRequest)
      );
    }

    this.lastRequest = Date.now();
    return await makeAuthRequest(login, password);
  }
}

Veaotsing

401 Volitamata

  • Kontrollige, kas mandaadid on õiged
  • Tšeki tunnus ei ole aegunud
  • Veenduge, et loa oleks lisatud päringu päistesse
  • Kinnitage märgi vorming

403 Keelatud

  • Kontrollige, kas märgil on vajalikud õigused
  • Kontrollige, kas kasutate õiget märgi tüüpi (ettevõte vs operaator)
  • Veenduge, et luba poleks tühistatud

Token aegunud

  • Uue märgi taotlemine
  • Rakendage märgi automaatne värskendamine
  • Määrake sobivad aegumisajad

Järgmised sammud