Ctrl + K

Authentication

Oblien Sandbox uses a two-tier authentication system for secure access to sandbox environments.

Authentication Overview

There are two levels of authentication:

  1. Account Authentication - Using client credentials to manage sandboxes
  2. Sandbox Authentication - Using sandbox-specific tokens to interact with a sandbox instance
┌─────────────────────────────────────┐
│  Client ID + Client Secret          │
│  (Account Level)                    │
└────────────┬────────────────────────┘

             │  Create/Manage Sandboxes

┌─────────────────────────────────────┐
│  Sandbox Token                      │
│  (Sandbox Level)                    │
└────────────┬────────────────────────┘

             │  Files, Git, Terminal, etc.

┌─────────────────────────────────────┐
│  Sandbox Instance                   │
└─────────────────────────────────────┘

Get Your Credentials

Visit oblien.com/dashboard/api to get your:

  • Client ID - Identifies your account
  • Client Secret - Authenticates your account

⚠️ Warning: Never share your client secret. It provides full access to create and manage sandboxes under your account.

1. Account Authentication

Use client credentials to create and manage sandboxes.

import { OblienClient } from 'agent-sandbox';

const client = new OblienClient({
  clientId: process.env.OBLIEN_CLIENT_ID,
  clientSecret: process.env.OBLIEN_CLIENT_SECRET
});

// Create a sandbox
const sandbox = await client.createSandbox({
  name: 'my-sandbox'
});

// List sandboxes
const { sandboxes } = await client.sandboxes.list();

// Get sandbox details
const details = await client.sandboxes.get('sandbox_abc123');

// Delete a sandbox
await client.sandboxes.delete('sandbox_abc123');

All account-level requests use X-Client-ID and X-Client-Secret headers:

const response = await fetch('https://api.oblien.com/sandbox', {
  method: 'POST',
  headers: {
    'X-Client-ID': process.env.OBLIEN_CLIENT_ID,
    'X-Client-Secret': process.env.OBLIEN_CLIENT_SECRET,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'my-sandbox'
  })
});

const { sandbox } = await response.json();

Account-Level Endpoints:

EndpointDescription
POST /Create a new sandbox
GET /List all sandboxes
GET /:idGet sandbox details
DELETE /:idDelete a sandbox
POST /:id/startStart a stopped sandbox
POST /:id/stopStop a running sandbox
POST /:id/restartRestart a sandbox
POST /:id/regenerate-tokenGenerate new token
GET /:id/metricsGet sandbox metrics
# Create a sandbox
curl -X POST https://api.oblien.com/sandbox \
  -H "X-Client-ID: YOUR_CLIENT_ID" \
  -H "X-Client-Secret: YOUR_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-sandbox"
  }'

# List sandboxes
curl https://api.oblien.com/sandbox \
  -H "X-Client-ID: YOUR_CLIENT_ID" \
  -H "X-Client-Secret: YOUR_CLIENT_SECRET"

# Get sandbox details
curl https://api.oblien.com/sandbox/sandbox_abc123 \
  -H "X-Client-ID: YOUR_CLIENT_ID" \
  -H "X-Client-Secret: YOUR_CLIENT_SECRET"

# Delete a sandbox
curl -X DELETE https://api.oblien.com/sandbox/sandbox_abc123 \
  -H "X-Client-ID: YOUR_CLIENT_ID" \
  -H "X-Client-Secret: YOUR_CLIENT_SECRET"

2. Sandbox Authentication

Each sandbox has its own unique token for isolated access.

Getting a Sandbox Token

Tokens are automatically provided when you create a sandbox:

// SDK automatically manages tokens
const sandbox = await client.createSandbox({
  name: 'my-sandbox'
});

// The sandbox client is ready to use with token already configured
await sandbox.files.list({ dirPath: '/opt/app' });
const response = await fetch('https://api.oblien.com/sandbox', {
  method: 'POST',
  headers: {
    'X-Client-ID': process.env.OBLIEN_CLIENT_ID,
    'X-Client-Secret': process.env.OBLIEN_CLIENT_SECRET,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ name: 'my-sandbox' })
});

const { sandbox } = await response.json();

// sandbox.token - Use this for all sandbox operations
// sandbox.url - Base URL for this sandbox

Response:

{
  "success": true,
  "sandbox": {
    "id": "sandbox_abc123",
    "name": "my-sandbox",
    "url": "https://sandbox.oblien.com",
    "token": "sandbox_token_xyz789...",
    "status": "active"
  }
}
curl -X POST https://api.oblien.com/sandbox \
  -H "X-Client-ID: YOUR_CLIENT_ID" \
  -H "X-Client-Secret: YOUR_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-sandbox"
  }'

# Response includes sandbox.token and sandbox.url
# Use these for all subsequent sandbox operations

Using Sandbox Token

Use the sandbox token for all file, git, terminal, and other sandbox operations:

