diff options
| author | MohamedBassem <me@mbassem.com> | 2024-03-05 13:11:06 +0000 |
|---|---|---|
| committer | MohamedBassem <me@mbassem.com> | 2024-03-05 13:11:06 +0000 |
| commit | 8a46ecb7373d6c5e7300861169ea51a7917cd2b4 (patch) | |
| tree | 4ad318c3b5fc8b7a74cba6d0e37b6ade24db829a /packages/web/server/auth.ts | |
| parent | 224aa38d5976523f213e2860b6addc7630d472ba (diff) | |
| download | karakeep-8a46ecb7373d6c5e7300861169ea51a7917cd2b4.tar.zst | |
refactor: Extract trpc logic into its package
Diffstat (limited to 'packages/web/server/auth.ts')
| -rw-r--r-- | packages/web/server/auth.ts | 100 |
1 files changed, 1 insertions, 99 deletions
diff --git a/packages/web/server/auth.ts b/packages/web/server/auth.ts index 1810c87d..950443b9 100644 --- a/packages/web/server/auth.ts +++ b/packages/web/server/auth.ts @@ -2,15 +2,13 @@ import NextAuth, { NextAuthOptions, getServerSession } from "next-auth"; import type { Adapter } from "next-auth/adapters"; import AuthentikProvider from "next-auth/providers/authentik"; import serverConfig from "@hoarder/shared/config"; +import { validatePassword } from "@hoarder/trpc/auth"; import { db } from "@hoarder/db"; import { DefaultSession } from "next-auth"; -import * as bcrypt from "bcrypt"; import CredentialsProvider from "next-auth/providers/credentials"; import { DrizzleAdapter } from "@auth/drizzle-adapter"; -import { randomBytes } from "crypto"; import { Provider } from "next-auth/providers/index"; -import { apiKeys } from "@hoarder/db/schema"; declare module "next-auth/jwt" { export interface JWT { @@ -96,99 +94,3 @@ export const authOptions: NextAuthOptions = { export const authHandler = NextAuth(authOptions); export const getServerAuthSession = () => getServerSession(authOptions); - -// API Keys - -const BCRYPT_SALT_ROUNDS = 10; -const API_KEY_PREFIX = "ak1"; - -export async function generateApiKey(name: string, userId: string) { - const id = randomBytes(10).toString("hex"); - const secret = randomBytes(10).toString("hex"); - const secretHash = await bcrypt.hash(secret, BCRYPT_SALT_ROUNDS); - - const plain = `${API_KEY_PREFIX}_${id}_${secret}`; - - const key = ( - await db - .insert(apiKeys) - .values({ - name: name, - userId: userId, - keyId: id, - keyHash: secretHash, - }) - .returning() - )[0]; - - return { - id: key.id, - name: key.name, - createdAt: key.createdAt, - key: plain, - }; -} - -function parseApiKey(plain: string) { - const parts = plain.split("_"); - if (parts.length != 3) { - throw new Error( - `Malformd API key. API keys should have 3 segments, found ${parts.length} instead.`, - ); - } - if (parts[0] !== API_KEY_PREFIX) { - throw new Error(`Malformd API key. Got unexpected key prefix.`); - } - return { - keyId: parts[1], - keySecret: parts[2], - }; -} - -export async function authenticateApiKey(key: string) { - const { keyId, keySecret } = parseApiKey(key); - const apiKey = await db.query.apiKeys.findFirst({ - where: (k, { eq }) => eq(k.keyId, keyId), - with: { - user: true, - }, - }); - - if (!apiKey) { - throw new Error("API key not found"); - } - - const hash = apiKey.keyHash; - - const validation = await bcrypt.compare(keySecret, hash); - if (!validation) { - throw new Error("Invalid API Key"); - } - - return apiKey.user; -} - -export async function hashPassword(password: string) { - return bcrypt.hash(password, BCRYPT_SALT_ROUNDS); -} - -export async function validatePassword(email: string, password: string) { - const user = await db.query.users.findFirst({ - where: (u, { eq }) => eq(u.email, email), - }); - - if (!user) { - throw new Error("User not found"); - } - - if (!user.password) { - throw new Error("This user doesn't have a password defined"); - } - - const validation = await bcrypt.compare(password, user.password); - if (!validation) { - throw new Error("Wrong password"); - } - - return user; -} |
