mirror of
https://github.com/khoaliber/dockhand.git
synced 2026-03-07 05:40:11 +00:00
Initial commit
This commit is contained in:
117
routes/api/auth/login/+server.ts
Normal file
117
routes/api/auth/login/+server.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
import {
|
||||
authenticateLocal,
|
||||
authenticateLdap,
|
||||
getEnabledLdapConfigs,
|
||||
createUserSession,
|
||||
isRateLimited,
|
||||
recordFailedAttempt,
|
||||
clearRateLimit,
|
||||
verifyMfaToken,
|
||||
isAuthEnabled
|
||||
} from '$lib/server/auth';
|
||||
import { getUser, getUserByUsername } from '$lib/server/db';
|
||||
|
||||
// POST /api/auth/login - Authenticate user
|
||||
export const POST: RequestHandler = async ({ request, cookies, getClientAddress }) => {
|
||||
// Check if auth is enabled
|
||||
if (!(await isAuthEnabled())) {
|
||||
return json({ error: 'Authentication is not enabled' }, { status: 400 });
|
||||
}
|
||||
|
||||
try {
|
||||
const { username, password, mfaToken, provider = 'local' } = await request.json();
|
||||
|
||||
if (!username || !password) {
|
||||
return json({ error: 'Username and password are required' }, { status: 400 });
|
||||
}
|
||||
|
||||
// Rate limiting by IP and username
|
||||
const clientIp = getClientAddress();
|
||||
const rateLimitKey = `${clientIp}:${username}`;
|
||||
|
||||
const { limited, retryAfter } = isRateLimited(rateLimitKey);
|
||||
if (limited) {
|
||||
return json(
|
||||
{ error: `Too many login attempts. Please try again in ${retryAfter} seconds.` },
|
||||
{ status: 429 }
|
||||
);
|
||||
}
|
||||
|
||||
// Attempt authentication based on provider
|
||||
let result: any;
|
||||
let authProviderType: 'local' | 'ldap' | 'oidc' = 'local';
|
||||
|
||||
if (provider.startsWith('ldap:')) {
|
||||
// LDAP provider with specific config ID (e.g., "ldap:1")
|
||||
const configId = parseInt(provider.split(':')[1], 10);
|
||||
result = await authenticateLdap(username, password, configId);
|
||||
authProviderType = 'ldap';
|
||||
} else if (provider === 'ldap') {
|
||||
// Generic LDAP (will try all enabled configs)
|
||||
result = await authenticateLdap(username, password);
|
||||
authProviderType = 'ldap';
|
||||
} else {
|
||||
result = await authenticateLocal(username, password);
|
||||
authProviderType = 'local';
|
||||
}
|
||||
|
||||
if (!result.success) {
|
||||
recordFailedAttempt(rateLimitKey);
|
||||
return json({ error: result.error || 'Authentication failed' }, { status: 401 });
|
||||
}
|
||||
|
||||
// Handle MFA if required
|
||||
if (result.requiresMfa) {
|
||||
if (!mfaToken) {
|
||||
// Return that MFA is required
|
||||
return json({ requiresMfa: true }, { status: 200 });
|
||||
}
|
||||
|
||||
// Verify MFA token
|
||||
const user = await getUserByUsername(username);
|
||||
if (!user || !(await verifyMfaToken(user.id, mfaToken))) {
|
||||
recordFailedAttempt(rateLimitKey);
|
||||
return json({ error: 'Invalid MFA code' }, { status: 401 });
|
||||
}
|
||||
|
||||
// MFA verified, create session
|
||||
const session = await createUserSession(user.id, authProviderType, cookies);
|
||||
clearRateLimit(rateLimitKey);
|
||||
|
||||
return json({
|
||||
success: true,
|
||||
user: {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
email: user.email,
|
||||
displayName: user.displayName,
|
||||
isAdmin: user.isAdmin
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// No MFA, create session directly
|
||||
if (result.user) {
|
||||
const session = await createUserSession(result.user.id, authProviderType, cookies);
|
||||
clearRateLimit(rateLimitKey);
|
||||
|
||||
return json({
|
||||
success: true,
|
||||
user: {
|
||||
id: result.user.id,
|
||||
username: result.user.username,
|
||||
email: result.user.email,
|
||||
displayName: result.user.displayName,
|
||||
isAdmin: result.user.isAdmin
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return json({ error: 'Authentication failed' }, { status: 401 });
|
||||
} catch (error) {
|
||||
console.error('Login error:', error);
|
||||
return json({ error: 'Login failed' }, { status: 500 });
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user