Authentication
A comprehensive guide to authenticating requests via Merchant JWT Bearer tokens, HTTP-only session cookies, and Gateway API Keys.
Authentication Methods Comparison
Ziba Pay enforces authentication across all sensitive API routes. Depending on whether your system is an automated backend service, a scheduled worker, or a browser-based web application, select the appropriate authentication strategy below:
| Method | Target Consumer | HTTP Header / Cookie | Security Characteristics | Supported Routes |
|---|---|---|---|---|
| Merchant Bearer Token | Backend servers, microservices, mobile apps | Authorization: Bearer <token> | Stateless JWT, 15-min lifespan, 30-day refresh token | All /orders/*, /transactions/*, /developer/*, and merchant /payment/* |
| Gateway API Keys | Direct server-to-server payment automation | x-api-key and x-api-secret | One-way hashed secret, persistent until revoked | POST/payment/mtn-momo-pay, GET/developer/gatewayConfigs/:apiKey |
| Cookie-Based Session | Browser web apps, client dashboards | Cookie: auth_token=<token> | HTTP-only; requires X-Requested-With: XMLHttpRequest for CSRF protection | All dashboard mutation routes |
Bearer Token Authentication (JWT)
Merchant routes authenticate using a signed JSON Web Token (JWT) passed in the standard Authorization HTTP request header:
import axios from "axios";
const response = await axios.get("https://payment-service-mh2d.onrender.com/api/transactions", {
headers: {
Authorization: `Bearer ${process.env.ZIBA_TOKEN}`,
"Content-Type": "application/json",
},
timeout: 10000,
});
console.log("Transactions:", response.data);Gateway API Keys (Server-to-Server)
Automated payment jobs that do not maintain short-lived merchant login sessions authenticate using Gateway API Keys (x-api-key and x-api-secret).
You generate API Keys via POST/developer/gatewayConfigs. The plaintext apiSecret is shown only once and must be stored securely in an environment variable.
curl -X POST "https://payment-service-mh2d.onrender.com/api/payment/mtn-momo-pay" \
-H "Authorization: Bearer $ZIBA_ACCESS_TOKEN" \
-H "x-api-secret: $ZIBA_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"amount": 100,
"currency": "RWF",
"phoneNumber": "+250788000000"
}'Token Lifecycles & Automatic Refresh
When you authenticate via POST/auth/login or POST/auth/signup, Ziba Pay returns both an access token and a refresh token in the response JSON and sets corresponding HTTP-only cookies:
| Token Type | Storage Location | Lifespan | Renewal Method |
|---|---|---|---|
| Access Token (token) | In-memory / auth_token cookie | 15 minutes | Exchange refresh token via POST/auth/refresh |
| Refresh Token (refreshToken) | Encrypted vault / refresh_token cookie | 30 days | Re-authenticate with POST/auth/login |
| Gateway API Secret | Server environment variables | Persistent until revoked | Revoke via DELETE/developer/delete/:id and re-create |
Account & Authentication Endpoints
The table below details all identity, session, and credential lifecycle routes:
| Endpoint | Method | Auth Required | Description |
|---|---|---|---|
/auth/signup | POST | None | Register a new merchant account; returns JWT token pair. |
/auth/login | POST | None | Sign in with email and password. Every role is emailed a 6-digit code; no session is issued yet. |
/auth/verify-otp | POST | None | Verify the 6-digit email OTP and receive the JWT token pair. |
/auth/refresh | POST | Refresh Token | Exchange valid refresh token for a fresh 15-min access token. |
/auth/logout | POST | Bearer / Cookie | Revoke active merchant sessions and clear session cookies. |
/auth/forgot-password | POST | None | Request a password reset email. |
/auth/reset-password/:token | PATCH | None | Set a new password using reset token. |
Fields
| Field | Type | Required | Description |
|---|---|---|---|
firstName | string | Required | Signup only. Merchant first name. Minimum 2 characters. |
lastName | string | Required | Signup only. Merchant last name. Minimum 2 characters. |
email | string | Required | Signup and login. Valid email address. |
password | string | Required | Signup (min 8 characters) and login. |
howHear | string | Required | Signup only. Referral source. |
businessName | string | Required | Signup only. Registered business or store name. |
businessType | string | Required | Signup only. Business industry or entity type. |
country | string | Required | Signup only. Business operating country. |
phoneNumber | string | Required | Signup only. Valid phone number with international dial code. |
otpCode | string | Required | POST /auth/verify-otp, with email, after any role signs in. |
refreshToken | string | Optional | POST /auth/refresh. Also accepted from the refresh_token cookie or x-refresh-token header. |
Notes
- POST /auth/signup and POST /auth/register invoke the identical registration handler. HTTP 201 returns the token pair.
- POST /auth/login returns { status: 'success', message: 'OTP sent to your email' } for every role. POST /auth/verify-otp then returns the token pair.
- POST /auth/login, POST /auth/verify-otp, and POST /auth/refresh are rate-limited to 10 requests per 15 minutes from a single IP.
- POST /auth/refresh replaces both access and refresh cookies. POST /auth/logout clears both cookies.