mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-07-17 05:43:36 +00:00
refactor(crypto): make system-wrapped DEKs the authoritative key path
DataCrypto and AuthManager now read keys through UserKeyManager: DEKs are always unwrappable server-side, so the in-memory unlock session, DEK-in-JWT wrapping, session-expiry data locks and ALLOW_APIKEY_DATA_UNLOCK are gone. utils/user-crypto.ts is deleted; boot migration now cleans legacy wraps. A one-release shim adopts DEKs from legacy dataKeyWrap tokens so active password users migrate without re-login. Password login migrates legacy password-wrapped DEKs via migratePasswordUserAtLogin.
This commit is contained in:
@@ -49,10 +49,6 @@ vi.mock("../../utils/data-crypto.js", () => ({
|
||||
DataCrypto: { getInstance: () => ({ encrypt: vi.fn(), decrypt: vi.fn() }) },
|
||||
}));
|
||||
|
||||
vi.mock("../../utils/user-crypto.js", () => ({
|
||||
UserCrypto: { getInstance: () => ({ getUserKey: vi.fn() }) },
|
||||
}));
|
||||
|
||||
vi.mock("../repositories/factory.js", () => ({
|
||||
createCurrentTermixIdentityCaRepository: vi.fn(() => ({
|
||||
findPublicByIdentityId: vi.fn(),
|
||||
|
||||
@@ -119,40 +119,6 @@ export function registerUserOidcAccountRoutes(
|
||||
scopes: oidcUser.scopes || "openid email profile",
|
||||
});
|
||||
|
||||
try {
|
||||
await authManager.convertToOIDCEncryption(targetUser.id);
|
||||
} catch (encryptionError) {
|
||||
authLogger.error(
|
||||
"Failed to convert encryption to OIDC during linking",
|
||||
encryptionError,
|
||||
{
|
||||
operation: "link_convert_encryption_failed",
|
||||
userId: targetUser.id,
|
||||
},
|
||||
);
|
||||
await userRepository.update(targetUser.id, {
|
||||
isOidc: false,
|
||||
oidcIdentifier: null,
|
||||
clientId: "",
|
||||
clientSecret: "",
|
||||
issuerUrl: "",
|
||||
authorizationUrl: "",
|
||||
tokenUrl: "",
|
||||
identifierPath: "",
|
||||
namePath: "",
|
||||
scopes: "openid email profile",
|
||||
});
|
||||
|
||||
return res.status(500).json({
|
||||
error:
|
||||
"Failed to convert encryption for dual-auth. Please ensure the password account has encryption setup.",
|
||||
details:
|
||||
encryptionError instanceof Error
|
||||
? encryptionError.message
|
||||
: "Unknown error",
|
||||
});
|
||||
}
|
||||
|
||||
await authManager.revokeAllUserSessions(oidcUserId);
|
||||
authManager.logoutUser(oidcUserId);
|
||||
|
||||
|
||||
@@ -251,8 +251,6 @@ export function registerUserWebAuthnRoutes(
|
||||
(req.body?.response as RegistrationResponseJSON | undefined)?.response
|
||||
?.transports ?? [];
|
||||
|
||||
await authManager.setupWebAuthnUserEncryption(userId);
|
||||
|
||||
const name =
|
||||
typeof req.body?.name === "string" && req.body.name.trim()
|
||||
? req.body.name.trim().slice(0, 80)
|
||||
|
||||
@@ -1508,18 +1508,6 @@ router.post("/login", async (req, res) => {
|
||||
return res.status(401).json({ error: "Invalid username or password" });
|
||||
}
|
||||
|
||||
try {
|
||||
const kekSalt = await createCurrentSettingsRepository().get(
|
||||
`user_kek_salt_${userRecord.id}`,
|
||||
);
|
||||
|
||||
if (!kekSalt) {
|
||||
await authManager.registerUser(userRecord.id, password);
|
||||
}
|
||||
} catch {
|
||||
// expected - KEK salt registration may fail for existing users
|
||||
}
|
||||
|
||||
const deviceInfo = parseUserAgent(req);
|
||||
|
||||
let dataUnlocked = false;
|
||||
|
||||
Reference in New Issue
Block a user