SDK
Node.js SDK
@authon/node — JWT 검증, 사용자 관리, 모든 Node.js 백엔드 프레임워크와 Authon 통합을 위한 서버 측 SDK.
npm: @authon/nodeNode.js 18+ESM / CJS
설치
bash
npm install @authon/node초기화
단일 AuthonBackend 인스턴스를 생성하여 애플리케이션 전체에서 재사용하세요. secret key를 사용하되 — 클라이언트에 절대 노출하지 마세요.
lib/authon.ts
import { AuthonBackend } from "@authon/node";
export const authon = new AuthonBackend(
process.env.AUTHON_SECRET_KEY!, // sk_live_... or sk_test_...
{
// Optional — override the API base URL
apiUrl: "https://api.authon.dev",
}
);secret key(
sk_live_)를 클라이언트 측에서 절대 사용하지 마세요. 프로젝트에 대한 전체 관리자 접근 권한을 부여합니다.토큰 검증
클라이언트에서 Authorization 헤더로 전송된 JWT 액세스 토큰을 검증합니다. 토큰이 유효하면 전체 사용자 객체를 반환합니다.
ts
import { authon } from "@/lib/authon";
// Verify token and get the AuthonUser
async function getAuthenticatedUser(request: Request) {
const authHeader = request.headers.get("Authorization");
if (!authHeader?.startsWith("Bearer ")) return null;
const token = authHeader.slice(7);
try {
const user = await authon.verifyToken(token);
return user;
} catch {
return null;
}
}
// user is an AuthonUser:
// {
// id, projectId, email, displayName, avatarUrl, phone,
// emailVerified, phoneVerified, isBanned,
// publicMetadata, lastSignInAt, signInCount,
// createdAt, updatedAt
// }사용자 관리
authon.users 네임스페이스는 프로젝트의 사용자에 대한 전체 CRUD 작업을 제공합니다.
users.list()
선택적 검색 필터링으로 사용자를 페이지 단위로 조회합니다.
ts
const result = await authon.users.list({
page: 1, // 1-indexed page number
limit: 20, // results per page (max 100)
search: "john", // search by email or display name
});
// result: { data: AuthonUser[], total: number, page: number, limit: number }
console.log(`${result.total} users, showing page ${result.page}`);users.get()
ts
const user = await authon.users.get("usr_abc123");
console.log(user.email, user.displayName);users.create()
회원가입 흐름 없이 직접 사용자를 생성합니다. 사용자 가져오기나 관리자 계정 생성에 유용합니다.
ts
const user = await authon.users.create({
email: "newuser@example.com",
password: "securepassword", // optional — omit for OAuth-only users
displayName: "New User",
});users.update()
publicMetadata.
ts
const updated = await authon.users.update("usr_abc123", {
displayName: "Updated Name",
publicMetadata: {
plan: "pro",
onboarded: true,
orgId: "org_xyz",
},
});users.delete()
ts
// Permanently delete a user and all associated sessions
await authon.users.delete("usr_abc123");users.ban() / users.unban()
사용자를 차단하면 모든 활성 세션이 취소되고 이후 로그인이 차단됩니다. 사용자 레코드는 보존됩니다 — 영구 삭제는 delete() 를 사용하세요.
ts
// Ban a user (revokes all sessions)
const banned = await authon.users.ban("usr_abc123", "Violated ToS section 4.2");
console.log(banned.isBanned); // true
// Restore a banned user
const unbanned = await authon.users.unban("usr_abc123");
console.log(unbanned.isBanned); // falseExpress 미들웨어
expressMiddleware 메서드는 토큰을 검증하고 req.authonUser.
middleware/auth.ts
import express from "express";
import { authon } from "@/lib/authon";
const app = express();
// Optional — apply globally
app.use(async (req, res, next) => {
const authHeader = req.headers.authorization;
if (authHeader?.startsWith("Bearer ")) {
try {
req.authonUser = await authon.verifyToken(authHeader.slice(7));
} catch {
// Invalid token — req.authonUser remains undefined
}
}
next();
});
// Protected route
app.get("/api/me", (req, res) => {
if (!req.authonUser) {
return res.status(401).json({ error: "Unauthorized" });
}
res.json({ user: req.authonUser });
});
// TypeScript augmentation
declare global {
namespace Express {
interface Request {
authonUser?: import("@authon/shared").AuthonUser;
}
}
}웹훅 검증
authon.webhooks.verify() 로 수신되는 웹훅 페이로드를 검증하세요. 타이밍 공격을 방지하기 위해 시간 안전 비교를 사용합니다.
routes/webhooks.ts
import express from "express";
import { authon } from "@/lib/authon";
const router = express.Router();
// IMPORTANT: use raw body parser for webhook routes
router.post(
"/webhooks/authon",
express.raw({ type: "application/json" }),
(req, res) => {
const signature = req.headers["authon-signature"] as string;
let event: Record<string, unknown>;
try {
event = authon.webhooks.verify(
req.body, // Buffer — raw request body
signature, // "sha256=abc123..."
process.env.AUTHON_WEBHOOK_SECRET!,
);
} catch {
return res.status(401).json({ error: "Invalid signature" });
}
// Process the verified event
switch (event.type) {
case "user.created": {
const user = (event.data as any).user;
console.log("New user signed up:", user.email);
// e.g. add to CRM, send welcome email
break;
}
case "user.banned": {
const user = (event.data as any).user;
console.log("User banned:", user.id);
break;
}
case "session.revoked": {
console.log("Session revoked:", event.id);
break;
}
}
res.json({ received: true });
}
);
export default router;