OAuth (std/oauth)
SkillSecurityUse when a val needs to require login with a Val Town account, gating routes behind authentication, identifying the current user, building user-specific dashboards. Covers std/oauth's `oauthMiddleware` and `getOAuthUserData`, the auto-managed `/auth/*` routes, and session behavior. For third-party OAuth providers (Google, GitHub, etc.) see the `third-party-integrations` skill instead.
Use OAuth (std/oauth) in Claude, ChatGPT or Ahel Desktop
Free. Sign in, add OAuth (std/oauth) and connect your AI. About a minute.
Also: Claude Code · Cursor · Codex
Then ask your AI: use the OAuth (std/oauth) skill
Details
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; Ahel provides instructions and does not run this skill.
No other account needed.
Add Ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
What this skill tells your AI
The instructions your AI receives, as published by hashgraph-online/awesome-codex-plugins in plugins/val-town/plugins/skills/oauth/SKILL.md and read by Ahel’s review.
Val Town provides zero-config "Log in with Val Town" via std/oauth. No database setup, no provider config — wrap your Hono fetch handler and you get login, logout, and session management for free. Sessions are stored in encrypted cookies and last 30 days.
This is for Val Town account login only. For Google / GitHub / Slack / etc. OAuth, see the third-party-integrations skill — those flows are documented per-service.
If the goal is to keep an app internal to a team rather than to give it its own logged-in users, restricting the val's app access is the simpler answer — the platform gates the endpoint before your code runs, and you write no auth code. See the restricted-access skill. Don't apply both to one val: a restricted val that also runs oauthMiddleware makes visitors authenticate twice.
Imports
import {
getOAuthUserData,
oauthMiddleware,
} from "https://esm.town/v/std/oauth/middleware.ts";
Wrapping your app
oauthMiddleware(handler) takes your Hono fetch handler and returns a wrapped handler that injects three auto-managed routes:
GET /auth/login— starts the login flowGET /auth/callback— completes the login flowPOST /auth/logout— clears the session
Export the wrapped handler as the val's default:
import { Hono } from "npm:hono";
import { oauthMiddleware } from "https://esm.town/v/std/oauth/middleware.ts";
const app = new Hono();
app.onError((err) => Promise.reject(err));
app.get("/", (c) => c.text("hello"));
export default oauthMiddleware(app.fetch);
You don't write the /auth/* routes yourself — the middleware adds them. Don't shadow them in your own app.
Reading the current user
Call getOAuthUserData(rawRequest) from any route. In Hono, rawRequest is c.req.raw. It returns the session data if the request is authenticated, or null otherwise.
interface SessionData {
user: {
id: string;
username: string | null;
email: string | null;
bio: string | null;
tier: "free" | "pro" | null;
type: "user" | "org";
url: string;
links: {
self: string;
profileImageUrl: string | null;
};
};
accessToken: string; // Val Town API token (act on behalf of the user)
refreshToken?: string;
idToken?: string;
expiresAt: number; // Unix timestamp (ms)
isOrgMember?: boolean; // true if user belongs to this val's org
}
app.get("/", async (c) => {
const session = await getOAuthUserData(c.req.raw);
if (session?.user) {
return c.html(
`<p>Logged in as ${session.user.username}</p>` +
`<form method="POST" action="/auth/logout"><button>Log out</button></form>`
);
}
return c.html(`<a href="/auth/login">Log in with Val Town</a>`);
});
Gating routes
There's no built-in "require login" helper — gate routes by checking getOAuthUserData and returning a 401 or redirecting to /auth/login when the session is missing:
app.get("/dashboard", async (c) => {
const session = await getOAuthUserData(c.req.raw);
if (!session?.user) return c.redirect("/auth/login");
return c.html(`<h1>Welcome ${session.user.username}</h1>`);
});
What you don't need to configure
- No env vars — credentials and redirect URLs are handled by the platform.
- No callback URL setup —
/auth/callbackis wired automatically. - No session store — sessions live in encrypted cookies.
Verifying changes
After adding OAuth, call fetch_val_endpoint on a gated route to confirm it redirects or 401s when unauthenticated. The full login flow requires a real browser session and can't be exercised by fetch_val_endpoint alone — share the live URL and have the user try logging in.
Signals
- GitHub stars
- 1k
- Forks
- 316
- Last commit
- Oct 2026
Advanced
- Item type
- skill
- Key
oauth-hashgraph-online- Source
- github.com/hashgraph-online/awesome-codex-plugins
github.com/hashgraph-online/awesome-codex-plugins
Related picks
Skill · mattpocock
The pick for TypeScripttypescript-pro
Skill · jeffallan
The pick for TypeScriptslack-gif-creator
Skill · anthropics
The pick for Slackhive.slack-notifications-setup
Skill · aden-hive
The pick for Slacknodejs-backend-patterns
Skill · wshobson
The pick for Noderun-node-tests
Skill · hiroro-work
The pick for Node