Skip to content

Feat 21 Two Factor Authentication#89

Open
pdji1602003 wants to merge 55 commits intodevfrom
feat-21-2factor_authentication
Open

Feat 21 Two Factor Authentication#89
pdji1602003 wants to merge 55 commits intodevfrom
feat-21-2factor_authentication

Conversation

@pdji1602003
Copy link
Collaborator

@pdji1602003 pdji1602003 commented Feb 15, 2026

Main Description

This merge request introduces 2fa implementation and third-party login methods.

New User Features

  1. User can go to user menu > Configure Authentication to configure 2fa and enhance account security.
  2. CARE offers one time token via email and TOTP for 2fa.
  3. If user activates both 2fa methods (email & TOTP), user will be directed to a select page after login.
  4. CARE offers three extra third-party login flows: orcid, LDAP, and SAML.
  5. Admin can enable these login flows in the Setting dashboard.
  6. Admin can enforce 2fa in the Setting dashboard.
  7. Terms description about email processing was updated as we now use email to send the one time code.

Note

  1. SAML login flow requires testing.

Known Limitations

  1. Sever needs to be manually restarted if the admin changes any setting about third-login methods (orcid, LDAP, and SAML)
  2. In the 2fa enforcement flow, everyone is impacted, including admins. Consider admin exemption in the 2fa enforcement flow.
  3. Old user data is cleared now via page reload. A data clearing mechanism is needed.
  4. There is no page where user can provide their email.

@pdji1602003 pdji1602003 self-assigned this Feb 16, 2026
@pdji1602003 pdji1602003 linked an issue Feb 16, 2026 that may be closed by this pull request
router.go(0) calls the browser's native history.go(0) under the hood, which forces a full page reload.
This resets the vuex store back to its initial state, ensuring the correct user data is displayed after login.
Without this, there is currently no explicit store reset on logout, which caused the previous user's data to persist into the next session.
…handling method, and streamline loginManagement method
rate limitation is not implemented on backend, so remove the frontend part
Copy link

@melolw melolw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also have a general question because I haven't seen something like limiting the amount to tries? Like if someone tries to brute force all 6 digits possibilities, is there something stopping them?

Overall the code is great! I learned a lot along the way, I have limited knowledge about authentification so most of my questions are things I saw in theory only. I also think it's a great addition to the software, 2FA is such an important feature 😎

/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.changeColumn("user", "email", {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[QUESTION] should this also be in the down function? changing back the column "email" as it was
Also, why are we allowing null for emails?

},
{
key: "system.auth.orcid.clientSecret",
type: "string",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[QUESTION] i'm not very knowledgable about security, but is this (and a few others in this file) fine to put as a string in the database?

// TOTP for 2FA
totpSecret: DataTypes.STRING,
// External login method identifiers
orcidId: DataTypes.STRING,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[question] should we add unique: true here too?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually set the extra rules in the migration files; here we do not need to add unique: true.

*/
exports.generateOTP = function generateOTP() {
// Generate a random 6-digit number (000000 to 999999)
const otp = Math.floor(100000 + Math.random() * 900000).toString();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[suggestion] could we use Node's crypto module? i read here (https://www.boot.dev/blog/javascript/node-js-random-number/) that math.random is not safe and here (https://www.geeksforgeeks.org/node-js/node-js-crypto-randomint-method/) and here (https://www.w3schools.com/nodejs/nodejs_crypto.asp) is a method for generating a random number with crypto

if (typeof raw === "string" && raw.length > 0) {
this.methods = raw.split(",").filter((m) => !!m);
}
// Fallback: just support email/totp if nothing present
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[question] why email/totp? why not only email?

<button
class="btn btn-primary btn-block"
type="submit"
:disabled="!selectedMethod || isSubmitting"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[suggestion] could we add that to the cancel and radio button too? so that the user can't cancel when they are already submitting

"A new verification code has been sent to your Email";

// Start cooldown timer (60 seconds)
this.resendCooldown = 60;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[question] what if they reload the page? is the cooldown also tracked somewhere in the backend? could not find it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Two-factor Authentication

2 participants