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

Το Cliqer πραγματοποιεί έλεγχο ταυτότητας με ένα httpOnly cookie συνεδρίας (session_token), το οποίο εκδίδεται από το POST /api/auth/login. Τα προγράμματα περιήγησης το στέλνουν αυτόματα σε κάθε αίτημα· τα εργαλεία server-to-server το διατηρούν σε cookie jar. Οι ομάδες Studio 8K και Enterprise μπορούν επιπλέον να δημιουργούν κλειδιά API για πρόσβαση server-to-server, τα οποία αποστέλλονται ως Authorization: Bearer cliqer_<key>· δείτε την ενότητα Έλεγχος ταυτότητας με κλειδί API παρακάτω.
Μοντέλο συνεδρίας
| Διαπιστευτήριο | Πού βρίσκεται | Πώς αποκτάται |
|---|---|---|
Cookie συνεδρίας (session_token) | Cookie httpOnly και Secure στον host του Cliqer σας | Ορίζεται από το POST /api/auth/login και ανανεώνεται αυτόματα από τον διακομιστή |
Το cookie είναι HttpOnly, επομένως δεν είναι αναγνώσιμο από JavaScript. Η διάρκεια ζωής του ακολουθεί το TTL της συνεδρίας στον διακομιστή και ανανεώνεται διαφανώς κάθε φορά που καλείτε το GET /api/auth/me. Δεν υπάρχει ξεχωριστό endpoint ανανέωσης για να καλέσετε· για να διατηρείτε ενεργό έναν client που λειτουργεί για μεγάλο διάστημα, αρκεί να καλείτε περιοδικά το GET /api/auth/me.
Κύκλος ζωής συνεδρίας
Χρήση της συνεδρίας
Τα προγράμματα περιήγησης επισυνάπτουν το cookie αυτόματα. Για clients server-to-server, αποθηκεύστε το cookie που ορίζει η απόκριση σύνδεσης και στείλτε το στα επόμενα αιτήματα:
# Save the session cookie on login, then reuse it
curl -X POST "$BASE_URL/api/auth/login" \
-H "Content-Type: application/json" \
-c cookies.txt \
-d '{"email":"user@example.com","password":"your_password"}'
curl -X GET "$BASE_URL/api/auth/me" -b cookies.txt
// Same-origin $fetch sends the httpOnly cookie automatically.
// Cross-origin fetch must opt in with credentials: 'include'.
const me = await $fetch('/api/auth/me')
import requests
session = requests.Session() # persists the session cookie
session.post('$BASE_URL/api/auth/login',
json={'email': 'user@example.com', 'password': 'your_password'})
me = session.get('$BASE_URL/api/auth/me').json()
jar, _ := cookiejar.New(nil)
client := &http.Client{Jar: jar}
// Login stores the session cookie in the jar; later requests reuse it.
client.Post("$BASE_URL/api/auth/login", "application/json", body)
resp, _ := client.Get("$BASE_URL/api/auth/me")
$ch = curl_init('$BASE_URL/api/auth/login');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'email' => 'user@example.com', 'password' => 'your_password'
]));
curl_exec($ch);
// reqwest with cookie_store persists the session cookie across calls
let client = reqwest::Client::builder()
.cookie_store(true)
.build()?;
client.post("$BASE_URL/api/auth/login")
.json(&serde_json::json!({"email": "user@example.com", "password": "your_password"}))
.send().await?;
let me = client.get("$BASE_URL/api/auth/me").send().await?;
Έλεγχος ταυτότητας με κλειδί API
Οι ομάδες Studio 8K και Enterprise μπορούν να δημιουργούν κλειδιά API μακράς διάρκειας για πρόσβαση server-to-server, ως εναλλακτική λύση αντί να διατηρούν τα διαπιστευτήρια σύνδεσης ενός χρήστη. Δημιουργήστε και ανακαλέστε τα στον πίνακα ελέγχου, στην ενότητα Ομάδα → Κλειδιά API (/dash/team/api-keys)· για τη δημιουργία απαιτείται ο κάτοχος της ομάδας (ή ένας προσαρμοσμένος ρόλος στον οποίο έχει δοθεί η άδεια διαχείρισης κλειδιών API). Η διαχείριση κλειδιών είναι διαθέσιμη μόνο στα πλάνα Studio 8K και Enterprise.


