Authentication Guide

AGNT supports multiple authentication methods to suit different use cases.

Authentication Methods

1. Google OAuth

Authenticate using Google account.

Step 1: Initiate OAuth Flow

GET https://api.agnt.gg/users/auth/google

This redirects to Google's OAuth consent screen.

Step 2: Handle Callback

After user authorization, Google redirects to:

GET https://api.agnt.gg/users/auth/google/callback?code=AUTHORIZATION_CODE

The response includes a JWT token.

Passwordless authentication via email.

Step 1: Request Magic Link

curl -X POST https://api.agnt.gg/users/auth/magic-link/request \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com"}'
const response = await fetch('https://api.agnt.gg/users/auth/magic-link/request', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: 'user@example.com' }),
});

const data = await response.json();
// { "success": true, "message": "Magic link sent to your email" }
import requests

response = requests.post(
    'https://api.agnt.gg/users/auth/magic-link/request',
    json={'email': 'user@example.com'}
)

data = response.json()
# { "success": true, "message": "Magic link sent to your email" }

Step 2: Verify Magic Link

POST https://api.agnt.gg/users/auth/magic-link/verify

{
  "email": "user@example.com",
  "code": "123456"
}

// Response
{
  "success": true,
  "token": "eyJhbiOsisJIgzI15NIIgnR5caC6IkXCJ...",
  "user": { /* user data */ }
}

3. API Key Authentication

For programmatic access (generated in desktop app).

Generate API Key:

POST https://api.agnt.gg/users/generate-api-key
Authorization: Bearer YOUR_JWT_TOKEN

// Response
{
  "success": true,
  "apiKey": "agnt_sk_1234567890abcdef"
}

Using API Key:

fetch('https://api.agnt.gg/agents', {
  headers: {
    'X-API-Key': 'agnt_sk_1234567890abcdef',
  },
});

Token Management

Token Expiration

  • JWT tokens expire after 30 days
  • Refresh tokens before expiration to maintain access

Checking Auth Status

GET https://api.agnt.gg/users/auth/status
Authorization: Bearer YOUR_JWT_TOKEN

// Response
{
  "isAuthenticated": true,
  "user": {
    "id": "user-id",
    "email": "user@example.com",
    "auth_type": "google-login"
  }
}

Logout

POST https://api.agnt.gg/users/logout
Authorization: Bearer YOUR_JWT_TOKEN

// Response
{
  "success": true,
  "message": "Logged out successfully"
}

Middleware & Authorization

Authentication Middleware

