feat(auth): harden authentication with argon2 passwords and rotating hashed refresh tokens
This commit is contained in:
+38
-16
@@ -1,5 +1,6 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import { JwtManager } from './classes.jwtmanager.js';
|
||||
import type { LoginSession } from './classes.loginsession.js';
|
||||
|
||||
/**
|
||||
* a User is identified by its username or email.
|
||||
@@ -11,21 +12,27 @@ export class Jwt extends plugins.smartdata.SmartDataDbDoc<Jwt, plugins.idpInterf
|
||||
public static async createJwtForRefreshToken(
|
||||
jwtManagerInstance: JwtManager,
|
||||
refreshTokenArg: string
|
||||
) {
|
||||
const loginSession =
|
||||
await jwtManagerInstance.receptionRef.loginSessionManager.CLoginSession.getLoginSessionByRefreshToken(
|
||||
): Promise<string | null> {
|
||||
const sessionLookup =
|
||||
await jwtManagerInstance.receptionRef.loginSessionManager.findLoginSessionByRefreshToken(
|
||||
refreshTokenArg
|
||||
);
|
||||
if (!loginSession) {
|
||||
return null;
|
||||
}
|
||||
const refreshTokenValid = await loginSession.validateRefreshToken(refreshTokenArg);
|
||||
if (!refreshTokenValid) {
|
||||
if (!sessionLookup || sessionLookup.validationStatus !== 'current') {
|
||||
return null;
|
||||
}
|
||||
return this.createJwtForLoginSession(jwtManagerInstance, sessionLookup.loginSession);
|
||||
}
|
||||
|
||||
public static async createJwtForLoginSession(
|
||||
jwtManagerInstance: JwtManager,
|
||||
loginSession: LoginSession
|
||||
): Promise<string | null> {
|
||||
const user = await jwtManagerInstance.receptionRef.userManager.CUser.getInstance({
|
||||
id: loginSession.data.userId,
|
||||
});
|
||||
if (!user) {
|
||||
return null;
|
||||
}
|
||||
const validUntil = plugins.smarttime.ExtendedDate.fromMillis(
|
||||
Date.now() + plugins.smarttime.getMilliSecondsFromUnits({ days: 1 })
|
||||
);
|
||||
@@ -33,10 +40,10 @@ export class Jwt extends plugins.smartdata.SmartDataDbDoc<Jwt, plugins.idpInterf
|
||||
jwt.id = plugins.smartunique.shortId();
|
||||
jwt.data = {
|
||||
userId: user.id,
|
||||
sessionId: loginSession.id,
|
||||
validUntil: validUntil.getTime(),
|
||||
refreshEvery: 1000000,
|
||||
refreshFrom: Date.now() + plugins.smarttime.getMilliSecondsFromUnits({ days: 0.5 }),
|
||||
refreshToken: await loginSession.getRefreshToken(), // TODO: handle multiple refresh tokens
|
||||
justForLooks: {
|
||||
validUntilIsoString: validUntil.toISOString(),
|
||||
}
|
||||
@@ -46,7 +53,7 @@ export class Jwt extends plugins.smartdata.SmartDataDbDoc<Jwt, plugins.idpInterf
|
||||
|
||||
const jwtString = await jwtManagerInstance.smartjwtInstance.createJWT({
|
||||
id: jwt.id,
|
||||
blocked: null,
|
||||
blocked: false,
|
||||
data: jwt.data,
|
||||
} as plugins.idpInterfaces.data.IJwt);
|
||||
return jwtString;
|
||||
@@ -68,11 +75,26 @@ export class Jwt extends plugins.smartdata.SmartDataDbDoc<Jwt, plugins.idpInterf
|
||||
}
|
||||
|
||||
public async getLoginSession() {
|
||||
const loginSession = await this.manager.receptionRef.loginSessionManager.CLoginSession.getInstance({
|
||||
data: {
|
||||
refreshToken: this.data.refreshToken,
|
||||
}
|
||||
});
|
||||
return loginSession;
|
||||
if (this.data.sessionId) {
|
||||
return this.manager.receptionRef.loginSessionManager.CLoginSession.getInstance({
|
||||
id: this.data.sessionId,
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.data.refreshToken) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const sessionLookup =
|
||||
await this.manager.receptionRef.loginSessionManager.findLoginSessionByRefreshToken(
|
||||
this.data.refreshToken
|
||||
);
|
||||
|
||||
if (!sessionLookup) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return sessionLookup.loginSession;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user