Skip to content

Kindly API Authentication Guide

Overview

The Kindly API uses two primary authentication methods to ensure secure access:

  1. JWT Bearer Tokens - For user sessions and temporary access
  2. API Keys - For long-term programmatic access

Both methods provide full access to the API, but have different use cases and security characteristics.

JWT Bearer Token Authentication

JWT (JSON Web Token) authentication is ideal for: - Web applications with user sessions - Mobile applications - Short-lived access requirements - Scenarios requiring user-specific permissions

Registration

Create a new user account:

curl -X POST https://api.kindly.com/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "SecureP@ssw0rd!",
    "name": "John Doe"
  }'

Response:

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com",
    "name": "John Doe",
    "created_at": "2024-01-08T12:00:00Z"
  }
}

Login

Authenticate an existing user:

curl -X POST https://api.kindly.com/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "SecureP@ssw0rd!"
  }'

Using the Access Token

Include the access token in the Authorization header:

curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
     https://api.kindly.com/api/compression/stats

Token Refresh

Access tokens expire after 1 hour. Use the refresh token to obtain a new access token:

curl -X POST https://api.kindly.com/api/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  }'

Logout

Invalidate the current session:

curl -X POST https://api.kindly.com/api/auth/logout \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

JWT Token Structure

Our JWT tokens contain:

{
  "header": {
    "alg": "HS256",
    "typ": "JWT"
  },
  "payload": {
    "sub": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com",
    "name": "John Doe",
    "iat": 1704720000,
    "exp": 1704723600,
    "jti": "unique-token-id"
  }
}

API Key Authentication

API Keys are ideal for: - Server-to-server communication - CI/CD pipelines - Long-running services - Automated scripts

Creating an API Key

First, authenticate with JWT, then create an API key:

curl -X POST https://api.kindly.com/api/keys \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production Server",
    "expires_at": "2025-01-08T00:00:00Z"
  }'

Response:

{
  "id": "660e8400-e29b-41d4-a716-446655440001",
  "key": "kapi_prod_7f3d9a2b5c1e4890abcdef1234567890",
  "name": "Production Server",
  "expires_at": "2025-01-08T00:00:00Z"
}

Important: The key field is only shown once. Store it securely!

Using API Keys

Include the API key in the X-API-Key header:

curl -H "X-API-Key: kapi_prod_7f3d9a2b5c1e4890abcdef1234567890" \
     https://api.kindly.com/api/compression/stats

API Key Format

API keys follow a consistent format: - Prefix: kapi_ - Environment: prod_, test_, dev_ - Random string: 32 characters

Example: kapi_prod_7f3d9a2b5c1e4890abcdef1234567890

Managing API Keys

List all your API keys:

curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
     https://api.kindly.com/api/keys

Revoke an API key:

curl -X DELETE https://api.kindly.com/api/keys/660e8400-e29b-41d4-a716-446655440001 \
     -H "Authorization: Bearer YOUR_JWT_TOKEN"

Security Best Practices

1. Secure Storage

Never store credentials in: - Source code - Version control - Client-side code - Unencrypted databases - Log files

Do store credentials in: - Environment variables - Secure key management services (AWS KMS, HashiCorp Vault) - Encrypted configuration files - Operating system keychains

2. Key Rotation

Regularly rotate your credentials:

import os
from datetime import datetime, timedelta

class KeyRotationManager:
    def __init__(self, api_client):
        self.api_client = api_client
        self.rotation_interval = timedelta(days=90)

    def should_rotate(self, key_created_at):
        age = datetime.utcnow() - key_created_at
        return age > self.rotation_interval

    def rotate_api_key(self, old_key_id):
        # Create new key
        new_key = self.api_client.create_api_key({
            "name": f"Rotated key - {datetime.utcnow().isoformat()}"
        })

        # Update application configuration
        os.environ['KINDLY_API_KEY'] = new_key['key']

        # Schedule old key deletion (grace period)
        self.schedule_key_deletion(old_key_id, delay_hours=24)

        return new_key

3. Least Privilege

Create specific API keys for different purposes:

// Development key with limited permissions
const devKey = await createApiKey({
  name: "Development - Local Testing",
  permissions: ["read:compression", "read:context"],
  ip_whitelist: ["127.0.0.1", "::1"],
  expires_at: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) // 7 days
});

// Production key with full permissions
const prodKey = await createApiKey({
  name: "Production - Main Service",
  permissions: ["*"],
  ip_whitelist: ["52.44.123.456", "52.44.123.457"],
  expires_at: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000) // 1 year
});

4. Request Signing (Advanced)

For additional security, sign your requests:

import hmac
import hashlib
import time
import json

class SignedRequestClient:
    def __init__(self, api_key, api_secret):
        self.api_key = api_key
        self.api_secret = api_secret

    def create_signature(self, method, path, body=None):
        timestamp = str(int(time.time()))
        nonce = os.urandom(16).hex()

        # Create message to sign
        message_parts = [method, path, timestamp, nonce]
        if body:
            message_parts.append(json.dumps(body, sort_keys=True))

        message = ''.join(message_parts)

        # Create HMAC signature
        signature = hmac.new(
            self.api_secret.encode(),
            message.encode(),
            hashlib.sha256
        ).hexdigest()

        return {
            'X-API-Key': self.api_key,
            'X-Timestamp': timestamp,
            'X-Nonce': nonce,
            'X-Signature': signature
        }