Ένα κλειδί εμφανίζεται μία φορά, κατά τη δημιουργία του, στη μορφή cliqer_<prefix>_<secret>. Αποθηκεύστε το με ασφάλεια: δεν μπορεί να ανακτηθεί, οπότε αν χαθεί, ανακαλέστε το και δημιουργήστε νέο. Στείλτε το ως Bearer token σε οποιοδήποτε REST endpoint δέχεται συνεδρία:
curl -X GET "$BASE_URL/api/licenses/status?license_key=YOUR_LICENSE_KEY" \
-H "Authorization: Bearer cliqer_ab12cd34_your_secret_here"
Τα κλειδιά API λειτουργούν μόνο στα REST endpoints. Το WebSocket, συμπεριλαμβανομένου του ελέγχου διαφανειών, απαιτεί token συνεδρίας.
Το κλειδί πραγματοποιεί έλεγχο ταυτότητας ως ο χρήστης που το δημιούργησε, με εμβέλεια την ομάδα και το πλάνο του συγκεκριμένου χρήστη. Ένα ανακληθέν ή άγνωστο κλειδί επιστρέφει 401, ακριβώς όπως μια συνεδρία που λείπει. Τα endpoints που προορίζονται μόνο για διαχειριστές απορρίπτουν πάντα τα κλειδιά API με 403. Τα κλειδιά υπόκεινται στα ίδια όρια ρυθμού αιτημάτων με τα αιτήματα συνεδρίας.
Σύνδεση
Ανταλλάσσει τα διαπιστευτήρια του χρήστη με μια συνεδρία. Σε περίπτωση επιτυχίας, η απόκριση ορίζει το cookie session_token.
Endpoint: POST /api/auth/login
| Παράμετρος | Τύπος | Υποχρεωτική | Περιγραφή |
|---|---|---|---|
email | string | Ναι | Email χρήστη (γίνεται επίσης δεκτό όνομα χρήστη WordPress) |
password | string | Ναι | Κωδικός πρόσβασης χρήστη |
otp | string | Όχι | Κωδικός TOTP, όταν ο λογαριασμός χρησιμοποιεί εφαρμογή ελέγχου ταυτότητας |
email_otp | string | Όχι | PIN που αποστέλλεται μέσω email, όταν ο λογαριασμός χρησιμοποιεί 2FA μέσω email |
curl -X POST "$BASE_URL/api/auth/login" \
-H "Content-Type: application/json" \
-c cookies.txt \
-d '{"email":"user@example.com","password":"your_password"}'
interface LoginResponse {
data: {
expires: number | null // session lifetime in ms
}
}
const res: LoginResponse = await $fetch('/api/auth/login', {
method: 'POST',
body: { email: 'user@example.com', password: 'your_password' }
})
// The session_token cookie is set by the response; no token is in the body.
import requests
session = requests.Session()
data = {'email': 'user@example.com', 'password': 'your_password'}
res = session.post('$BASE_URL/api/auth/login', json=data)
# The session cookie now lives in `session`.
jar, _ := cookiejar.New(nil)
client := &http.Client{Jar: jar}
payload := map[string]string{"email": "user@example.com", "password": "your_password"}
body, _ := json.Marshal(payload)
client.Post("$BASE_URL/api/auth/login", "application/json", bytes.NewBuffer(body))
$ch = curl_init('$BASE_URL/api/auth/login');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'email' => 'user@example.com',
'password' => 'your_password'
]));
$response = curl_exec($ch);
use serde::Serialize;
#[derive(Serialize)]
struct LoginRequest { email: String, password: String }
let client = reqwest::Client::builder().cookie_store(true).build()?;
let response = client
.post("$BASE_URL/api/auth/login")
.json(&LoginRequest { email: "user@example.com".into(), password: "your_password".into() })
.send()
.await?;
Απόκριση (επιτυχία): ορίζει το cookie session_token και επιστρέφει τα μεταδεδομένα της συνεδρίας.
{
"data": {
"expires": 604800000
}
}
Απόκριση (απαιτείται 2FA): ένα σήμα ροής ελέγχου 200, όχι σφάλμα. Υποβάλετε ξανά το POST /api/auth/login με τα ίδια διαπιστευτήρια και επιπλέον το otp (εφαρμογή ελέγχου ταυτότητας) ή το email_otp (PIN μέσω email).
{
"requires_otp": true,
"method": "totp",
"email_sent": false
}
Το method είναι ένα από τα totp, email ή both. Για το email, ο διακομιστής στέλνει ένα PIN μέσω email και το email_sent δείχνει αν το email αυτό στάλθηκε. Ένας λογαριασμός both συνδέεται με τον κωδικό της εφαρμογής ελέγχου ταυτότητας (otp)· το PIN μέσω email δεν αποτελεί παράγοντα σύνδεσης για αυτόν.
401, όπως και ένας λανθασμένος ή ληγμένος κωδικός TOTP. Ένα λανθασμένο ή ληγμένο PIN μέσω email επιστρέφει επίσης 401 με το ίδιο μήνυμα που επιστρέφει ένας λανθασμένος κωδικός πρόσβασης. Ένα μέλος οργανισμού που απαιτεί single sign-on λαμβάνει 403 και πρέπει να συνδεθεί με SSO (δείτε τις Συχνές ερωτήσεις για το SSO).Ανανέωση συνεδρίας
Δεν υπάρχει ξεχωριστό endpoint ανανέωσης. Ο διακομιστής ανανεώνει το cookie session_token για εσάς: όταν μια συνεδρία πλησιάζει αρκετά στη λήξη της, το GET /api/auth/me απαντά με ένα νέο Set-Cookie μαζί με το προφίλ. Ένας client που διατηρεί cookie jar και καλεί περιοδικά το GET /api/auth/me παραμένει συνδεδεμένος επ' αόριστον, χωρίς επιπλέον εργασία.
Τρέχων χρήστης
Επιστρέφει το προφίλ του χρήστη που έχει περάσει τον έλεγχο ταυτότητας ή { "data": null } όταν δεν υπάρχει έγκυρη συνεδρία (λειτουργεί και για ανώνυμους χρήστες, δεν επιστρέφει ποτέ 401).
Endpoint: GET /api/auth/me
curl -X GET "$BASE_URL/api/auth/me" -b cookies.txt
const { data } = await $fetch('/api/auth/me')
if (data) console.log(data.email, data.is_admin)
me = session.get('$BASE_URL/api/auth/me').json()
resp, _ := client.Get("$BASE_URL/api/auth/me")
$ch = curl_init('$BASE_URL/api/auth/me');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
$response = curl_exec($ch);
let me = client.get("$BASE_URL/api/auth/me").send().await?;
Απόκριση:
{
"data": {
"id": "uuid",
"email": "user@example.com",
"first_name": "Jane",
"last_name": "Doe",
"role": "uuid",
"tfa_method": "none",
"is_admin": false
}
}
Αποσύνδεση
Τερματίζει τη συνεδρία του τρέχοντος cookie και το διαγράφει από το πρόγραμμα περιήγησης.
Endpoint: POST /api/auth/logout
curl -X POST "$BASE_URL/api/auth/logout" -b cookies.txt -c cookies.txt
await $fetch('/api/auth/logout', { method: 'POST' })
session.post('$BASE_URL/api/auth/logout')
req, _ := http.NewRequest("POST", "$BASE_URL/api/auth/logout", nil)
client.Do(req)
$ch = curl_init('$BASE_URL/api/auth/logout');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
curl_exec($ch);
client.post("$BASE_URL/api/auth/logout").send().await?;
Απόκριση:
{
"success": true
}
Βέλτιστες πρακτικές ασφάλειας
- Χρησιμοποιείτε μόνο HTTPS: το cookie συνεδρίας είναι
Secure· όλα τα αιτήματα πρέπει να χρησιμοποιούν TLS 1.2+. - Μη διαβάζετε ποτέ το cookie από JavaScript: είναι
HttpOnlyεκ σχεδιασμού· διατηρήστε το έτσι. - Ανανεώνετε προληπτικά: καλείτε το
GET /api/auth/meπριν λήξει η συνεδρία σε καρτέλες που μένουν ανοιχτές για πολύ· ο διακομιστής ανανεώνει το cookie για εσάς. - Αποσυνδεθείτε για ανάκληση: το
POST /api/auth/logoutτερματίζει αμέσως τη συνεδρία στην πλευρά του διακομιστή. - Αποθηκεύετε διαπιστευτήρια, όχι συνεδρίες: οι ενσωματώσεις server-to-server πρέπει να διατηρούν τα διαπιστευτήρια σύνδεσης σε διαχειριστή μυστικών και να δημιουργούν ξανά συνεδρία, χωρίς ποτέ να αποθηκεύουν το cookie στον πηγαίο κώδικα.