Token Upgrade시 챌린지를 거치도록 변경

This commit is contained in:
static
2024-12-31 03:01:29 +09:00
parent 4f20d2edbf
commit b84d6fd5ad
14 changed files with 208 additions and 69 deletions

View File

@@ -90,7 +90,7 @@ export const setUserClientStateToActive = async (userId: number, clientId: numbe
.execute();
};
export const createUserClientChallenge = async (
export const registerUserClientChallenge = async (
userId: number,
clientId: number,
answer: string,

View File

@@ -16,3 +16,16 @@ export const refreshToken = sqliteTable(
unq: unique().on(t.userId, t.clientId),
}),
);
export const tokenUpgradeChallenge = sqliteTable("token_upgrade_challenge", {
id: integer("id").primaryKey(),
refreshTokenId: text("refresh_token_id")
.notNull()
.references(() => refreshToken.id),
clientId: integer("client_id")
.notNull()
.references(() => client.id),
answer: text("challenge").notNull().unique(), // Base64
allowedIp: text("allowed_ip").notNull(),
expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
});

View File

@@ -1,9 +1,9 @@
import { SqliteError } from "better-sqlite3";
import { eq, lte } from "drizzle-orm";
import { and, eq, gt, lte } from "drizzle-orm";
import ms from "ms";
import env from "$lib/server/loadenv";
import db from "./drizzle";
import { refreshToken } from "./schema";
import { refreshToken, tokenUpgradeChallenge } from "./schema";
const expiresIn = ms(env.jwt.refreshExp);
const expiresAt = () => new Date(Date.now() + expiresIn);
@@ -73,3 +73,44 @@ export const revokeRefreshToken = async (tokenId: string) => {
export const cleanupExpiredRefreshTokens = async () => {
await db.delete(refreshToken).where(lte(refreshToken.expiresAt, new Date())).execute();
};
export const registerTokenUpgradeChallenge = async (
tokenId: string,
clientId: number,
answer: string,
allowedIp: string,
expiresAt: Date,
) => {
await db
.insert(tokenUpgradeChallenge)
.values({
refreshTokenId: tokenId,
clientId,
answer,
allowedIp,
expiresAt,
})
.execute();
};
export const getTokenUpgradeChallenge = async (answer: string, ip: string) => {
const challenges = await db
.select()
.from(tokenUpgradeChallenge)
.where(
and(
eq(tokenUpgradeChallenge.answer, answer),
eq(tokenUpgradeChallenge.allowedIp, ip),
gt(tokenUpgradeChallenge.expiresAt, new Date()),
),
)
.execute();
return challenges[0] ?? null;
};
export const cleanupExpiredTokenUpgradeChallenges = async () => {
await db
.delete(tokenUpgradeChallenge)
.where(lte(tokenUpgradeChallenge.expiresAt, new Date()))
.execute();
};