DeepBlue Dynamics / Docs / GrubCrawler / Authentication

Authentication

N.U.T.S. tokens, session scoping, and self-hosted deployments.

Token shapes

Three kinds of tokens, one auth backend at auth.nuts.services:

TokenShapeLifetimeUse
Browser JWTeyJ... (3-part)24 hoursBrowser login flow
API tokenahp_<opaque>1 yearScripts, agents, MCP clients
Internal HMAC<b64>.<b64>secondsPre-signed query-string URLs only

Browser login (web apps)

Redirect users to auth.nuts.services/login with a return_url pointing back to your service. Magic-link, Google, and GitHub are all supported.

  1. Send the user to:
    https://auth.nuts.services/login?return_url=https://grub.nuts.services/auth/callback
  2. User signs in via email magic-link, Google, or GitHub.
  3. Auth redirects back to your return_url with the JWT in the query:
    https://grub.nuts.services/auth/callback?token=eyJ...
  4. Stash the token (usually in localStorage.nuts_session_token) and use it as the Bearer header for subsequent API calls.

Minimal JS — drop it in any page on your domain:

// Send users to login
function login() {
  const returnUrl = encodeURIComponent(window.location.origin + '/auth/callback');
  window.location.href = `https://auth.nuts.services/login?return_url=${returnUrl}`;
}

// On your /auth/callback page
const token = new URLSearchParams(location.search).get('token');
if (token) {
  localStorage.setItem('nuts_session_token', token);
  history.replaceState({}, '', '/dashboard');
}

Cross-origin tip: localStorage is per-origin. To open the auth.nuts.services dashboard from grub.nuts.services without forcing a re-login, append your JWT to the URL: https://auth.nuts.services/dashboard?token=<your-jwt>. The auth dashboard auto-captures it into its own localStorage.

ahp_ API tokens (backend / agents)

For scripts, AI agents, and MCP clients use long-lived ahp_ tokens. Generate from the auth dashboard → "New Token". Pass as the Bearer header on every request:

curl -X POST https://grub.nuts.services/api/crawl \
  -H "Authorization: Bearer ahp_yourtoken" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com"}'

GrubCrawler validates tokens by routing them based on shape: 3-part dot-separated → GET auth.nuts.services/api/verify for JWT verification; ahp_-prefixed → POST auth.nuts.services/auth for exchange. Either way, your email is extracted from the verified claims and becomes the storage partition key — all your crawl results are stored under your account.

Self-hosted: disabling auth

If you're running GrubCrawler on a private network or internal cluster, you can disable token validation entirely:

docker run -p 8766:6792 -e DISABLE_AUTH=true deepbluedynamics/grubcrawler

With auth disabled, pass customer_id in every request body to scope storage:

{
  "url": "https://example.com",
  "customer_id": "my-agent-001"
}

Do not expose DISABLE_AUTH=true instances to the public internet. There is no rate limiting or access control when auth is disabled.

Session scoping

Sessions group related crawls. Pass a session_id to keep results together:

{
  "url": "https://example.com",
  "session_id": "research-run-2026-04-21",
  "customer_id": "my-agent"
}

Retrieve all files for a session:

GET /api/sessions/{session_id}/files?customer_id=my-agent

AHP internal tokens

The GET /{tool_name}?bearer_token=... catch-all route uses short-lived HMAC tokens for internal tool-call dispatch. These are generated internally and are not for external use.

Get your N.U.T.S. API token at nuts.services. One token works across all N.U.T.S. services.