Skip to main content

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 TypeTypical Use CaseAvailable Auth Methods
apiBackend service, automated jobsRSA self-signed JWT
userHuman operator in app or dashboardLogin 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

  1. You generate an RSA key pair locally
  2. You create an API client in the Console and get a Client ID
  3. You attach your public key to the API client
  4. For each API call, you sign a JWT with your private key
  5. 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

FieldLocationValue
typHeaderJWT
algHeaderRS256
kidHeaderSHA-256 hash of your public key (DER)
subPayloadSame as kid
issPayloadYour Client ID
expPayloadToken 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 exp claim — 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
warning

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 requests
  • refreshToken — 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.

After successful Google authentication, Google redirects back to Carabaas callback endpoint:

GET /api/v1/auth/google-callback

Carabaas completes the login flow and returns:

  • accessToken
  • refreshToken

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