5. IP Whitelisting

Restrict API key usage to specific IP addresses:

# Configure IP restrictions when creating key
api_key = client.create_api_key(
  name: "Production Server",
  allowed_ips: [
    "203.0.113.0/24",  # Production subnet
    "198.51.100.42"    # Backup server
  ],
  denied_ips: [
    "192.168.0.0/16",  # Block all private IPs
    "10.0.0.0/8"
  ]
)

CSRF Protection

For browser-based applications, implement CSRF protection:

1. Get CSRF Token

const response = await fetch('https://api.kindly.com/api/csrf-token', {
  credentials: 'include'
});
const { csrf_token } = await response.json();

2. Include in State-Changing Requests

const result = await fetch('https://api.kindly.com/api/compression/compress', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'X-CSRF-Token': csrf_token,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(data),
  credentials: 'include'
});

OAuth 2.0 Integration (Coming Soon)

We're implementing OAuth 2.0 for third-party integrations:

// Future OAuth flow
const authUrl = `https://api.kindly.com/oauth/authorize?
  client_id=${CLIENT_ID}&
  redirect_uri=${REDIRECT_URI}&
  response_type=code&
  scope=read:compression write:compression&
  state=${STATE}`;

// After user authorization, exchange code for token
const tokenResponse = await fetch('https://api.kindly.com/oauth/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    grant_type: 'authorization_code',
    code: authorizationCode,
    client_id: CLIENT_ID,
    client_secret: CLIENT_SECRET,
    redirect_uri: REDIRECT_URI
  })
});

Multi-Factor Authentication (MFA)

Enable MFA for enhanced security:

1. Enable MFA

curl -X POST https://api.kindly.com/api/auth/mfa/enable \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Response includes QR code for authenticator apps.

2. Login with MFA

curl -X POST https://api.kindly.com/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "SecureP@ssw0rd!",
    "mfa_code": "123456"
  }'

Service Accounts

For automated systems, use service accounts:

# Create service account
service_account = api.create_service_account({
    "name": "analytics-processor",
    "description": "Automated analytics processing service",
    "permissions": [
        "read:analytics",
        "write:analytics",
        "read:compression"
    ]
})

# Service account authentication
service_client = KindlyAPIClient(
    service_account_id=service_account['id'],
    private_key=service_account['private_key']
)

Webhook Authentication

Verify webhook signatures to ensure authenticity:

func VerifyWebhookSignature(payload []byte, signature string, secret string) bool {
    expectedSig := hmac.New(sha256.New, []byte(secret))
    expectedSig.Write(payload)
    expected := hex.EncodeToString(expectedSig.Sum(nil))

    return hmac.Equal([]byte(expected), []byte(signature))
}

// In your webhook handler
func HandleWebhook(w http.ResponseWriter, r *http.Request) {
    payload, _ := ioutil.ReadAll(r.Body)
    signature := r.Header.Get("X-Kindly-Signature")

    if !VerifyWebhookSignature(payload, signature, webhookSecret) {
        http.Error(w, "Invalid signature", http.StatusUnauthorized)
        return
    }

    // Process webhook...
}

Troubleshooting

Common Authentication Errors

Error Code Description Solution
AUTH_001 Invalid credentials Check email/password
AUTH_002 Token expired Refresh token or re-login
AUTH_003 Invalid token format Ensure proper Bearer format
AUTH_004 API key not found Check key hasn't been revoked
AUTH_005 IP not whitelisted Add IP to allowed list
AUTH_006 MFA required Provide MFA code
AUTH_007 Account locked Contact support

Debug Authentication Issues

Enable debug headers to troubleshoot:

curl -H "X-API-Key: your_key" \
     -H "X-Debug-Auth: true" \
     https://api.kindly.com/api/health

Debug response headers:

X-Auth-Method: api_key
X-Auth-User-ID: 550e8400-e29b-41d4-a716-446655440000
X-Auth-Key-ID: 660e8400-e29b-41d4-a716-446655440001
X-Auth-IP: 203.0.113.42
X-Auth-Remaining-Quota: 9950

Security Checklist

  • [ ] Store credentials securely (environment variables, key management service)
  • [ ] Rotate API keys every 90 days
  • [ ] Use HTTPS for all API calls
  • [ ] Implement request signing for sensitive operations
  • [ ] Enable MFA for user accounts
  • [ ] Monitor API key usage for anomalies
  • [ ] Use IP whitelisting for production keys
  • [ ] Implement CSRF protection for web applications
  • [ ] Verify webhook signatures
  • [ ] Use service accounts for automated systems
  • [ ] Implement proper error handling without exposing sensitive data
  • [ ] Log authentication events for audit trails

Support

For authentication issues: - Check our Status Page for service availability - Review Common Issues - Contact support: support@kindly.com - Enterprise support: enterprise@kindly.com