Files
wishlist/src/auth.ts
2025-12-19 20:50:06 +01:00

132 lines
2.9 KiB
TypeScript

import { SvelteKitAuth } from '@auth/sveltekit';
import { DrizzleAdapter } from '@auth/drizzle-adapter';
import Credentials from '@auth/core/providers/credentials';
import Google from '@auth/core/providers/google';
import type { OAuthConfig } from '@auth/core/providers';
import { db } from '$lib/server/db';
import { users } from '$lib/server/schema';
import { eq } from 'drizzle-orm';
import bcrypt from 'bcrypt';
import { env } from '$env/dynamic/private';
import type { SvelteKitAuthConfig } from '@auth/sveltekit';
function Authentik(config: {
clientId: string;
clientSecret: string;
issuer: string;
}): OAuthConfig<any> {
return {
id: 'authentik',
name: 'Authentik',
type: 'oidc',
clientId: config.clientId,
clientSecret: config.clientSecret,
issuer: config.issuer,
authorization: {
params: {
scope: 'openid email profile'
}
},
profile(profile) {
return {
id: profile.sub,
email: profile.email,
name: profile.name || profile.preferred_username,
image: profile.picture
};
}
};
}
const authConfig: SvelteKitAuthConfig = {
adapter: DrizzleAdapter(db),
session: {
strategy: 'jwt'
},
providers: [
...(env.GOOGLE_CLIENT_ID && env.GOOGLE_CLIENT_SECRET
? [
Google({
clientId: env.GOOGLE_CLIENT_ID,
clientSecret: env.GOOGLE_CLIENT_SECRET
})
]
: []),
...(env.AUTHENTIK_CLIENT_ID && env.AUTHENTIK_CLIENT_SECRET && env.AUTHENTIK_ISSUER
? [
Authentik({
clientId: env.AUTHENTIK_CLIENT_ID,
clientSecret: env.AUTHENTIK_CLIENT_SECRET,
issuer: env.AUTHENTIK_ISSUER
})
]
: []),
Credentials({
id: 'credentials',
name: 'credentials',
credentials: {
username: { label: 'Username', type: 'text' },
password: { label: 'Password', type: 'password' }
},
async authorize(credentials) {
if (!credentials?.username || !credentials?.password) {
return null;
}
const user = await db.query.users.findFirst({
where: eq(users.username, credentials.username as string)
});
if (!user || !user.password) {
return null;
}
const isValidPassword = await bcrypt.compare(
credentials.password as string,
user.password
);
if (!isValidPassword) {
return null;
}
return {
id: user.id,
email: user.email || undefined,
name: user.name,
image: user.image
};
}
})
],
pages: {
signIn: '/signin'
},
callbacks: {
async signIn({ user }) {
if (user?.id) {
await db.update(users)
.set({ lastLogin: new Date() })
.where(eq(users.id, user.id));
}
return true;
},
async jwt({ token, user }) {
if (user) {
token.id = user.id;
}
return token;
},
async session({ session, token }) {
if (token && session.user) {
session.user.id = token.id as string;
}
return session;
}
},
secret: env.AUTH_SECRET,
trustHost: true
};
export const { handle, signIn, signOut } = SvelteKitAuth(authConfig);