From c1b2773d0fb15bc74c9e45947b12a7b094262a6b Mon Sep 17 00:00:00 2001 From: Ivan Borshchov Date: Fri, 24 Oct 2025 13:41:48 +0000 Subject: [PATCH 1/4] fix: read cookie duration from extra in blc hook --- index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.ts b/index.ts index a087585..3d3bae3 100644 --- a/index.ts +++ b/index.ts @@ -307,8 +307,8 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin { const authResource = adminforth.config.resources.find((res)=>res.resourceId === adminforth.config.auth.usersResourceId ) const authPk = authResource.columns.find((col)=>col.primaryKey).name const userPk = adminUser.dbUser[authPk] - const rememberMe = extra?.body?.rememberMe || false; - const rememberMeDays = rememberMe ? adminforth.config.auth.rememberMeDays || 30 : 1; + + const rememberMeDays = extra?.rememberMeDays; let newSecret = null; const userNeeds2FA = this.options.usersFilterToApply ? this.options.usersFilterToApply(adminUser) : true; From d24c4622127d4ea928404b6d1d1c7fc0000d0486 Mon Sep 17 00:00:00 2001 From: Ivan Borshchov Date: Fri, 24 Oct 2025 13:49:56 +0000 Subject: [PATCH 2/4] chore - use better location for param --- index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.ts b/index.ts index 3d3bae3..f17bf1b 100644 --- a/index.ts +++ b/index.ts @@ -293,7 +293,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin { const beforeLoginConfirmation = this.adminforth.config.auth.beforeLoginConfirmation; const beforeLoginConfirmationArray = Array.isArray(beforeLoginConfirmation) ? beforeLoginConfirmation : [beforeLoginConfirmation]; beforeLoginConfirmationArray.push( - async({ adminUser, response, extra }: { adminUser: AdminUser, response: IAdminForthHttpResponse, extra?: any} )=> { + async({ adminUser, response, extra, rememberMeDays }: { adminUser: AdminUser, response: IAdminForthHttpResponse, extra?: any, rememberMeDays?: number} )=> { if (extra?.body?.loginAllowedByPasskeyDirectSignIn === true) { return { body: { loginAllowed: true }, ok: true }; } @@ -308,7 +308,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin { const authPk = authResource.columns.find((col)=>col.primaryKey).name const userPk = adminUser.dbUser[authPk] - const rememberMeDays = extra?.rememberMeDays; + const useRememberMeDays = rememberMeDays || 1; // default 1 day, but should never happen for new versions let newSecret = null; const userNeeds2FA = this.options.usersFilterToApply ? this.options.usersFilterToApply(adminUser) : true; @@ -321,7 +321,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin { const tempSecret = twofactor.generateSecret({name: issuerName,account: userName}) newSecret = tempSecret.secret; - const totpTemporaryJWT = this.adminforth.auth.issueJWT({userName, newSecret, issuer:issuerName, pk:userPk, userCanSkipSetup, rememberMeDays }, 'temp2FA', this.options.passkeys?.challengeValidityPeriod || '1m'); + const totpTemporaryJWT = this.adminforth.auth.issueJWT({userName, newSecret, issuer:issuerName, pk:userPk, userCanSkipSetup, rememberMeDays: useRememberMeDays }, 'temp2FA', this.options.passkeys?.challengeValidityPeriod || '1m'); this.adminforth.auth.setCustomCookie({response, payload: {name: "2FaTemporaryJWT", value: totpTemporaryJWT, expiry: undefined, expirySeconds: 10 * 60, httpOnly: true}}); return { From 741a6852272c02c444786e5c86feaf55f9980afc Mon Sep 17 00:00:00 2001 From: Ivan Borshchov Date: Fri, 24 Oct 2025 13:52:23 +0000 Subject: [PATCH 3/4] chore: pass rememberMeDays in proceesLoginCallbacks called by passkey login button --- index.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.ts b/index.ts index f17bf1b..b172690 100644 --- a/index.ts +++ b/index.ts @@ -496,6 +496,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin { const toReturn = { allowedLogin: true, error: '' }; + const rememberMeDays = this.options.passkeys.rememberDaysAfterPasskeyLogin ? this.options.passkeys.rememberDaysAfterPasskeyLogin : this.adminforth.config.auth.rememberMeDays; await this.adminforth.restApi.processLoginCallbacks(adminUser, toReturn, response, { headers, cookies, @@ -504,6 +505,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin { body: { loginAllowedByPasskeyDirectSignIn: true }, + rememberMeDays, }); if ( toReturn.allowedLogin === true ) { @@ -511,7 +513,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin { response, username, pk: user.id, - expireInDays: this.options.passkeys.rememberDaysAfterPasskeyLogin ? this.options.passkeys.rememberDaysAfterPasskeyLogin : this.adminforth.config.auth.rememberMeDays, + expireInDays: rememberMeDays, }); } return toReturn; From b4338ad0be96ca018241b9c0c9c7c81a5ad2780e Mon Sep 17 00:00:00 2001 From: Vitalii Date: Mon, 27 Oct 2025 16:16:05 +0200 Subject: [PATCH 4/4] fix: rename rememberMeDays to sessionDuration for consistency in 2FA login flow --- index.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/index.ts b/index.ts index b172690..9a9dc9c 100644 --- a/index.ts +++ b/index.ts @@ -293,7 +293,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin { const beforeLoginConfirmation = this.adminforth.config.auth.beforeLoginConfirmation; const beforeLoginConfirmationArray = Array.isArray(beforeLoginConfirmation) ? beforeLoginConfirmation : [beforeLoginConfirmation]; beforeLoginConfirmationArray.push( - async({ adminUser, response, extra, rememberMeDays }: { adminUser: AdminUser, response: IAdminForthHttpResponse, extra?: any, rememberMeDays?: number} )=> { + async({ adminUser, response, extra, sessionDuration }: { adminUser: AdminUser, response: IAdminForthHttpResponse, extra?: any, sessionDuration?: number} )=> { if (extra?.body?.loginAllowedByPasskeyDirectSignIn === true) { return { body: { loginAllowed: true }, ok: true }; } @@ -308,7 +308,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin { const authPk = authResource.columns.find((col)=>col.primaryKey).name const userPk = adminUser.dbUser[authPk] - const useRememberMeDays = rememberMeDays || 1; // default 1 day, but should never happen for new versions + const useSessionDuration = sessionDuration || 1; // default 1 day, but should never happen for new versions let newSecret = null; const userNeeds2FA = this.options.usersFilterToApply ? this.options.usersFilterToApply(adminUser) : true; @@ -321,7 +321,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin { const tempSecret = twofactor.generateSecret({name: issuerName,account: userName}) newSecret = tempSecret.secret; - const totpTemporaryJWT = this.adminforth.auth.issueJWT({userName, newSecret, issuer:issuerName, pk:userPk, userCanSkipSetup, rememberMeDays: useRememberMeDays }, 'temp2FA', this.options.passkeys?.challengeValidityPeriod || '1m'); + const totpTemporaryJWT = this.adminforth.auth.issueJWT({userName, newSecret, issuer:issuerName, pk:userPk, userCanSkipSetup, sessionDuration: useSessionDuration }, 'temp2FA', this.options.passkeys?.challengeValidityPeriod || '1m'); this.adminforth.auth.setCustomCookie({response, payload: {name: "2FaTemporaryJWT", value: totpTemporaryJWT, expiry: undefined, expirySeconds: 10 * 60, httpOnly: true}}); return { @@ -333,7 +333,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin { } } else { - const value = this.adminforth.auth.issueJWT({userName, issuer:issuerName, pk:userPk, userCanSkipSetup, rememberMeDays }, 'temp2FA', this.options.passkeys?.challengeValidityPeriod || '1m'); + const value = this.adminforth.auth.issueJWT({userName, issuer:issuerName, pk:userPk, userCanSkipSetup, sessionDuration: useSessionDuration }, 'temp2FA', this.options.passkeys?.challengeValidityPeriod || '1m'); this.adminforth.auth.setCustomCookie({response, payload: {name: "2FaTemporaryJWT", value: value, expiry: undefined, expirySeconds: 10 * 60, httpOnly: true}}); return { @@ -389,7 +389,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin { await connector.updateRecord({resource:this.authResource, recordId:decoded.pk, newValues:{[this.options.twoFaSecretFieldName]: decoded.newSecret}}) } this.adminforth.auth.removeCustomCookie({response, name:'2FaTemporaryJWT'}) - this.adminforth.auth.setAuthCookie({expireInDays: decoded.rememberMeDays, response, username:decoded.userName, pk:decoded.pk}) + this.adminforth.auth.setAuthCookie({expireInDays: decoded.sessionDuration, response, username:decoded.userName, pk:decoded.pk}) return { status: 'ok', allowedLogin: true } } else { return {error: 'Wrong or expired OTP code'} @@ -420,7 +420,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin { } if (verified) { this.adminforth.auth.removeCustomCookie({response, name:'2FaTemporaryJWT'}) - this.adminforth.auth.setAuthCookie({expireInDays: decoded.rememberMeDays, response, username:decoded.userName, pk:decoded.pk}) + this.adminforth.auth.setAuthCookie({expireInDays: decoded.sessionDuration, response, username:decoded.userName, pk:decoded.pk}) return { status: 'ok', allowedLogin: true } } else { return {error: 'Verification failed'} @@ -496,7 +496,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin { const toReturn = { allowedLogin: true, error: '' }; - const rememberMeDays = this.options.passkeys.rememberDaysAfterPasskeyLogin ? this.options.passkeys.rememberDaysAfterPasskeyLogin : this.adminforth.config.auth.rememberMeDays; + const sessionDuration = this.options.passkeys.rememberDaysAfterPasskeyLogin ? this.options.passkeys.rememberDaysAfterPasskeyLogin : this.adminforth.config.auth.rememberMeDays; await this.adminforth.restApi.processLoginCallbacks(adminUser, toReturn, response, { headers, cookies, @@ -505,15 +505,14 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin { body: { loginAllowedByPasskeyDirectSignIn: true }, - rememberMeDays, - }); + }, sessionDuration ); if ( toReturn.allowedLogin === true ) { this.adminforth.auth.setAuthCookie({ response, username, pk: user.id, - expireInDays: rememberMeDays, + expireInDays: sessionDuration, }); } return toReturn;