server/plugins/openid/routes/oauth/revoke.ts
Jesse Wierzbinski 58342e86e1
refactor(api): ♻️ Move from @hono/zod-openapi to hono-openapi
hono-openapi is easier to work with and generates better OpenAPI definitions
2025-03-29 03:30:06 +01:00

93 lines
3.2 KiB
TypeScript

import { handleZodError, jsonOrForm } from "@/api";
import { Token, db } from "@versia/kit/db";
import { and, eq } from "@versia/kit/drizzle";
import { Tokens } from "@versia/kit/tables";
import { describeRoute } from "hono-openapi";
import { resolver, validator } from "hono-openapi/zod";
import { z } from "zod";
import type { PluginType } from "../../index.ts";
export default (plugin: PluginType): void => {
plugin.registerRoute("/oauth/revoke", (app) => {
app.post(
"/oauth/revoke",
describeRoute({
summary: "Revoke token",
tags: ["OpenID"],
responses: {
200: {
description: "Token deleted",
content: {
"application/json": {
schema: resolver(z.object({})),
},
},
},
401: {
description: "Authorization error",
content: {
"application/json": {
schema: resolver(
z.object({
error: z.string(),
error_description: z.string(),
}),
),
},
},
},
},
}),
jsonOrForm(),
plugin.middleware,
validator(
"json",
z.object({
client_id: z.string(),
client_secret: z.string(),
token: z.string().optional(),
}),
handleZodError,
),
async (context) => {
const { client_id, client_secret, token } =
context.req.valid("json");
const foundToken = await Token.fromSql(
and(
eq(Tokens.accessToken, token ?? ""),
eq(Tokens.clientId, client_id),
),
);
if (!(foundToken && token)) {
return context.json(
{
error: "unauthorized_client",
error_description:
"You are not authorized to revoke this token",
},
401,
);
}
// Check if the client secret is correct
if (foundToken.data.application?.secret !== client_secret) {
return context.json(
{
error: "unauthorized_client",
error_description:
"You are not authorized to revoke this token",
},
401,
);
}
await db.delete(Tokens).where(eq(Tokens.accessToken, token));
return context.json({}, 200);
},
);
});
};