inai-hono-sdk
SKILL.md
InAI Auth SDK for Hono
This skill guides you through integrating InAI Auth into Hono 4+ applications using the @inai-dev/hono package. Works with Cloudflare Workers, Deno, Bun, and Node.js.
Key Facts
- API URL: Always
https://apiauth.inai.dev— hardcoded in the SDK, never configurable - Required env var:
INAI_PUBLISHABLE_KEY=pk_live_... - Package:
@inai-dev/hono(depends on@inai-dev/backendand@inai-dev/shared) - Auth modes:
"app"(end users) and"platform"(admin/developer panels) - Peer dep:
hono >= 4.0.0
Installation
npm install @inai-dev/hono
Integration Consists of 3 Pieces
- Middleware —
inaiAuthMiddleware()as global middleware - API Routes —
createAuthRoutes()mounted as a sub-app - Route protection —
requireAuth()for per-route authorization
1. Middleware Setup
import { Hono } from "hono";
import { inaiAuthMiddleware } from "@inai-dev/hono/middleware";
const app = new Hono();
app.use(
"*",
inaiAuthMiddleware({
publicRoutes: ["/", "/health", "/login", "/register"],
})
);
Middleware behavior
- Checks if request path matches
publicRoutes— if so, setsinaiAuthcontext tonulland proceeds - Extracts token from
Authorization: Bearer <token>header orauth_tokencookie - If token is expired and
refresh_tokencookie exists → auto-refresh - Builds
AuthObjectfrom JWT claims and stores in Hono context asinaiAuth - If no valid auth → calls
onUnauthorizedhandler (default: 401 JSON response)
Middleware configuration
inaiAuthMiddleware({
authMode: "app", // "app" (default) or "platform"
publicRoutes: ["/", "/health"], // string[] or (path: string) => boolean
onUnauthorized: (c) => {
return c.json({ error: "Unauthorized" }, 401);
},
})
publicRoutes patterns
// String array
publicRoutes: ["/", "/health", "/api/public/*"]
// Function
publicRoutes: (path) => path.startsWith("/public/")
2. API Routes
import { createAuthRoutes } from "@inai-dev/hono/api-routes";
const authRoutes = createAuthRoutes();
app.route("/api/auth", authRoutes);
Creates these endpoints automatically:
POST /api/auth/login— Login, sets httpOnly cookies. Returns{ user }or{ mfa_required, mfa_token }POST /api/auth/register— Registration. Returns{ user }or{ needs_email_verification, user }POST /api/auth/mfa-challenge— TOTP MFA verificationPOST /api/auth/refresh— Token rotation (also called by middleware automatically)POST /api/auth/logout— Invalidate session, clear cookies
Platform Auth (admin panels)
For admin/developer panels, use platform auth mode:
app.use(
"*",
inaiAuthMiddleware({
authMode: "platform",
publicRoutes: ["/login"],
})
);
Platform mode uses /api/platform/auth/* endpoints internally. No publishable key needed.
3. Route Protection
requireAuth middleware
import { requireAuth } from "@inai-dev/hono/middleware";
// Require any authenticated user
app.get("/api/profile", requireAuth(), (c) => {
const auth = getAuth(c);
return c.json({ userId: auth?.userId });
});
// Require specific role
app.get("/api/admin", requireAuth({ role: "admin" }), (c) => {
return c.json({ message: "Admin access granted" });
});
// Require specific permission
app.put("/api/posts/:id", requireAuth({ permission: "posts:write" }), (c) => {
// Update post...
});
Manual auth check with getAuth
import { getAuth } from "@inai-dev/hono";
app.get("/api/data", (c) => {
const auth = getAuth(c);
if (!auth?.userId) {
return c.json({ error: "Not authenticated" }, 401);
}
if (auth.has({ role: "admin" })) {
// Return admin data
}
return c.json({ userId: auth.userId });
});
Context Extension
The middleware extends Hono's context:
// c.get("inaiAuth") is available after middleware runs
const auth = c.get("inaiAuth");
auth?.userId // string | null
auth?.tenantId // string | null
auth?.orgId // string | null
auth?.orgRole // string | null
auth?.sessionId // string | null
auth?.has({ role: "admin" }) // boolean
auth?.has({ permission: "posts:write" }) // boolean
auth?.getToken() // Promise<string | null>
Hono's ContextVariableMap is augmented:
declare module "hono" {
interface ContextVariableMap {
inaiAuth: AuthObject | null;
}
}
Cookie Architecture
| Cookie | Purpose | httpOnly | Path | MaxAge |
|---|---|---|---|---|
auth_token |
Access JWT | Yes | / |
Token expiry |
refresh_token |
Refresh JWT | Yes | /api/auth |
7 days |
auth_session |
User data (readable by JS) | No | / |
Token expiry |
- Production (
NODE_ENV=production):secure: trueon all cookies - Development:
secure: falsefor http://localhost
Cookie Helpers
For custom auth flows or manual token management:
import { setAuthCookies, clearAuthCookies } from "@inai-dev/hono";
// After manual authentication
setAuthCookies(c, tokens, user);
// Manual logout
clearAuthCookies(c);
Token Extraction
import { getTokenFromContext, getRefreshTokenFromContext } from "@inai-dev/hono";
// Gets token from Authorization header or auth_token cookie
const token = getTokenFromContext(c);
// Gets refresh token from cookie only
const refreshToken = getRefreshTokenFromContext(c);
Auth Object Shape
{
userId: string | null
tenantId: string | null
appId: string | null
envId: string | null
orgId: string | null
orgRole: string | null
sessionId: string | null
getToken(): Promise<string | null>
has(params: { role?: string; permission?: string }): boolean
}
Common Patterns
Full Hono app with auth
import { Hono } from "hono";
import {
inaiAuthMiddleware,
requireAuth,
createAuthRoutes,
getAuth,
} from "@inai-dev/hono";
const app = new Hono();
// Global auth middleware
app.use(
"*",
inaiAuthMiddleware({
publicRoutes: ["/", "/health", "/login", "/register"],
})
);
// Auth routes
app.route("/api/auth", createAuthRoutes());
// Public route
app.get("/health", (c) => c.json({ status: "ok" }));
// Protected route
app.get("/api/me", requireAuth(), (c) => {
const auth = getAuth(c);
return c.json({ userId: auth?.userId });
});
// Admin-only route
app.delete("/api/users/:id", requireAuth({ role: "admin" }), (c) => {
// Delete user...
return c.json({ deleted: true });
});
export default app;
Cloudflare Workers deployment
// src/index.ts
import { Hono } from "hono";
import { inaiAuthMiddleware, createAuthRoutes } from "@inai-dev/hono";
type Bindings = {
INAI_PUBLISHABLE_KEY: string;
};
const app = new Hono<{ Bindings: Bindings }>();
app.use("*", (c, next) => {
return inaiAuthMiddleware({
publicRoutes: ["/"],
publishableKey: c.env.INAI_PUBLISHABLE_KEY,
})(c, next);
});
app.route("/api/auth", createAuthRoutes());
export default app;
Login form handler (client-side)
const res = await fetch("/api/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, password }),
});
const data = await res.json();
if (data.mfa_required) {
await fetch("/api/auth/mfa-challenge", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ mfa_token: data.mfa_token, code: totpCode }),
});
}
Source Code Reference
When you need to check implementation details, the source files are at:
packages/hono/src/middleware.ts— inaiAuthMiddleware(), requireAuth()packages/hono/src/api-routes.ts— createAuthRoutes()packages/hono/src/helpers.ts— Cookie & token context utilitiespackages/hono/src/types.ts— TypeScript interfaces & Hono type augmentationpackages/backend/src/client.ts— InAIAuthClient (core API client)packages/shared/src/constants.ts— Cookie names, URLs, headers
Weekly Installs
4
Repository
inai-team/inai-…h-skillsFirst Seen
3 days ago
Security Audits
Installed on
opencode4
gemini-cli4
claude-code4
github-copilot4
codex4
kimi-cli4