Tài liệu này mô tả model request và response của các endpoint /v1/auth/*. Nguồn chuẩn là proto/auth/authentication.proto và proto/justo/identity/model.proto. JSON dùng tên field camelCase theo json_name trong proto.
- Type: HTTP/1.1 (REST APIs)
- SSL: v1.3 trở lên
- Connection: Client to Server - “keep-alive”
- Method: POST (trừ khi endpoint ghi khác)
- Headers:
- Content-Type:
application/json; charset=utf-8
- X-Api-Tracking-ID: <device-identify-string>
- X-Api-Request-ID: <unique-string>
- X-Api-Idempotency-Key: <unique-string>
- X-Api-Timestamp: <unix-timestamp>
- X-Api-Session-Id: <session-id> (bắt buộc với các endpoint sau
init-session, trừ init-session và attestation)
| Endpoint |
Method |
Request |
Payload |
/v1/attestation/get-challenge |
GET |
- |
GetChallengePayload |
/v1/auth/init-session |
POST |
InitSessionRequest |
InitSessionPayload |
/v1/auth/verify-email |
POST |
VerifyEmailRequest |
VerifyEmailPayload |
/v1/auth/verify-otp-email |
POST |
VerifyOtpEmailRequest |
VerifyOtpEmailPayload |
/v1/auth/verify-phone |
POST |
VerifyPhoneRequest |
VerifyPhonePayload |
/v1/auth/verify-otp-phone |
POST |
VerifyOtpPhoneRequest |
VerifyOtpPhonePayload |
/v1/auth/register |
POST |
RegisterRequest |
RegisterPayload |
/v1/auth/register-basic-info |
POST |
RegisterBasicInfoRequest |
RegisterBasicInfoPayload |
/v1/auth/create-pin-code |
POST |
CreatePinCodeRequest |
CreatePinCodePayload |
/v1/auth/verify-password |
POST |
VerifyPasswordRequest |
VerifyPasswordPayload |
/v1/auth/social/nonce |
POST |
Không có body |
SocialNoncePayload |
/v1/auth/social-login |
POST |
SocialLoginRequest |
SocialLoginPayload |
/v1/auth/logout |
POST |
Không có body |
- |
Mọi response dùng justo.common.StandardResponse gồm code, message và payload. Bảng mã lỗi xem tại Mã lỗi.
Ba trường dễ bị nhầm vì đều mang giá trị kiểu thuật toán. Chúng có ý nghĩa khác nhau:
| Trường |
Nơi xuất hiện |
Ý nghĩa |
Giá trị hợp lệ |
algorithm |
clientJwtCert, clientSensitiveJwtCert, clientP256Cert, claim algorithm của SessionClaim |
Loại khóa |
P-256 |
publicKey.crv |
JWK trong request |
Đường cong |
P-256 |
alg |
Header JWT: jwtToken, challengeJwt, JWT client |
Thuật toán chữ ký |
EdDSA (Preshare), ES256 (JWT client) |
Lưu ý: algorithm không phải header alg của JWT. Đặt ES256 hoặc EdDSA vào algorithm sẽ bị từ chối. Trường publicKey.alg trong JWK (tùy chọn) nếu có phải là ES256.
| Field |
Kiểu |
Bắt buộc |
Ràng buộc |
userId |
string |
Không |
Hex. Để trống với luồng chưa có người dùng |
clientJwtCert |
CertificateJWT |
Có |
- |
clientSensitiveJwtCert |
CertificateJWT |
Có |
- |
clientP256Cert |
CertificateP256 |
Có |
- |
attestation |
AttestationChallenge |
Có |
- |
| Field |
Kiểu |
Ghi chú |
payload.jwtToken |
string |
JWT ký Ed25519 bằng preshare key. Chứa SessionClaim |
| Field |
Kiểu |
Ràng buộc |
kty |
string |
Bắt buộc, EC |
crv |
string |
Bắt buộc, P-256 |
x |
string |
Base64url không padding, 43 ký tự (32 byte) |
y |
string |
Base64url không padding, 43 ký tự (32 byte) |
d |
string |
Phải vắng mặt trong chứng chỉ client (max_len: 0) |
alg |
string |
Tùy chọn. Nếu có, phải là ES256 |
| Field |
Kiểu |
Ràng buộc |
publicKey |
JWK |
Bắt buộc |
algorithm |
string |
P-256 |
scopes |
string |
Danh sách scope cách nhau bằng dấu phẩy, ví dụ read,write,admin |
| Field |
Kiểu |
Ràng buộc |
publicKey |
JWK |
Bắt buộc |
algorithm |
string |
P-256 |
salt |
bytes (base64 trong JSON) |
Đúng 32 byte. Dùng với ECDH để suy ra khóa AES-256-GCM (HKDF-SHA256) |
| Field |
Kiểu |
Ràng buộc |
platform |
string |
IOS hoặc ANDROID |
deviceUuid |
string |
1 đến 32 ký tự |
challengeJwt |
string |
Chỉ IOS. JWT từ get-challenge, hết hạn sau 5 phút |
xKeyId |
string |
Chỉ IOS. App Attest key ID |
xChallengeResponse |
string |
Chỉ IOS. Attestation object, base64 |
androidToken |
string |
Chỉ ANDROID |
| Field |
Kiểu |
Ràng buộc |
sessionId |
string |
Bắt buộc. Dùng làm header X-Api-Session-Id |
publicKey |
bytes |
65 byte, dạng 0x04 || X || Y (ECDH P-256 của server) |
algorithm |
string |
Mặc định P-256 khi trống |
salt |
bytes |
60 byte, dạng nonce || ciphertext || tag của AES-256-GCM, với aad là sessionId |
InitSessionRequest chứa ba chứng chỉ (clientJwtCert, clientSensitiveJwtCert, clientP256Cert) và một AttestationChallenge. Server trả jwtToken chứa SessionClaim.
| Field (request) |
Kiểu |
Ràng buộc |
email |
string |
Định dạng email |
| Field (payload) |
Kiểu |
Ghi chú |
nextStep |
Step |
STEP_VERIFY_EMAIL_OTP (email chưa có tài khoản), STEP_VERIFY_PHONE (tài khoản Justo hiện hữu), STEP_OLD_PASSWORD (tài khoản Ecommerce cũ) |
otpId |
string |
Chỉ có khi gửi OTP email (đăng ký mới). Hết hạn sau 5 phút |
phone |
string |
Số điện thoại đã che (masked) của tài khoản Justo hiện hữu |
| Field (request) |
Kiểu |
Ràng buộc |
otpId |
string |
Bắt buộc |
otp |
string |
1 đến 10 ký tự |
| Field (payload) |
Kiểu |
Ghi chú |
nextStep |
Step |
STEP_VERIFY_PHONE |
phone |
string |
Số điện thoại đã liên kết, nếu có |
| Field (request) |
Kiểu |
Ràng buộc |
phone |
string |
E.164: ^\+?[1-9][0-9]{1,14}$ |
| Field (payload) |
Kiểu |
Ghi chú |
nextStep |
Step |
STEP_VERIFY_PHONE_OTP |
otpId |
string |
OTP gửi tới số điện thoại |
| Field (request) |
Kiểu |
Ràng buộc |
otpId |
string |
Bắt buộc |
otp |
string |
1 đến 10 ký tự |
| Field (payload) |
Kiểu |
Ghi chú |
nextStep |
Step |
STEP_CREATE_ACCOUNT (đăng ký mới), STEP_LOGIN_PASSWORD (đăng nhập), STEP_CREATE_PIN_CODE hoặc STEP_BASIC_INFO (Ecommerce cũ) |
salt |
bytes |
Salt trả về cho client |
| Field (request) |
Kiểu |
Ràng buộc |
password |
string |
8 đến 256 ký tự |
| Field (payload) |
Kiểu |
Ghi chú |
nextStep |
Step |
STEP_BASIC_INFO |
| Field (request) |
Kiểu |
Ghi chú |
givenName |
string |
Tên |
paternalSurname |
string |
Họ |
maternalSurname |
string |
Họ mẹ |
dateOfBirth |
string |
YYYY-MM-DD. Người dùng dưới 18 tuổi bị từ chối |
gender |
Gender |
GENDER_MALE, GENDER_FEMALE, GENDER_OTHER |
| Field (payload) |
Kiểu |
Ghi chú |
nextStep |
Step |
STEP_COMPLETED (dưới 18 tuổi, tài khoản Level 1) hoặc STEP_CREATE_PIN_CODE (từ 18 tuổi) |
| Field (request) |
Kiểu |
Ghi chú |
pinCode |
string |
Mã PIN |
| Field (payload) |
Kiểu |
Ghi chú |
nextStep |
Step |
STEP_COMPLETED |
| Field (request) |
Kiểu |
Ràng buộc |
password |
string |
1 đến 256 ký tự |
| Field (payload) |
Kiểu |
Ghi chú |
nextStep |
Step |
STEP_CREATE_PIN_CODE (Level 2), STEP_COMPLETED (Level 1) hoặc STEP_VERIFY_PHONE (Ecommerce cũ) |
phone |
string |
Số điện thoại đã liên kết |
Không có body. Trả về nonce dùng một lần.
| Field (payload) |
Kiểu |
Ghi chú |
nonce |
string |
Nonce dùng cho đăng nhập social |
expiresAt |
string |
Thời điểm hết hạn, nonce có hiệu lực 10 phút |
| Field (request) |
Kiểu |
Ghi chú |
provider |
string |
Nhà cung cấp, ví dụ google hoặc apple |
idToken |
string |
ID token từ nhà cung cấp |
| Field (payload) |
Kiểu |
Ghi chú |
id |
string |
Hex. Định danh người dùng |
displayName |
string |
Tên hiển thị |
nextStep |
Step |
Bước tiếp theo, xem Luồng xác thực |
phone |
string |
Số điện thoại đã liên kết, nếu có |
Không có body. Kết thúc session đang dùng (header X-Api-Session-Id).
| Giá trị |
Ý nghĩa |
STEP_UNSPECIFIED |
Chưa xác định |
STEP_BASIC_INFO |
Cần nhập thông tin cá nhân |
STEP_CREATE_PIN_CODE |
Cần tạo mã PIN |
STEP_VERIFY_EMAIL_OTP |
Cần nhập OTP email |
STEP_VERIFY_PHONE |
Cần nhập số điện thoại |
STEP_VERIFY_PHONE_OTP |
Cần nhập OTP phone |
STEP_CREATE_ACCOUNT |
Cần tạo mật khẩu |
STEP_LOGIN_PASSWORD |
Cần nhập mật khẩu đăng nhập |
STEP_COMPLETED |
Hoàn tất |
STEP_OLD_PASSWORD |
Cần nhập mật khẩu tài khoản ecommerce cũ |
Mã lỗi của từng endpoint xem tại Mã lỗi.