inai-hono-sdk

Integrate InAI Auth SDK into Hono applications. Use this skill whenever the user wants to add authentication, login, signup, middleware protection, role-based access control (RBAC), MFA, or session management to a Hono app using @inai-dev/hono. Also trigger when the user mentions InAI auth with Hono, asks about protecting routes in Hono, needs auth middleware for Hono or Cloudflare Workers, wants to set up auth API routes in Hono, or is building an edge-first API with Hono that needs authentication. Covers middleware setup, route protection, cookie management, and both app and platform auth modes.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "inai-hono-sdk" with this command: npx skills add inai-team/inai-auth-skills/inai-team-inai-auth-skills-inai-hono-sdk

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/backend and @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

  1. MiddlewareinaiAuthMiddleware() as global middleware
  2. API RoutescreateAuthRoutes() mounted as a sub-app
  3. Route protectionrequireAuth() 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

  1. Checks if request path matches publicRoutes — if so, sets inaiAuth context to null and proceeds
  2. Extracts token from Authorization: Bearer <token> header or auth_token cookie
  3. If token is expired and refresh_token cookie exists → auto-refresh
  4. Verifies JWT signature using ES256 via JWKS, builds AuthObject and stores in Hono context as inaiAuth
  5. If no valid auth → calls onUnauthorized handler (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);
  },
  // jwksUrl: "https://apiauth.inai.dev/.well-known/jwks.json", // optional override
})

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 verification
  • POST /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?.roles       // string[]
auth?.permissions // string[]
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

CookiePurposehttpOnlyPathMaxAge
auth_tokenAccess JWTYes/Token expiry
refresh_tokenRefresh JWTYes/7 days
auth_sessionUser data (readable by JS)No/Token expiry
  • Production (NODE_ENV=production): secure: true on all cookies
  • Development: secure: false for 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
  roles: string[]
  permissions: string[]
  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 utilities
  • packages/hono/src/types.ts — TypeScript interfaces & Hono type augmentation
  • packages/backend/src/client.ts — InAIAuthClient (core API client)
  • packages/shared/src/constants.ts — Cookie names, URLs, headers
  • packages/shared/src/jwks.ts — JWKSClient (JWKS key fetching, caching, error throttling)
  • packages/shared/src/jwt.ts — ES256 verification, JWT decoding

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

inai-nextjs-sdk

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

github-tools

Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.

Archived SourceRecently Updated
Coding

openclaw-version-monitor

监控 OpenClaw GitHub 版本更新,获取最新版本发布说明,翻译成中文, 并推送到 Telegram 和 Feishu。用于:(1) 定时检查版本更新 (2) 推送版本更新通知 (3) 生成中文版发布说明

Archived SourceRecently Updated
Coding

ask-claude

Delegate a task to Claude Code CLI and immediately report the result back in chat. Supports persistent sessions with full context memory. Safe execution: no data exfiltration, no external calls, file operations confined to workspace. Use when the user asks to run Claude, delegate a coding task, continue a previous Claude session, or any task benefiting from Claude Code's tools (file editing, code analysis, bash, etc.).

Archived SourceRecently Updated