fix: SSO-MFA-Umgehung, Datei-Magic-Bytes und oeffentliches Swagger geschlossen
Weitere vom Sicherheitsaudit gemeldete Luecken behoben, die bisher als niedrige Prioritaet offen gelassen wurden: - SSO-Login (Entra ID) prüft jetzt lokale MFA genauso wie der Passwort-Login: ist mfaEnabled gesetzt, liefert /auth/sso/complete denselben mfaRequired-Codepfad wie /auth/login, bevor Tokens ausgestellt werden. Frontend (Login-Seite, AuthContext) zeigt in dem Fall den bestehenden Code-Eingabe-Schritt statt die Anmeldung stillschweigend abzuschliessen. - Avatar- und Dokument-Uploads pruefen jetzt die tatsaechlichen Datei-Bytes (Magic Numbers fuer PNG/JPEG/WEBP/PDF) statt nur dem client-angegebenen MIME-Typ/data:-URL-Praefix zu vertrauen. - Swagger-UI (/api/v1/docs) ist jetzt standardmaessig deaktiviert (ENABLE_SWAGGER=true erforderlich), da sie zuvor das komplette API-Schema ungeschuetzt oeffentlich preisgab. npm-audit-Warnungen (deepmerge-ts/mysql2 unter prisma) bewusst nicht gefixt: kein stabiles Prisma-Release loest sie bislang auf, nur eine Release-Candidate-Hauptversion - das Risiko eines Downgrades/RC-Upgrades der Datenbankschicht uebersteigt den Nutzen fuer eine Kette, die zur Laufzeit ohnehin nicht erreichbar ist (nur Prisma-CLI, nur MySQL-Treiber, dieses Projekt nutzt Postgres). Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
1 parent
1b16b49913
commit
b7ff92abd3
16 files changed
+225
-28
No files matched your search
@@ -144,12 +144,24 @@ export class AuthService {
|
||||
return { mfaRequired: false, accessToken, refreshToken };
|
||||
}
|
||||
|
||||
/** Issues our own access/refresh token pair for a user already authenticated via SSO. */
|
||||
async issueTokensForSsoUser(userId: string): Promise<AuthTokens> {
|
||||
/**
|
||||
* Issues our own access/refresh token pair for a user already
|
||||
* authenticated via SSO. Local MFA is still enforced here, same as
|
||||
* password login: SSO establishes identity, not the second factor, so a
|
||||
* user who has explicitly enabled TOTP must complete it here too rather
|
||||
* than getting it silently skipped by signing in via Microsoft instead.
|
||||
*/
|
||||
async issueTokensForSsoUser(userId: string): Promise<LoginResult> {
|
||||
const user = await this.usersService.findById(userId);
|
||||
if (!user.isActive) {
|
||||
throw new UnauthorizedException('Invalid credentials');
|
||||
}
|
||||
if (user.mfaEnabled) {
|
||||
return {
|
||||
mfaRequired: true,
|
||||
mfaToken: this.mfaService.signChallengeToken(user.id),
|
||||
};
|
||||
}
|
||||
const accessToken = this.signAccessToken({
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
@@ -161,7 +173,7 @@ export class AuthService {
|
||||
action: 'LOGIN',
|
||||
userId: user.id,
|
||||
});
|
||||
return { accessToken, refreshToken };
|
||||
return { mfaRequired: false, accessToken, refreshToken };
|
||||
}
|
||||
|
||||
async verifyMfaAndLogin(mfaToken: string, code: string): Promise<AuthTokens> {
|
||||
|
||||
Reference in new issue
Block a user