Add local username/password login as fallback when Microsoft login isn't available
Neues "users"-Table (bcrypt-Hash, nie Klartext), POST /api/auth/login gibt ein selbst-signiertes JWT (HS256) aus. requireAuth unterscheidet MSAL- (RS256) und lokale Tokens (HS256) anhand des alg-Headers. Server legt beim Start optional ein erstes lokales Konto an, wenn SEED_ADMIN_USERNAME/SEED_ADMIN_PASSWORD als Stack-Env gesetzt sind (idempotent, Klartext-Passwort landet nie im Repo). Frontend: Login-Screen hat jetzt einen Alternativ-Link zu Benutzername/Passwort, App.tsx kombiniert MSAL- und lokalen Auth-Status. Temporärer test-build-only.yml Workflow zur Docker-Build-Verifikation ohne Registry-Push (wird nach dem Test wieder entfernt). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
7bdf4f2897
commit
97c4aa1c68
@@ -0,0 +1,35 @@
|
||||
import { Router } from 'express';
|
||||
import bcrypt from 'bcryptjs';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { prisma } from '../prisma.js';
|
||||
import { JWT_SECRET } from '../auth.js';
|
||||
|
||||
export const authRouter = Router();
|
||||
|
||||
authRouter.post('/login', async (req, res) => {
|
||||
const { username, password } = req.body ?? {};
|
||||
if (!username || !password) {
|
||||
res.status(400).json({ error: 'Benutzername und Passwort erforderlich.' });
|
||||
return;
|
||||
}
|
||||
if (!JWT_SECRET) {
|
||||
res.status(500).json({ error: 'JWT_SECRET ist serverseitig nicht konfiguriert.' });
|
||||
return;
|
||||
}
|
||||
const user = await prisma.user.findUnique({ where: { username } });
|
||||
if (!user) {
|
||||
res.status(401).json({ error: 'Benutzername oder Passwort falsch.' });
|
||||
return;
|
||||
}
|
||||
const ok = await bcrypt.compare(password, user.passwordHash);
|
||||
if (!ok) {
|
||||
res.status(401).json({ error: 'Benutzername oder Passwort falsch.' });
|
||||
return;
|
||||
}
|
||||
const token = jwt.sign(
|
||||
{ username: user.username, name: user.name ?? user.username },
|
||||
JWT_SECRET,
|
||||
{ algorithm: 'HS256', expiresIn: '30d' }
|
||||
);
|
||||
res.json({ token, name: user.name ?? user.username });
|
||||
});
|
||||
Reference in New Issue
Block a user