The authenticateToken middleware validates JWT tokens:

  • Authenticated: Sets req.user with user data
  • Unauthenticated: Sets req.user.isAuthenticated = false
  • Invalid Token: Continues as unauthenticated (doesn't reject)

Plan-Based Authorization

Some endpoints require specific subscription plans:

// Requires 'business' plan or higher
GET https://api.agnt.gg/advanced-feature
Authorization: Bearer YOUR_JWT_TOKEN

// Response (if insufficient plan)
{
  "error": "Upgrade required",
  "message": "This feature requires business plan or higher",
  "currentPlan": "personal",
  "requiredPlan": "business"
}

Feature-Based Authorization

Access to specific features based on plan:

// Requires specific feature
POST https://api.agnt.gg/premium-feature
Authorization: Bearer YOUR_JWT_TOKEN

// Response (if feature not available)
{
  "error": "Feature not available",
  "message": "This feature is not available on your current plan",
  "currentPlan": "free",
  "requiredFeature": "advanced_analytics"
}

Security Best Practices

1. Store Tokens Securely

// ❌ Don't store in localStorage (vulnerable to XSS)
localStorage.setItem('token', token);

// βœ… Use httpOnly cookies or secure storage
// Server sets: Set-Cookie: token=...; HttpOnly; Secure; SameSite=Strict

2. Validate Tokens Server-Side

// Always verify tokens on the server
jwt.verify(token, process.env.JWT_SECRET);

3. Use HTTPS

// βœ… Always use HTTPS in production
const API_URL = 'https://api.agnt.gg';

// ❌ Never use HTTP for authentication
const API_URL = 'http://api.agnt.gg'; // Insecure!

4. Implement Token Rotation

// Refresh tokens before expiration
if (tokenExpiresIn < 24 * 60 * 60 * 1000) {
  // Less than 24 hours remaining
  await refreshToken();
}

5. Handle Token Expiration

fetch('https://api.agnt.gg/agents', {
  headers: { Authorization: `Bearer ${token}` },
})
  .then((res) => {
    if (res.status === 401) {
      // Token expired, redirect to login
      window.location.href = '/login';
    }
    return res.json();
  })
  .catch((error) => console.error(error));

Provider & Integration API

These endpoints (mounted at /auth) manage external tool providers (like Google, GitHub, etc.) and their connections to your agents.

Provider Registry

Manage the available integration providers.

List All Providers

GET https://api.agnt.gg/auth/providers
Authorization: Bearer YOUR_JWT_TOKEN

// Response
[
  {
    "id": "google",
    "name": "Google",
    "icon": "...",
    "categories": ["productivity"],
    "connectionType": "oauth"
  }
]

Create Custom Provider

POST https://api.agnt.gg/auth/providers
Authorization: Bearer YOUR_JWT_TOKEN

{
  "id": "custom-service",
  "name": "Custom Service",
  "connectionType": "api_key", // or 'oauth'
  // ... configuration fields
}

Manage Providers

// Get Provider
GET https://api.agnt.gg/auth/providers/:id

// Update Provider
PUT https://api.agnt.gg/auth/providers/:id

// Delete Provider
DELETE https://api.agnt.gg/auth/providers/:id

Connection Management

Manage OAuth connections for your agents.

Connect Provider

Initiate the OAuth flow for a specific provider.

GET https://api.agnt.gg/auth/connect/:provider
Authorization: Bearer YOUR_JWT_TOKEN

// Response
{
  "authUrl": "https://accounts.google.com/o/oauth2/v2/auth?..."
}

Handle Callback

Exchange the authorization code for tokens.

POST https://api.agnt.gg/auth/callback
Authorization: Bearer YOUR_JWT_TOKEN

{
  "code": "AUTHORIZATION_CODE",
  "state": "provider:origin"
}

// Response
{
  "success": true,
  "provider": "google"
}

Local Callback

GET endpoint for local/desktop app callbacks.

GET https://api.agnt.gg/auth/callback/:provider?code=...&state=...

Disconnect Provider

POST https://api.agnt.gg/auth/disconnect/:provider
Authorization: Bearer YOUR_JWT_TOKEN

// Response
{ "success": true }

List Connected Apps

GET https://api.agnt.gg/auth/connected
Authorization: Bearer YOUR_JWT_TOKEN

// Response
{
  "success": true,
  "connectedApps": [
    {
      "provider": "google",
      "email": "user@gmail.com",
      "connectedAt": "2025-11-25T10:00:00Z"
    }
  ]
}

Provider API Keys

Manage manual API keys for providers (e.g., OpenAI).

Store API Key

POST https://api.agnt.gg/auth/apikeys/:providerId
Authorization: Bearer YOUR_JWT_TOKEN

{
  "apiKey": "sk-..." // Will be encrypted on storage
}

Retrieve API Key

GET https://api.agnt.gg/auth/apikeys/:providerId
Authorization: Bearer YOUR_JWT_TOKEN

// Response
{
  "success": true,
  "apiKey": "sk-..." // Decrypted key
}

Utilities

Get Valid Token

Retrieve a fresh access token for a connected provider.

GET https://api.agnt.gg/auth/valid-token?providerId=google&userId=...
Authorization: Bearer YOUR_JWT_TOKEN

// Response
{
  "access_token": "ya29..."
}

Get Google Search Keys

Retrieve public Google Search configuration.

GET https://api.agnt.gg/auth/google-search-keys
Authorization: Bearer YOUR_JWT_TOKEN

// Response
{
  "apiKey": "...",
  "searchEngineId": "..."
}

Error Handling

Common Authentication Errors

Status Error Description Solution
401 Unauthorized No token provided Include Authorization header
401 Invalid token Token is malformed or expired Refresh or re-authenticate
403 Forbidden Insufficient permissions Upgrade plan or check feature access
429 Too Many Requests Rate limit exceeded Wait before retrying

Example Error Response

{
  "success": false,
  "error": "Authentication required",
  "statusCode": 401,
  "timestamp": "2025-11-25T10:00:00Z"
}

Complete Authentication Flow Example

class AgntAuth {
  constructor() {
    this.token = null;
    this.user = null;
  }

  async requestMagicLink(email) {
    const response = await fetch('https://api.agnt.gg/users/auth/magic-link/request', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email }),
    });

    if (!response.ok) {
      throw new Error('Failed to send magic link');
    }

    return await response.json();
  }

  async verifyMagicLink(email, code) {
    const response = await fetch('https://api.agnt.gg/users/auth/magic-link/verify', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email, code }),
    });

    if (!response.ok) {
      throw new Error('Magic link verification failed');
    }

    const data = await response.json();
    this.token = data.token;
    this.user = data.user;

    // Store securely
    this.storeToken(data.token);

    return data;
  }

  async makeAuthenticatedRequest(url, options = {}) {
    if (!this.token) {
      throw new Error('Not authenticated');
    }

    const response = await fetch(url, {
      ...options,
      headers: {
        ...options.headers,
        Authorization: `Bearer ${this.token}`,
      },
    });

    if (response.status === 401) {
      // Token expired, clear and redirect
      this.logout();
      throw new Error('Session expired');
    }

    return response;
  }

  storeToken(token) {
    // Implement secure storage
    sessionStorage.setItem('agnt_token', token);
  }

  logout() {
    this.token = null;
    this.user = null;
    sessionStorage.removeItem('agnt_token');
  }
}

// Usage - Request magic link
const auth = new AgntAuth();
await auth.requestMagicLink('user@example.com');

// User receives code in email
// Then verify the code
await auth.verifyMagicLink('user@example.com', '123456');

// Make authenticated requests
const agents = await auth.makeAuthenticatedRequest('https://api.agnt.gg/agents');

Next Steps