132 lines
2.9 KiB
TypeScript
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);
|