One For All Auth

Using an AI assistant? Point it at 14a.dev/developers.md, the same guide as plain Markdown, or at 14a.dev/llms.txt.

One For All Auth: Developer Guide

Let your Even Hub app use a user's Groq AI or Spotify without asking them to paste API keys into your app.

The user sets up each service once on One For All Auth (https://14a.dev). Your app shows a short code. The user approves it, and your app is connected. Your app never sees their keys. The user can disconnect your app at any time.

Plain language, written so a person or an AI coding assistant can follow it top to bottom.


How it works (30 seconds)

  1. Your app calls startConnect() and gets a code like BCDF-GHJK.
  2. You show the code on the phone screen and the glasses, plus an "Open approval page" button.
  3. The user approves on https://14a.dev/link (the button opens it with the code filled in).
  4. login.done resolves. You're connected, and this survives app restarts.
  5. You call ofa.chat("groq", …) or ofa.spotify("/me/player/…").

There's no server to run, no client secret, and no redirect URLs.


Quick start

1. Get an app ID

Sign in at https://14a.dev/developer → Register a new app.

2. Add the SDK (one file)

Download these two files into your project's src/ folder:

import { OneForAllAuth, OneForAllAuthError, SCOPES, evenHubStorage, createConnectButton } from "./oneforall.js";

It has no dependencies and works with plain Vite + TypeScript Even Hub projects.

3. Allow the network in app.json

"permissions": [
  {
    "name": "network",
    "desc": "Connects to One For All Auth to use your AI and music services",
    "whitelist": [
      "https://oneforall-api.brandon-813.workers.dev",
      "https://api.spotify.com"
    ]
  }
]

Include https://api.spotify.com only if you use Spotify.

4. Connect and use it

import { waitForEvenAppBridge } from "@evenrealities/even_hub_sdk";
import { OneForAllAuth, OneForAllAuthError, SCOPES, evenHubStorage } from "./oneforall.js";

const bridge = await waitForEvenAppBridge();

const ofa = new OneForAllAuth({
  clientId: "YOUR-APP-ID",                       // from step 1
  storage: evenHubStorage(bridge),               // keeps the login across restarts
  optionalScopes: [SCOPES.GROQ, SCOPES.SPOTIFY], // or `scopes: [...]` if your app can't work without them
});

async function connect() {
  const login = await ofa.startConnect();
  showCode(login.userCode);                      // your UI: phone screen AND glasses
  openButton.onclick = () => login.open();       // opens https://14a.dev/link with the code filled in
  await login.done;                              // resolves once the user approves
}

if (!(await ofa.isConnected())) await connect();

// Groq: OpenAI-style chat completion
if (await ofa.hasScope(SCOPES.GROQ)) {
  const res = await ofa.chat("groq", {
    model: "llama-3.1-8b-instant",
    messages: [{ role: "user", content: "One fun fact in under 30 words." }],
  });
  console.log(res.choices[0].message.content);
}

// Spotify: any Web API call, path after https://api.spotify.com/v1
if (await ofa.hasScope(SCOPES.SPOTIFY)) {
  const r = await ofa.spotify("/me/player/currently-playing");
  if (r.status === 204) console.log("Nothing playing");
  else console.log((await r.json()).item?.name);
}

That's the whole integration. A full working example (phone UI plus glasses display) is in examples/even-groq/src/main.ts in the One For All Auth repo.


The Connect button

Use the official button, so users recognize it in every app.

Easiest: let the SDK make it. Its styles are built in, so no CSS is needed:

import { createConnectButton } from "./oneforall.js";

const button = createConnectButton({ onClick: connect });
document.querySelector("#connect-area")!.append(button);

Building your own? Match this exactly:

Label Connect with One For All Auth (use "Reconnect" wording only when reconnecting)
Background #71e7eb (hover #8eedf0)
Text and icon #131b24 (blue-gray off-black, not pure black)
Shape 44px tall minimum, 10px rounded corners, 18px side padding
Font 16px, bold (700), your app's system font
Icon The One For All Auth dot mark, 18px tall, left of the label (brandMarkSvg() returns it as SVG)
<button class="ofa-connect-button">
  <!-- brandMarkSvg() output goes here -->
  <span>Connect with One For All Auth</span>
</button>
<style>
  .ofa-connect-button {
    display: inline-flex; align-items: center; gap: 10px;
    min-height: 44px; padding: 0 18px; border: 0; border-radius: 10px;
    background: #71e7eb; color: #131b24; font: 700 16px/1 system-ui, sans-serif; cursor: pointer;
  }
  .ofa-connect-button:hover { background: #8eedf0; }
</style>

Please don't recolor it, stretch the icon, or change the wording.


What to show the user while connecting

Show the code on the glasses and the phone. Users can approve by reading the code off the glasses.

Connect One For All Auth
Code: BCDF-GHJK
Approve it on your phone.

On the phone, show:

Codes expire after 10 minutes. If login.done rejects with expired_token, show a "Try again" button that calls connect() again.


Required vs optional services

Option Behavior
scopes: [...] Required. The user can't approve until every one is set up on their account.
optionalScopes: [...] Optional. If the user hasn't set one up, it's skipped. Your app connects with the rest.

After connecting, check with await ofa.hasScope(SCOPES.GROQ). If an optional service is missing, tell the user:

"Groq isn't connected. Set it up at 14a.dev, then tap Reconnect."

and make Reconnect call connect() again. Reconnecting replaces the old connection automatically.


SDK reference

new OneForAllAuth(options)

Option Type Notes
clientId string Your app ID. Required.
storage TokenStorage Use evenHubStorage(bridge) in Even Hub apps. Required.
scopes string[] Required services.
optionalScopes string[] Optional services.
apiUrl string Leave unset.

Methods

Method Returns What it does
isConnected() Promise<boolean> True if this app has a saved connection.
startConnect() Promise<DeviceLogin> Starts the code login. Also used to reconnect.
hasScope(scope) Promise<boolean> Whether the user granted that service.
chat(provider, body) Promise<ChatCompletion> OpenAI-style chat completion. provider: "groq".
spotify(path, init?) Promise<Response> Spotify Web API call; path is after /v1.
getProviderToken("spotify") Promise<string> Raw 1-hour Spotify token, if you'd rather call Spotify yourself.
fetch(path, init?) Promise<Response> Any One For All Auth API path with auth handled (advanced).
proxyBaseUrl("groq") string OpenAI-compatible base URL, for OpenAI client libraries (advanced; send requests with ofa.fetch).
disconnect() Promise<void> Disconnects this app and forgets its login.

Helpers

Export What it is
createConnectButton({ onClick, label? }) The official Connect button, styled.
brandMarkSvg(color?, size?) The One For All Auth mark as an SVG string.
BRAND_COLOR, BRAND_INK #71e7eb and #131b24.

DeviceLogin (from startConnect())

Field Notes
userCode Show it on the phone and glasses.
verificationUri https://14a.dev/link, for typing the code on another device.
verificationUriComplete Same page with the code filled in.
open() Opens verificationUriComplete. Returns false if blocked.
done Resolves on approval; rejects with OneForAllAuthError otherwise.
cancel() Stops waiting (done rejects with cancelled).

Scopes

Constant Value Service Notes
SCOPES.GROQ llm:groq Groq AI Chat (chat("groq", …)). Speech-to-text via ofa.fetch("/v1/proxy/groq/openai/v1/audio/transcriptions", …).
SCOPES.SPOTIFY spotify:playback Spotify Now playing and play/pause/skip. Playback control needs Spotify Premium.

Your app can only request scopes it registered in step 1.


Errors

Every SDK error is a OneForAllAuthError with a code:

code Meaning What your app should do
not_connected No login, or the user disconnected your app. Show Connect.
insufficient_scope This connection doesn't include that service. "Set it up at 14a.dev, then tap Reconnect."
credential_missing The user removed that service from their account. Same as above.
credential_expired Spotify needs reconnecting (every 180 days). "Reconnect Spotify at 14a.dev."
access_denied The user tapped Deny. Show Connect again.
expired_token The code expired (10 minutes). Show Try again.
cancelled You called login.cancel(). Nothing.
rate_limited Too many requests (about 60 a minute per user). Wait and retry. Don't poll faster than every few seconds.
provider_error Groq or Spotify returned an error. Show err.message.
try {
  await ofa.chat("groq", body);
} catch (err) {
  if (err instanceof OneForAllAuthError && err.code === "not_connected") showConnectButton();
  else showMessage(err instanceof Error ? err.message : "Something went wrong");
}

Rules (please follow)


Testing


Without the SDK (raw HTTP)

Base URL: https://oneforall-api.brandon-813.workers.dev. Form-encoded or JSON bodies.

  1. POST /oauth/device/code with client_id, scope (space-separated, required), optional_scope (space-separated). Returns device_code, user_code, verification_uri, verification_uri_complete, interval, expires_in.
  2. Every interval seconds: POST /oauth/token with grant_type=urn:ietf:params:oauth:grant-type:device_code, device_code, client_id.
    • 400 {"error":"authorization_pending"}: keep waiting.
    • slow_down: add 5 s to the interval.
    • Success returns access_token (15 min), refresh_token, expires_in, scope.
  3. Renew: POST /oauth/token with grant_type=refresh_token, refresh_token, client_id. Refresh tokens are single use. Save the new one every time; reusing an old one disconnects the app.
  4. Call services with Authorization: Bearer <access_token>:
    • Groq: POST /v1/proxy/groq/openai/v1/chat/completions (also GET …/models, POST …/audio/transcriptions)
    • Spotify: POST /v1/tokens/spotify → { access_token, expires_at }, then call https://api.spotify.com/v1/... with it.
  5. Disconnect: POST /oauth/revoke with token=<refresh_token>.

For AI coding assistants

When integrating One For All Auth into an Even Hub app:

  1. Copy oneforall.js (and oneforall.d.ts) from https://14a.dev/sdk/ into src/.
  2. Add the API host (and https://api.spotify.com if using Spotify) to app.json → permissions → network → whitelist.
  3. Create new OneForAllAuth({ clientId, storage: evenHubStorage(bridge), optionalScopes: [...] }) after waitForEvenAppBridge().
  4. On start: if !(await ofa.isConnected()), show the official Connect button (createConnectButton({ onClick })). On tap: startConnect(), show userCode on the phone and glasses, wire a button to login.open(), await login.done.
  5. Before using a service, check hasScope(). If it's missing, show "set it up at 14a.dev, then Reconnect", with Reconnect calling startConnect().
  6. Use ofa.chat("groq", {...}) for AI and ofa.spotify("/me/player/...") for Spotify.
  7. Catch OneForAllAuthError and handle not_connected by showing Connect again.
  8. Never store, log, or display tokens or keys.

Help

Questions, bugs, or want your app verified? Email brandon@scarletsocial.com.