// Option 1: Use createSandbox (recommended)
const sandbox = await client.createSandbox({ name: 'my-sandbox' });
await sandbox.files.list({ dirPath: '/opt/app' });

// Option 2: Connect to existing sandbox
const sandbox = await client.sandbox('sandbox_abc123');
await sandbox.files.list({ dirPath: '/opt/app' });

// Option 3: Direct SandboxClient (if you have a token)
import { SandboxClient } from 'agent-sandbox';

const sandbox = new SandboxClient({
  token: 'your_sandbox_token'
});

All sandbox operations use Authorization: Bearer <token> header:

const response = await fetch(`${sandbox.url}/files/list`, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${sandbox.token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ dirPath: '/opt/app' })
});
curl -X POST https://sandbox.oblien.com/files/list \
  -H "Authorization: Bearer YOUR_SANDBOX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"dirPath": "/opt/app"}'

Security Best Practices

1. Store Credentials Securely

Never hardcode credentials:

// ❌ Bad - credentials in code
const client = new OblienClient({
  clientId: 'client_123abc',
  clientSecret: 'secret_xyz789'
});

// ✅ Good - credentials in environment variables
const client = new OblienClient({
  clientId: process.env.OBLIEN_CLIENT_ID,
  clientSecret: process.env.OBLIEN_CLIENT_SECRET
});

2. Use Environment Variables

Create a .env file:

# .env
OBLIEN_CLIENT_ID=your_client_id
OBLIEN_CLIENT_SECRET=your_client_secret

Load environment variables:

import dotenv from 'dotenv';
dotenv.config();

const client = new OblienClient({
  clientId: process.env.OBLIEN_CLIENT_ID,
  clientSecret: process.env.OBLIEN_CLIENT_SECRET
});

3. Rotate Tokens Regularly

Regenerate sandbox tokens periodically:

const { token } = await client.sandboxes.regenerateToken('sandbox_abc123');
console.log('New token:', token);
const response = await fetch(
  'https://api.oblien.com/sandbox/sandbox_abc123/regenerate-token',
  {
    method: 'POST',
    headers: {
      'X-Client-ID': process.env.OBLIEN_CLIENT_ID,
      'X-Client-Secret': process.env.OBLIEN_CLIENT_SECRET
    }
  }
);

const { token } = await response.json();
curl -X POST https://api.oblien.com/sandbox/sandbox_abc123/regenerate-token \
  -H "X-Client-ID: YOUR_CLIENT_ID" \
  -H "X-Client-Secret: YOUR_CLIENT_SECRET"

Recommended rotation schedule:

  • Production: Every 30 days
  • Development: Every 7 days
  • Immediately if compromised

4. Use HTTPS Only

All Oblien APIs use HTTPS by default. Never use HTTP for API requests.

5. Limit Token Exposure

  • Don't log tokens
  • Don't commit tokens to version control
  • Use .gitignore for .env files
  • Restrict token access to necessary services only

WebSocket Authentication

WebSocket connections also require authentication:

// SDK handles WebSocket auth automatically
const terminal = await sandbox.terminal.create({
  cols: 120,
  rows: 30
});

// Or use file watcher
await sandbox.watcher.start({
  onChange: (path) => console.log('Changed:', path)
});

Include token as query parameter:

const ws = new WebSocket(
  `wss://sandbox.oblien.com/?token=${sandbox.token}`
);

ws.on('open', () => {
  console.log('Connected');
});

WebSocket connections use query parameter authentication:

# WebSocket URL format (use with ws/wscat client)
wss://sandbox.oblien.com/?token=YOUR_SANDBOX_TOKEN

# Example with wscat
wscat -c "wss://sandbox.oblien.com/?token=YOUR_SANDBOX_TOKEN"

Error Responses

401 Unauthorized

Missing or invalid credentials:

{
  "success": false,
  "error": "Unauthorized",
  "message": "Invalid or missing authentication credentials"
}

Solutions:

  • Verify client ID and secret are correct
  • Check that sandbox token is valid
  • Ensure correct header format

403 Forbidden

Insufficient permissions:

{
  "success": false,
  "error": "Forbidden",
  "message": "You don't have permission to access this resource"
}

Solutions:

  • Verify you own the sandbox
  • Check token hasn't been revoked
  • Ensure using correct authentication level

Authentication Summary

OperationAuthentication MethodHeaders/Format
Create sandboxClient credentialsX-Client-ID, X-Client-Secret
List sandboxesClient credentialsX-Client-ID, X-Client-Secret
Manage sandboxClient credentialsX-Client-ID, X-Client-Secret
File operationsSandbox tokenAuthorization: Bearer <token>
Git operationsSandbox tokenAuthorization: Bearer <token>
TerminalSandbox tokenAuthorization: Bearer <token>
WebSocketSandbox tokenQuery param: ?token=<token>

Need Help?