Authentication στο REST API
Το JWT API contract για Postman, curl, mobile clients, scripts και debugging του browser login.
Endpoints
| Method | Endpoint | Authentication | Σκοπός |
|---|---|---|---|
| POST | /api/v1/auth/token/ | Κανένα | Ανταλλαγή username/password με access και refresh tokens |
| POST | /api/v1/auth/token/refresh/ | Refresh token σε JSON | Περιστροφή refresh token και έκδοση νέου access token |
| GET | /api/v1/auth/me/ | Access Bearer token | Επιστροφή του τρέχοντος χρήστη και των Organizations που βλέπει |
| GET/PATCH | /api/v1/auth/me/profile/ | Access Bearer token | Προβολή ή συμπλήρωση του προσωπικού onboarding profile |
| GET/PATCH | /api/v1/auth/me/settings/ | Access Bearer token | Προβολή ή αλλαγή email και profile settings |
| GET | /api/v1/auth/me/export/ | Access Bearer token | Λήψη export των προσωπικών δεδομένων του χρήστη |
| POST | /api/v1/auth/me/delete/ | Access Bearer token | Διαγραφή account μετά από ελέγχους password και ownership |
| POST | /api/v1/auth/me/password/ | Access Bearer token | Αλλαγή του τρέχοντος password |
| POST | /api/v1/auth/password-reset/ | Κανένα | Αίτημα επαναφοράς password με γενική απάντηση |
| POST | /api/v1/auth/password-reset/<uidb64>/<token>/ | Reset token στο URL | Ορισμός νέου password από έγκυρο reset link |
| POST | /api/v1/auth/logout/ | Access Bearer token | Blacklist του refresh token που υποβάλλεται |
| GET | /api/v1/setup/ | Κανένα | Έλεγχος αν είναι διαθέσιμο το first-run setup |
| POST | /api/v1/setup/ | Server-side setup token σε JSON | Δημιουργία πρώτου admin, workspace και προαιρετικού SMTP account |
| POST | /api/v1/setup/smtp-test/ | Server-side setup token σε JSON | Αποστολή δοκιμαστικού email με SMTP settings που δεν έχουν αποθηκευτεί |
| POST | /api/v1/organizations/ | Installation admin Bearer token | Δημιουργία shared workspace· διαφορετικός Owner λαμβάνει email invitation |
| GET | /api/v1/organizations/provisioning/ | Authenticated Bearer token | Προβολή των pending handoffs· Installation admins βλέπουν όλα |
| POST/DELETE | /api/v1/organizations/provisioning/<organization_id>/ | Provisioning creator ή Installation admin Bearer token | Resend invitation Owner ή ακύρωση pending workspace |
| GET/POST | /api/v1/organizations/<organization_id>/invitations/ | Owner/Admin Bearer token | Προβολή invitation history ή αποστολή νέας invitation |
| DELETE | /api/v1/organizations/<organization_id>/invitations/<invitation_id>/ | Owner/Admin Bearer token | Ανάκληση invitation και ακύρωση του link |
| POST | /api/v1/organizations/<organization_id>/invitations/<invitation_id>/resend/ | Owner/Admin Bearer token | Ανάκληση προηγούμενων links και αποστολή νέας invitation επτά ημερών |
| GET | /api/v1/organizations/<organization_id>/members/ | Owner/Admin Bearer token | Προβολή μελών· απευθείας δημιουργία membership δεν υποστηρίζεται |
| GET/POST | /api/v1/organizations/installation-admin-invitations/ | Installation admin Bearer token | Προβολή IT admins και pending invitations ή πρόσκληση νέου IT admin |
| GET | /api/v1/installation-admin-invitations/<token>/ | Invitation token στο URL | Preview invitation για IT admin |
| POST | /api/v1/installation-admin-invitations/<token>/accept/ | Invitation token· και Bearer token για υπάρχοντες χρήστες | Αποδοχή μία φορά και ανάθεση ρόλου Installation admin |
| GET | /api/v1/invitations/<token>/ | Invitation token στο URL | Preview έγκυρης invitation |
| POST | /api/v1/invitations/<token>/accept/ | Invitation token· και Bearer token για υπάρχοντες χρήστες | Αποδοχή μία φορά και σύνδεση στο workspace |
Το Django admin στο /admin/ εξακολουθεί να χρησιμοποιεί session authentication. Τα κανονικά REST requests δεν χρησιμοποιούν browser sessions.
First-run setup
Το setup endpoint είναι ξεχωριστό bootstrap flow, όχι δημόσια εγγραφή. Το GET επιστρέφει μόνο { "available": true|false } και δεν αποκαλύπτει το token. Το POST γίνεται δεκτό μόνο αν έχει οριστεί server-side BUBLLIO_SETUP_TOKEN με τουλάχιστον 32 χαρακτήρες, οι πίνακες users και Organizations είναι άδειοι και το setup δεν έχει ολοκληρωθεί.
Το request περιλαμβάνει setup_token, username, email, password, organization_name και organization_slug. Το προαιρετικό smtp μπορεί να περιλαμβάνει τα πεδία του email account, μαζί με το password του. Η ρύθμιση SMTP απαιτεί έγκυρο server-side BUBLLIO_EMAIL_ENCRYPTION_KEYS. Σε επιτυχία επιστρέφεται 201 και το setup κλείνει οριστικά για τη συγκεκριμένη database. Υπάρχει rate limit στα setup POST requests. Για την πλήρη διαδικασία, δείτε το Getting Started.
Οι απλοί χρήστες δεν μπορούν να δημιουργήσουν personal ή shared workspaces. Τα υπάρχοντα personal workspaces παραμένουν απομονωμένα· η δημιουργία νέου workspace προορίζεται για Installation admins.
Το SMTP test request περιλαμβάνει setup_token, recipient (έγκυρη διεύθυνση email) και το ίδιο smtp object που δέχεται το setup. Ανοίγει σύνδεση SMTP, κάνει authentication και στέλνει ένα δοκιμαστικό μήνυμα. Δεν αποθηκεύει email account και δεν ολοκληρώνει το setup. Η απάντηση 200 σημαίνει ότι ο SMTP server αποδέχτηκε το μήνυμα, όχι ότι παραδόθηκε στα εισερχόμενα του παραλήπτη. Αποτυχία δικτύου ή authentication επιστρέφει γενικό 502, χωρίς να αποκαλύπτει credentials. Το endpoint απενεργοποιείται μόλις ολοκληρωθεί το setup.
Εγγραφή μόνο με invitation
Δεν υπάρχει γενικό public signup endpoint. Owner ή Admin δημιουργεί invitation κάτω από το URL του Organization με { "email": "person@example.com", "role": "member" }. Το owner δεν μπορεί να ανατεθεί μέσω της συνηθισμένης invitation· οι αρχικές προσκλήσεις Owner γίνονται από το provisioning flow. Μόνο Owner μπορεί να προσκαλέσει admin. Για την αποστολή απαιτείται το ενεργό default SMTP account του Organization ή το fallback SMTP της εγκατάστασης. Το link λήγει σε επτά ημέρες. Ορίστε το BUBLLIO_APP_URL στο public origin του React app, ώστε τα links να δείχνουν στη σωστή εγκατάσταση.
Ο παραλήπτης ανοίγει το link για να δει το workspace και τον ρόλο της invitation. Νέος χρήστης στέλνει username και password στο accept/· ο server ορίζει το invited email και επιστρέφει JWT tokens μαζί με organization_id. Υπάρχων χρήστης συνδέεται και στέλνει κενό JSON body με το Bearer token του. Το email του account πρέπει να ταιριάζει με την invitation. Η αποδοχή δημιουργεί membership μόνο στο συγκεκριμένο workspace και καταναλώνει το link· επανάληψη ή λήξη επιστρέφει 404.
Ένα συνηθισμένο workspace membership δεν επιτρέπει τη δημιουργία άλλου Organization. Μόνο Installation admin δημιουργεί workspace. Αν το owner_email ανήκει σε άλλο άτομο, το workspace μένει κρυφό μέχρι να αποδεχτεί ο Owner· τότε αφαιρείται και το προσωρινό membership του Installation admin. Για το handoff και την ανάκτηση workspace, δείτε τον οδηγό ρόλων.
Το invitation history έχει ένα από τα status pending, accepted, expired ή revoked. Η λήξη υπολογίζεται από το expires_at, χωρίς background job. Τα resend και revoke actions περιορίζονται στο αντίστοιχο Organization· οι Admins δεν διαχειρίζονται invitations για τον ρόλο Admin.
Οι invitations για IT admins χρησιμοποιούν το fallback SMTP της εγκατάστασης και το ξεχωριστό browser route /installation-admin-invite/<token>. Υπάρχων χρήστης συνδέεται με το invited email· νέος χρήστης συμπληρώνει στοιχεία εγγραφής. Με την αποδοχή αποκτά Django superuser/staff status, χωρίς workspace membership. Δώστε αυτό το προνόμιο μόνο σε έμπιστους operators, καθώς το Django /admin/ παρέχει ευρεία πρόσβαση εκτός του κανονικού tenant-scoped API.
Κατά την εγγραφή, νέοι προσκεκλημένοι χρήστες συμπληρώνουν display name και προαιρετικά first/last name, ημερομηνία γέννησης, timezone και locale. Υπάρχοντες χρήστες μπορούν να συμπληρώσουν ή να ενημερώσουν το profile τους μέσω /api/v1/auth/me/profile/. Τα account settings στο /api/v1/auth/me/settings/ καλύπτουν αλλαγές email και profile· το /api/v1/auth/me/password/ αλλάζει το password μετά από authentication. Τα password reset requests επιστρέφουν την ίδια γενική απάντηση είτε υπάρχει το email είτε όχι. Τα reset links χρησιμοποιούνται μία φορά και λήγουν όταν αλλάξει το password.
Μετά την αρχικοποίηση της εγκατάστασης, οι χρήστες μπορούν ρητά να δημιουργήσουν ένα ιδιωτικό personal workspace. Τα shared/team workspaces είναι ξεχωριστά Organizations και εμφανίζονται μόνο μέσω αποδεκτού membership. Τα personal workspaces δεν μπορούν να προσκαλέσουν ή να προσθέσουν μέλη, ούτε να διαγραφούν. Όταν μια ομάδα χρειάζεται κοινά CRM data, Installation admin δημιουργεί κανονικό workspace ή αναθέτει αυτό το δικαίωμα σε επιλεγμένο account.
Τα account settings περιλαμβάνουν επίσης ροή export προσωπικών δεδομένων και διαγραφής account. Το export περιέχει μόνο account, profile και membership metadata — ποτέ tokens, passwords, SMTP secrets ή CRM data workspace. Για διαγραφή απαιτείται το τρέχον password και η ακριβής επιβεβαίωση DELETE. Owner πρέπει πρώτα να μεταβιβάσει την ιδιοκτησία του workspace.
Login με curl
Δημιουργήστε πρώτα έναν τοπικό χρήστη:
uv run python src/manage.py createsuperuserΖητήστε το ζεύγος tokens:
curl -X POST http://127.0.0.1:8000/api/v1/auth/token/ \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"your-password"}'Επιτυχής απάντηση:
{
"refresh": "<long-refresh-token>",
"access": "<short-lived-access-token>"
}Μην κάνετε commit καμία από τις δύο τιμές. Το access token χρησιμοποιείται στα API requests· το refresh token χρησιμοποιείται μόνο για έκδοση νέου ζεύγους ή για logout.
Κλήση authenticated endpoint
curl http://127.0.0.1:8000/api/v1/auth/me/ \
-H "Authorization: Bearer $ACCESS_TOKEN"Η απάντηση περιλαμβάνει τα Organizations που βλέπει ο χρήστης. Κάθε Organization μπορεί να έχει διαφορετικό current_user_role, καθώς το membership περιορίζεται ανά Organization.
Refresh και rotation
curl -X POST http://127.0.0.1:8000/api/v1/auth/token/refresh/ \
-H 'Content-Type: application/json' \
-d '{"refresh":"<refresh-token>"}'Το refresh rotation είναι ενεργό. Αν η απάντηση περιέχει νέο refresh, ο client πρέπει να αντικαταστήσει το παλιό token. Το παλιό μπαίνει σε blacklist, οπότε η επόμενη ανανέωση θα αποτύχει αν συνεχίσετε να το χρησιμοποιείτε.
Logout
curl -X POST http://127.0.0.1:8000/api/v1/auth/logout/ \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"refresh":"<refresh-token>"}'Όταν το refresh token μπει σε blacklist, το endpoint επιστρέφει 204 No Content. Ο client πρέπει να καθαρίζει τοπικά τα tokens ακόμη κι αν αποτύχει το network request, ώστε το UI να γίνει αμέσως ιδιωτικό.
Status codes
200: επιτυχές token, refresh ή request τρέχοντος χρήστη.204: επιτυχές logout.400: λανθασμένο ή ελλιπές refresh token.401: authentication που λείπει, έληξε, δεν είναι έγκυρο ή έχει ανακληθεί.404: ο χρήστης είναι authenticated αλλά δεν έχει πρόσβαση σε tenant ή resource. Έτσι δεν αποκαλύπτεται αν υπάρχει Organization στο οποίο δεν έχει πρόσβαση.
Συμπεριφορά του browser client
Ο επίσημος React client υλοποιεί αυτό το contract στα frontend/src/services/api.ts και frontend/src/features/auth/hooks/useAuth.tsx. Το Axios προσθέτει Bearer header και επαναλαμβάνει μία αποτυχημένη κλήση μετά το refresh. Το Zustand αποθηκεύει τα tokens στο sessionStorage της ίδιας καρτέλας: reload διατηρεί το session, ενώ το logout το καθαρίζει.
Σημειώσεις ασφαλείας
- Χρησιμοποιείτε HTTPS εκτός local development.
- Μην αποθηκεύετε JWTs στο source control, σε Postman exports με πραγματικές τιμές, στα logs ή σε μεταβλητές
VITE_*. - Το starter αποστέλλει το refresh token σε JSON και το αποθηκεύει σε
sessionStorage, το οποίο είναι προσβάσιμο από JavaScript. Γι’ αυτό η προστασία από XSS είναι απαραίτητη. Production browser deployment μπορεί να επιλέξει refresh token σε HttpOnly cookie, αλλά χρειάζεται προσεκτική ρύθμιση CSRF και cookies. - Το Django επιβάλλει authorization στο API. Frontend route guards και κρυμμένα κουμπιά δεν αποτελούν μηχανισμό ασφαλείας.
