Authentication

Authentication is required for all requests to the Arthur AI platform. Arthur uses two distinct authentication mechanisms depending on which component you are interacting with:

  • Arthur Platform (platform API): Keycloak OAuth2 β€” either human login (device authorization) or machine-to-machine / service account (client credentials)
  • Arthur Engine (including the Arthur Agent Toolkit): API keys

Logging In to the Platform

Navigate to platform.arthur.ai and sign in with your username and password.

Enterprise deployments only: SSO (bring-your-own identity provider) is only available on enterprise deployments. If your organization does not have an enterprise deployment, you must use username/password login. See the SSO & Identity Provider Setup guide for enterprise SSO configuration.


Arthur Platform: OAuth2 Authentication

The Arthur Platform API uses OAuth2 via Keycloak. There are two flows depending on your use case.

Human Login (Device Authorization)

For human-run flows β€” such as running scripts locally or onboarding workflows β€” use DeviceAuthorizer. This opens a browser window for you to log in with your username and password.

from arthur_client.auth import ArthurOAuthSessionAPIConfiguration, DeviceAuthorizer
from arthur_client.api_bindings import ApiClient

sess = DeviceAuthorizer(arthur_host="https://<host>").authorize()
client = ApiClient(
    configuration=ArthurOAuthSessionAPIConfiguration(session=sess)
)

Machine-to-Machine / Service Account (Client Credentials)

For automated systems, CI/CD pipelines, or any non-human context, use a service account with a client_id and client_secret. Tokens are automatically refreshed with a 30-second leeway before expiration (thread-safe).

from arthur_client.auth import (
    ArthurOAuthSessionAPIConfiguration,
    ArthurClientCredentialsAPISession,
    ArthurOIDCMetadata,
)
from arthur_client.api_bindings import ApiClient

sess = ArthurClientCredentialsAPISession(
    client_id="<your-client-id>",
    client_secret="<your-client-secret>",
    metadata=ArthurOIDCMetadata(arthur_host="https://<host>"),
)
client = ApiClient(
    configuration=ArthurOAuthSessionAPIConfiguration(session=sess)
)
const response = await fetch(
  "https://<host>/realms/arthur/protocol/openid-connect/token",
  {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: new URLSearchParams({
      grant_type: "client_credentials",
      client_id: "<your-client-id>",
      client_secret: "<your-client-secret>",
    }),
  }
);
const { access_token } = await response.json();

// Use the token on subsequent requests
const apiResponse = await fetch("https://<host>/api/v1/...", {
  headers: { "Authorization": `Bearer ${access_token}` },
});

To create a service account and obtain credentials, see the Authorization API.


Arthur Engine: API Key

The Arthur Engine (including the Arthur Agent Toolkit) uses API key authentication. All requests include the key as a Bearer token:

Authorization: Bearer <api_key>

Key Types

TypeSourceUse
Master / Admin keyGENAI_ENGINE_ADMIN_KEY environment variableAdmin operations
User-generated keyCreated via the admin APIStandard operations

Creating a User Key

Use the admin key to create a user key. The raw key is returned once β€” it is bcrypt-hashed in the database after creation, so store it immediately.

curl -X POST http://<host>/auth/api_keys/ \
  -H "Authorization: Bearer <admin_key>" \
  -H "Content-Type: application/json" \
  -d '{"description": "my key"}'

Using a Key

A user-generated Arthur Engine API key can also be used as your ARTHUR_API_KEY environment variable in the observability SDK β€” the same key works in both contexts.

import os
headers = {"Authorization": f"Bearer {os.environ['ARTHUR_API_KEY']}"}
const response = await fetch("http://<host>/...", {
  headers: { "Authorization": `Bearer ${process.env.ARTHUR_API_KEY}` },
});
curl -X GET http://<host>/... \
  -H "Authorization: Bearer $ARTHUR_API_KEY"

Key Details

DetailValue
Storageapi_keys table, bcrypt-hashed (rounds=9)
Internal formatbase64({id}:{key})
In-memory cache TTL10 seconds per validator instance
Validation chainMaster key β†’ User-generated key β†’ JWT/OAuth fallback

Error Handling

Status CodeMeaning
401 UnauthorizedCredentials are missing, invalid, or expired.
403 ForbiddenCredentials are valid but lack permission for the requested resource.

Best Practices

  • Never commit credentials to version control. Use environment variables or a secrets manager.
  • Rotate keys and secrets regularly.
  • Use the minimum necessary permissions β€” assign scoped roles via the Authorization API.
  • Store user-generated API keys immediately upon creation β€” they cannot be retrieved after the response is returned.