Μετάβαση στο περιεχόμενο

Έλεγχος ταυτότητας

Το SMSBAT ChatHub API χρησιμοποιεί ένα σύστημα ελέγχου ταυτότητας δύο επιπέδων που βασίζεται σε διακριτικά JWT με εταιρικά διακριτικά και διακριτικά χειριστή.

Ροή ελέγχου ταυτότητας

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]

Εταιρικό διακριτικό

Τα εταιρικά διακριτικά παρέχουν πρόσβαση σε επίπεδο οργανισμού στο ChatHub API.

Λήψη εταιρικού διακριτικού

Τελικό σημείο: POST /api/company/get-token

Αίτημα:

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

Σώμα αιτήματος:

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

Απάντηση:

"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"

Η απάντηση είναι μια συμβολοσειρά διακριτικού JWT.

Χρησιμοποιήστε εταιρικό διακριτικό

Συμπεριλάβετε το εταιρικό διακριτικό στα αιτήματα API χρησιμοποιώντας μία από τις δύο μεθόδους:

Μέθοδος 1: Κεφαλίδα εξουσιοδότησης (Συνιστάται)

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

Μέθοδος 2: X-Authorization-Key Header

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

Διακριτικό χειριστή

Τα διακριτικά χειριστή παρέχουν πρόσβαση για συγκεκριμένο χρήστη για μεμονωμένους χειριστές μέσα σε έναν οργανισμό.

Αποκτήστε το διακριτικό χειριστή

Τελικό σημείο: POST /api/operator/get-token

Αίτημα:

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

Σώμα αιτήματος:

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

Παράμετροι:

Παράμετρος Τύπος Απαιτείται Περιγραφή
id ακέραιος Ναι Αναγνωριστικό χειριστή
«λήγει στο» συμβολοσειρά (ISO 8601) Ναι Ημερομηνία και ώρα λήξης του διακριτικού (μέγιστο 24 ώρες από τώρα)

Σημαντικό: Η μέγιστη διάρκεια ζωής του διακριτικού είναι 24 ώρες. Η παράμετρος "expiresAt" δεν μπορεί να υπερβαίνει τις 24 ώρες στο μέλλον.

Απάντηση:

"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcGVyYXRvcl9pZCI6MTIzLCJleHAiOjE3Mzc0MTI3OTl9.example_signature"

Χρησιμοποιήστε το διακριτικό χειριστή

Συμπεριλάβετε το διακριτικό χειριστή στα αιτήματα API:

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

Επικύρωση διακριτικού

Βεβαιωθείτε ότι ένα διακριτικό εξακολουθεί να ισχύει πριν το χρησιμοποιήσετε.

Τελικό σημείο: POST /api/operator/validate-token

Αίτημα:

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

Σώμα αιτήματος:

{
  "token": "string"
}

Απάντηση (Έγκυρο διακριτικό):

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

Απάντηση (Μη έγκυρο διακριτικό):

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

Λήξη διακριτικού

Εταιρικά διακριτικά

  • Χωρίς ρητή λήξη στο API
  • Επικοινωνήστε με τον διαχειριστή του λογαριασμού σας για πολιτικές κύκλου ζωής διακριτικών
  • Περιστρέψτε τα κουπόνια περιοδικά για ασφάλεια

Διακριτικά χειριστή

  • Ορίστηκε λήξη κατά την αίτηση διακριτικού (παράμετρος «expiresAt»)
  • Επικυρώστε τα tokens πριν από τη χρήση
  • Ζητήστε νέα διακριτικά πριν τη λήξη

Παραδείγματα Εφαρμογής

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');

Βέλτιστες πρακτικές

Αποθήκευση διακριτικών

  • ✅ Αποθηκεύστε τα διακριτικά με ασφάλεια (κρυπτογραφημένη βάση δεδομένων, διαχειριστής μυστικών)
  • ✅ Μην δεσμεύετε ποτέ διακριτικά στον έλεγχο έκδοσης
  • ✅ Χρησιμοποιήστε μεταβλητές περιβάλλοντος για διαπιστευτήρια
  • ❌ Μην αποθηκεύετε διακριτικά σε απλό κείμενο
  • ❌ Μην εκθέτετε διακριτικά σε κώδικα από την πλευρά του πελάτη

Περιστροφή διακριτικού

  • Εναλλαγή εταιρικών μάρκες περιοδικά (κάθε 3-6 μήνες)
  • Ορίστε εύλογη λήξη για τα διακριτικά χειριστή (7-30 ημέρες)
  • Εφαρμογή αυτόματης ανανέωσης διακριτικού πριν από τη λήξη
  • Ανάκληση διακριτικών όταν φεύγουν οι χειριστές

Χειρισμός σφαλμάτων

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

Επικύρωση διακριτικού

Να επικυρώνετε πάντα τα διακριτικά πριν από κρίσιμες λειτουργίες:

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

Θέματα ασφαλείας

Μόνο HTTPS

Να χρησιμοποιείτε πάντα το HTTPS κατά την αποστολή αιτημάτων ελέγχου ταυτότητας:

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

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

Token Scope

Χρησιμοποιήστε το κατάλληλο διακριτικό για κάθε λειτουργία:

  • Company Token: Διαχείριση οργανισμού, δημιουργία χειριστή
  • Operator Token: Λειτουργίες συνομιλίας, διαχείριση μηνυμάτων

Περιορισμός ποσοστού

Εφαρμογή περιορισμού ρυθμού για αιτήματα ελέγχου ταυτότητας:

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

Αντιμετώπιση προβλημάτων

401 Μη εξουσιοδοτημένο

  • Επαληθεύστε ότι τα διαπιστευτήρια είναι σωστά
  • Το διακριτικό επιταγής δεν έχει λήξει
  • Βεβαιωθείτε ότι το διακριτικό περιλαμβάνεται στις κεφαλίδες αιτημάτων
  • Επικύρωση μορφής διακριτικού

403 Απαγορεύεται

  • Επαληθεύστε ότι το διακριτικό έχει απαιτούμενα δικαιώματα
  • Ελέγξτε εάν χρησιμοποιείτε τον σωστό τύπο διακριτικού (εταιρεία έναντι χειριστή)
  • Βεβαιωθείτε ότι το διακριτικό δεν έχει ανακληθεί

Token έληξε

  • Ζητήστε νέο διακριτικό
  • Εφαρμογή αυτόματης ανανέωσης διακριτικού
  • Ορίστε κατάλληλους χρόνους λήξης

Επόμενα βήματα