Authentication
Carabaas supports two authentication modes:
- Self-signed JWT for machine-to-machine API integrations
- Custody-issued session tokens for human login flows
Client Types and Available Auth Methods
| Client Type | Typical Use Case | Available Auth Methods |
|---|---|---|
api | Backend service, automated jobs | RSA self-signed JWT |
user | Human operator in app or dashboard | Login with Google + session tokens, Email login code + session tokens, RSA self-signed JWT |
Self-Signed JWT (API Clients)
All API requests can be authenticated using self-signed JWT tokens with RSA key pairs. You generate your own tokens — Carabaas never sees your private key.
How It Works
- You generate an RSA key pair locally
- You create an API client in the Console and get a Client ID
- You attach your public key to the API client
- For each API call, you sign a JWT with your private key
- The API verifies the JWT signature using the attached public key
Generate RSA Keys
# Generate a 2048-bit RSA private key
openssl genrsa -out private_key.pem 2048
# Extract the public key
openssl rsa -in private_key.pem -pubout -out public_key.pem
Create an API Client
Create an API client in the Console (Organization → API tab → Add API Client). You'll receive a Client ID. Then attach your RSA public key to the client — either via the Console or the API.
Create a JWT Token
JWT Structure
| Field | Location | Value |
|---|---|---|
typ | Header | JWT |
alg | Header | RS256 |
kid | Header | SHA-256 hash of your public key (DER) |
sub | Payload | Same as kid |
iss | Payload | Your Client ID |
exp | Payload | Token expiration (Unix timestamp) |
JavaScript Example
const jwt = require('jsonwebtoken');
const fs = require('fs');
const { createHash, createPublicKey } = require('crypto');
const privateKey = fs.readFileSync('private_key.pem');
const pubKeyObject = createPublicKey({ key: privateKey, format: 'pem' });
const publicKey = pubKeyObject.export({ format: 'pem', type: 'spki' });
const keyHash = deriveKeyHash(publicKey);
const clientId = 'f7hJ9kL1mN3pQ5rS7tUvWx';
const payload = {
sub: keyHash,
iss: clientId,
exp: Math.floor(Date.now() / 1000) + 3600, // expires in 1 hour
};
const token = jwt.sign(payload, privateKey, {
header: { typ: 'JWT', alg: 'RS256', kid: keyHash },
});
function deriveKeyHash(publicKey) {
const cleanKey = publicKey
.replace('-----BEGIN PUBLIC KEY-----', '')
.replace('-----END PUBLIC KEY-----', '')
.replace(/\n/g, '');
return createHash('sha256')
.update(Buffer.from(cleanKey, 'base64'))
.digest('hex');
}
console.log(token);
Python Example
import jwt
import time
import hashlib
import base64
from cryptography.hazmat.primitives import serialization
with open('private_key.pem', 'rb') as f:
private_key = serialization.load_pem_private_key(f.read(), password=None)
public_key_der = private_key.public_key().public_bytes(
serialization.Encoding.DER,
serialization.PublicFormat.SubjectPublicKeyInfo
)
key_hash = hashlib.sha256(public_key_der).hexdigest()
client_id = 'f7hJ9kL1mN3pQ5rS7tUvWx'
payload = {
'sub': key_hash,
'iss': client_id,
'exp': int(time.time()) + 3600, # expires in 1 hour
}
token = jwt.encode(
payload,
private_key,
algorithm='RS256',
headers={'typ': 'JWT', 'kid': key_hash},
)
Use the Token
Include the JWT in the Authorization header of every request:
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
https://api.carabaas.com/api/v1/vaults
Token Security Best Practices
- Control the
expclaim — set token lifetime according to your security policy - Store your RSA private key securely — use an HSM, secret manager, or encrypt at rest
- Rotate JWTs frequently — generate fresh tokens per session or per request
- Rotate signing keys periodically — register new keys and revoke old ones
- Tokens inherit permissions — the JWT carries the permissions of the authenticated client
Never expose your private key. The private key should never leave your secure infrastructure.
Human Auth Flow
For user clients, Carabaas supports a one-time login code flow that issues custody-managed access and refresh tokens.
Request Login Code
curl -X POST \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]"
}' \
https://api.carabaas.com/api/v1/auth/login-code/request
Verify Login Code and Get Tokens
curl -X POST \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"code": "ABCD-EFGH"
}' \
https://api.carabaas.com/api/v1/auth/login-code/verify
Response contains:
accessToken— short-lived token for API requestsrefreshToken— token for obtaining new access tokens
Refresh Access Token
Use the refresh token in Authorization:
curl -X POST \
-H "Authorization: Bearer YOUR_REFRESH_TOKEN" \
https://api.carabaas.com/api/v1/auth/refresh
Revoke Tokens
Revoke current refresh token:
curl -X POST \
-H "Authorization: Bearer YOUR_REFRESH_TOKEN" \
https://api.carabaas.com/api/v1/auth/revoke
Revoke all refresh tokens for current client:
curl -X POST \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
https://api.carabaas.com/api/v1/auth/revoke-all
Session and Logout
Get current session info:
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
https://api.carabaas.com/api/v1/auth/session
Logout (revoke current session refresh token):
curl -X POST \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
https://api.carabaas.com/api/v1/auth/logout
Google OAuth Flow
For user clients, you can also authenticate via Google OAuth.
Start Google Login
Open the login endpoint in browser and provide a callback URL:
curl -i "https://api.carabaas.com/api/v1/auth/login?callback_url=https%3A%2F%2Fyour-app.com%2Fauth%2Fgoogle-callback"
The API responds with a redirect to Google OAuth consent screen.
Complete Google Consent
After successful Google authentication, Google redirects back to Carabaas callback endpoint:
GET /api/v1/auth/google-callback
Carabaas completes the login flow and returns:
accessTokenrefreshToken
Continue with Session Token Flow
After OAuth login, token lifecycle is the same as in Human Auth Flow:
- refresh access token via
POST /api/v1/auth/refresh - revoke current refresh token via
POST /api/v1/auth/revoke - revoke all refresh tokens via
POST /api/v1/auth/revoke-all - inspect current session via
GET /api/v1/auth/session - logout via
POST /api/v1/auth/logout