← Commit history

Initial commit: skill/3rd-party-auth

Kyle Bergstedt ·5344a025b5 ·4mo ago
2 files changed +141
README.mdadded+79
@@ -0,0 +1,79 @@+## Demo++![3rd Party Auth Demo](skills/3rd-party-auth/demo.webm)++2.5-minute narrated walkthrough of the Authentication Intent flow — from creating an intent to receiving a session token.++---++## Overview++Authentication Intents let any application add "Sign in with Adom" functionality. The flow uses **confirmation codes** to prevent phishing — the user must verify that a code shown in their application matches what they see in the browser.++### The Flow++1. **App creates an intent** — `POST /auth/intents` returns a token, confirmation code, and status URL+2. **App shows the code** — e.g. `BRTK-MXVZ` displayed in the terminal+3. **App opens browser** — points to `hydrogen.adom.inc/auth/intents/{token}`+4. **User logs in** — email/password or Google OAuth (new!)+5. **User enters the code** — types the confirmation code from their app+6. **Carbon creates a session** — Application-scoped, linked to the intent+7. **App receives the session token** — via SSE (real-time) or short polling++### Quick Start (JavaScript)++```javascript+// 1. Create the intent+const res = await fetch('https://carbon.adom.inc/auth/intents', {+  method: 'POST',+  headers: { 'Content-Type': 'application/json' },+  body: JSON.stringify({ max_age: 7776000 }),  // 90-day session+});+const intent = await res.json();++// 2. Show code + open browser+console.log(`Code: ${intent.confirmation_code}`);+open(`https://hydrogen.adom.inc/auth/intents/${intent.token}`);++// 3. Wait for authentication via SSE+const es = new EventSource(`${intent.updates_url}/status`);+es.addEventListener('authenticated', (e) => {+  const { session_token } = JSON.parse(e.data);+  // Use session_token for authenticated API calls+});+```++### Confirmation Code Format++- **8 uppercase consonants** formatted as `XXXX-XXXX`+- No vowels (avoids accidental profanity)+- Case-insensitive verification, dashes/spaces stripped+- Prevents phishing — user must see the code from the real app++### Intent Lifecycle++| State | Description |+|-------|-------------|+| Created | Waiting for user (15-min TTL) |+| Authenticated | User entered correct code, session linked |+| Consumed | App retrieved the session token |+| Expired | 15 minutes elapsed without completion |++### API Endpoints++| Method | Route | Description |+|--------|-------|-------------|+| `POST` | `/auth/intents` | Create a new intent (optional `max_age` body) |+| `GET` | `/auth/intents/{token}` | Retrieve intent details |+| `GET` | `/auth/intents/{token}/status` | Poll or SSE for auth status |+| `PATCH` | `/auth/intents/{token}` | Link user session (requires `confirmation_code`) |++### Google OAuth Sign-In++Users can now sign in to Hydrogen with their Google account. This is built into the login page — 3rd party apps get it for free when users are directed to the Hydrogen login flow. New Google users are prompted to choose a username before their account is created.++### Related++- **OAuth Gateway** — For integrating external OAuth providers (YouTube, GitHub, Slack) into Adom services. See the `oauth` skill for details.+- **Carbon API** — The backend that powers authentication intents, sessions, and user management.+- **Hydrogen** — The frontend that renders the login page, confirmation code entry, and Google OAuth flows.
page.jsonadded+62
@@ -0,0 +1,62 @@+{+  "schema_version": 1,+  "type": "skill",+  "slug": "3rd-party-auth",+  "title": "Third-Party Authentication",+  "brief": "Sign in with Adom — let users authenticate to your app using their Adom account via Authentication Intents with confirmation codes. Covers the full flow, API reference, code examples, and Google OAuth",+  "version": "1.0.0",+  "tags": [],+  "license": "MIT",+  "sample_prompts": [+    {+      "label": "Sign in with Adom",+      "prompt": "How do I add 'Sign in with Adom' to my app?"+    },+    {+      "label": "Create intent",+      "prompt": "Show me how to create an authentication intent"+    },+    {+      "label": "Auth flow code",+      "prompt": "Give me a complete JavaScript example of the auth intent flow"+    },+    {+      "label": "Confirmation codes",+      "prompt": "How do confirmation codes prevent phishing?"+    },+    {+      "label": "Poll vs SSE",+      "prompt": "Should I use polling or SSE to wait for authentication?"+    },+    {+      "label": "Session tokens",+      "prompt": "How do I use the session token after authentication?"+    },+    {+      "label": "Google OAuth",+      "prompt": "How does Google sign-in work with authentication intents?"+    },+    {+      "label": "Intent API",+      "prompt": "What are all the authentication intent API endpoints?"+    }+  ],+  "source_path": "SKILL.md",+  "readme": "## Demo\n\n![3rd Party Auth Demo](skills/3rd-party-auth/demo.webm)\n\n2.5-minute narrated walkthrough of the Authentication Intent flow — from creating an intent to receiving a session token.\n\n---\n\n## Overview\n\nAuthentication Intents let any application add \"Sign in with Adom\" functionality. The flow uses **confirmation codes** to prevent phishing — the user must verify that a code shown in their application matches what they see in the browser.\n\n### The Flow\n\n1. **App creates an intent** — `POST /auth/intents` returns a token, confirmation code, and status URL\n2. **App shows the code** — e.g. `BRTK-MXVZ` displayed in the terminal\n3. **App opens browser** — points to `hydrogen.adom.inc/auth/intents/{token}`\n4. **User logs in** — email/password or Google OAuth (new!)\n5. **User enters the code** — types the confirmation code from their app\n6. **Carbon creates a session** — Application-scoped, linked to the intent\n7. **App receives the session token** — via SSE (real-time) or short polling\n\n### Quick Start (JavaScript)\n\n```javascript\n// 1. Create the intent\nconst res = await fetch('https://carbon.adom.inc/auth/intents', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify({ max_age: 7776000 }),  // 90-day session\n});\nconst intent = await res.json();\n\n// 2. Show code + open browser\nconsole.log(`Code: ${intent.confirmation_code}`);\nopen(`https://hydrogen.adom.inc/auth/intents/${intent.token}`);\n\n// 3. Wait for authentication via SSE\nconst es = new EventSource(`${intent.updates_url}/status`);\nes.addEventListener('authenticated', (e) => {\n  const { session_token } = JSON.parse(e.data);\n  // Use session_token for authenticated API calls\n});\n```\n\n### Confirmation Code Format\n\n- **8 uppercase consonants** formatted as `XXXX-XXXX`\n- No vowels (avoids accidental profanity)\n- Case-insensitive verification, dashes/spaces stripped\n- Prevents phishing — user must see the code from the real app\n\n### Intent Lifecycle\n\n| State | Description |\n|-------|-------------|\n| Created | Waiting for user (15-min TTL) |\n| Authenticated | User entered correct code, session linked |\n| Consumed | App retrieved the session token |\n| Expired | 15 minutes elapsed without completion |\n\n### API Endpoints\n\n| Method | Route | Description |\n|--------|-------|-------------|\n| `POST` | `/auth/intents` | Create a new intent (optional `max_age` body) |\n| `GET` | `/auth/intents/{token}` | Retrieve intent details |\n| `GET` | `/auth/intents/{token}/status` | Poll or SSE for auth status |\n| `PATCH` | `/auth/intents/{token}` | Link user session (requires `confirmation_code`) |\n\n### Google OAuth Sign-In\n\nUsers can now sign in to Hydrogen with their Google account. This is built into the login page — 3rd party apps get it for free when users are directed to the Hydrogen login flow. New Google users are prompted to choose a username before their account is created.\n\n### Related\n\n- **OAuth Gateway** — For integrating external OAuth providers (YouTube, GitHub, Slack) into Adom services. See the `oauth` skill for details.\n- **Carbon API** — The backend that powers authentication intents, sessions, and user management.\n- **Hydrogen** — The frontend that renders the login page, confirmation code entry, and Google OAuth flows.\n",+  "author": {+    "id": "695820315b5f1e4db2fcf602",+    "name": "Kyle Bergstedt",+    "email": "[email protected]"+  },+  "visibility": {+    "public": true+  },+  "hero": null,+  "discovery_triggers": [],+  "discovery_pitch": null,+  "metadata": {},+  "created_at": "2026-05-28T05:29:34.040Z",+  "updated_at": "2026-05-28T05:29:34.040Z",+  "sub_skills": [],+  "parent_app": null+}\ No newline at end of file