Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add proposal for MFA #81

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
388 changes: 388 additions & 0 deletions docs/care/CEP/Draft/0013-mfa.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,388 @@
# CEP-13: Multi-Factor Authentication (MFA) for Enhanced Security in CARE

### Motive

Care is being used in various healthcare environments for managing patient information and care delivery. Security is a critical aspect of healthcare applications, especially when dealing with sensitive patient data. Implementing multi-factor authentication (MFA) in CARE will provide an additional layer of security to protect user accounts and patient information from unauthorized access.

## Phased Implementation Plan

To efficiently implement MFA, we will adopt a phased approach:

### **Phase 1: TOTP and Backup Codes**

- **Primary MFA Method:**
- **TOTP (Time-Based One-Time Password):** Using authenticator apps like Google Authenticator, Authy, etc.
- **Backup Options:**
- **Backup Codes:** One-time use codes provided to users for account recovery.

### **Phase 2: OTP via SMS/Email**

- **Secondary MFA Methods:**
- **OTP via SMS:** One-time passwords sent to the user's registered mobile number.
- **OTP via Email:** One-time passwords sent to the user's registered email address.

### **Phase 3: Passkeys**

- **Future Support:**
- **Passkeys:** Implement passwordless authentication methods using WebAuthn and FIDO2 standards.

## Detailed Requirements

### **Phase 1: TOTP and Backup Codes**

#### **User Flows**

##### **Setup MFA**

- **Initiate Setup:**
- Users navigate to their account settings and select "Enable MFA."
- Password verification is required to proceed.
- **TOTP Setup:**
- The system generates a unique secret key and provisioning URI.
- Users scan a QR code with their authenticator app or enter the secret key manually.
- Users confirm setup by entering a TOTP code from the app.
- **Backup Codes:**
- Users are provided with backup codes to save securely.
- **Notifications:**
- Users receive email notifications upon successful MFA setup.

##### **Login with MFA**

- **Initial Authentication:**
- Users enter their username and password.
- If the user is logging in for the first time after MFA is forced, they are taken to MFA setup.
- **MFA Verification:**
- If MFA is enabled, users are prompted to enter a code from their authenticator app.
- Backup codes can be used if the authenticator app is unavailable.
- **Failed Attempts Handling:**
- After 3 consecutive failed attempts, users receive a warning.
- After 5 consecutive failed attempts, the account is locked for 15 minutes.
- Notification or Email are sent to the user and admin regarding the lockout.

##### **Managing MFA Settings** (Applicable to other phases)

- **Accessing MFA Settings:**
- Users can view their enabled MFA methods in account settings.
- **Disabling MFA:**
- Password verification is required to disable MFA.
- Users cannot disable MFA if enforced by admin policies.
- **Notifications:**
- Users receive email notifications upon changes to MFA settings.

#### **Admin Controls** (Applicable to other phases)

- **Global MFA Enforcement:**
- Superadmins can enforce MFA for all users across the instance.
- Configurable via an environment variable or API endpoint.
- **Facility-Level MFA Enforcement:**
- Facility admins can enforce MFA for all users in their facility.
- Implement a setting in the `Facility` model to indicate enforcement.
- **User-Level MFA Enforcement:**
- Users can enable or disable MFA based on the above policies.
- Users cannot disable MFA if enforced by an admin.

---

### **Phase 2: OTP via SMS/Email**

#### **User Flows**

##### **Setup MFA**

- **Initiate Setup:**
- Users select "Enable SMS/Email MFA" in account settings.
- Password verification is required.
- **Verification:**
- An OTP is sent via the selected method (SMS or Email).
- Users confirm setup by entering the OTP.
- **Notifications:**
- Users receive confirmations upon successful setup.

##### **Login with Secondary MFA**

- **Initial Authentication:**
- Users enter their username and password.
- **MFA Verification:**
- Primary MFA is TOTP, users are provided with a link to other MFA options.
- Users are prompted to enter the OTP received via SMS or Email.
- Option to resend OTP if not received.
- **Failed Attempts Handling:**
- Similar to Phase 1, include warnings and account lockouts.

---

### **Phase 3: Passkeys**

#### **User Flows**

##### **Setup Passkeys**

- **Initiate Setup:**
- Users select "Add Passkeys" in account settings.
- Device and browser compatibility are checked.
- **Registration:**
- Users register their device using WebAuthn standards.
- Cryptographic keys are securely stored.
- **Notifications:**
- Confirmation upon successful setup.

##### **Login with Passkeys**

- **Passwordless Authentication:**
- Users are prompted to use their registered device for authentication.
- **Fallback Options:**
- If passkey authentication fails, fallback to other enabled MFA methods.

---

## Routes and API Endpoints

### **Setup MFA**

#### **Phase 1 Endpoints**

- **Initiate MFA Setup**

```
POST /api/v1/mfa/setup/initiate/
```

```json
{
"password": "user_password"
}
```

- **Get TOTP Setup Info**

```
GET /api/v1/mfa/totp/setup/
```

- Response:

```json
{
"uri": "otpauth://totp/CARE:[email protected]?secret=SECRET&issuer=CARE",
"secret_key": "BASE32SECRET"
}
```

- **Verify TOTP Code**

```
POST /api/v1/mfa/totp/verify/
```

```json
{
"code": "123456"
}
```

- **Generate Backup Codes**

```
POST /api/v1/mfa/backup-codes/generate/
```

- Response:

```json
{
"backup_codes": ["code1", "code2", "code3", "..."]
}
```

#### **Phase 2 Endpoints**

- **Initiate SMS/Email MFA Setup**

```
POST /api/v1/mfa/sms/setup/
POST /api/v1/mfa/email/setup/
```

- **Verify SMS/Email OTP**

```
POST /api/v1/mfa/sms/verify/
POST /api/v1/mfa/email/verify/
```

```json
{
"code": "123456"
}
```

---

### **Login Flow**

- **User Login**

```
POST /api/v1/auth/login/
```

```json
{
"username": "[email protected]",
"password": "user_password"
}
```

- Response if MFA is required:

```json
{
"mfa_required": true,
"temp_token": "temporary_token"
}
```

- **MFA Verification**

```
POST /api/v1/mfa/verify/
```

```json
{
"method": "totp", // "sms", "email", "backup_code"
"code": "123456",
"temp_token": "temporary_token"
}
```

- On success: Issue access and refresh tokens.

---

### **Managing MFA Settings**

- **Retrieve MFA Settings**

```
GET /api/v1/mfa/settings/
```

- Response:

```json
{
"is_mfa_enabled": true,
"is_totp_enabled": true,
"is_sms_enabled": true,
"is_email_enabled": false,
"is_backup_codes_enabled": true,
"enforced_by_admin": false,
"email": "[email protected]",
"phone_number": "+91 9994445638"
}
```

- **Disable MFA Method**

```
POST /api/v1/mfa/disable/
```

```json
{
"method": "totp", // "sms", "email", "backup_code"
"password": "user_password"
}
```

- On success: The selected MFA method is disabled.
- Enforcement policies are checked before disabling.

---

## Models

```python
class TOTPDevice(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='totp_device')
secret_key = models.CharField(max_length=16, unique=True)
confirmed = models.BooleanField(default=False)
```

> Need to check which way to go storing each user backup code as each record vs storing all codes in array field. Each has its own advantages and disadvantages.

```python
class BackupCode(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='backup_codes')
code = models.CharField(max_length=10)
is_used = models.BooleanField(default=False)
```

Adding an `enforce_mfa` field to the existing `Facility` model enables facility admins to enforce MFA for all users in their facility.

```python
class Facility(models.Model):
enforce_mfa = models.BooleanField(default=False)
```

At instance level we either enforce using ENV key or using a model

```python
class MfaConfiguration(models.Model):

    enforce_mfa = models.BooleanField(default=False)
max_failed_login_attempts =
failed_login_lockout_duration =

```

```python
class UserMFASettings(models.Model):

    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='mfa_settings')
    is_mfa_enabled = models.BooleanField(default=False)
    is_totp_enabled = models.BooleanField(default=False)
    is_sms_enabled = models.BooleanField(default=False)
    is_email_enabled = models.BooleanField(default=False)
    is_backup_codes_enabled = models.BooleanField(default=False)

    # Timestamp when MFA was enabled
    enabled_on = models.DateTimeField(auto_now_add=True)
```

> Probably we need to run a tasl=k to clean up failed attempts after x days.

```python
class FailedMfaAttempt(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='failed_attempts')
timestamp = models.DateTimeField(auto_now_add=True)

# Polymorphic relationship to store the method - TOTP, SMS, Email, PassKey
```

Next

- [ ] Which package to use - pyotp or django-two-factor-auth -> for traditional Django templates but can be extendable.
- [ ] I feel I can Improve API route urls names
- [ ] Rate limits and storing keys securly
- [ ] Explore how permissions in Django and Care work and RBAC.
- [ ] Understand model relationships and data types in Django

> Phase -2

- [ ] Understand how does emails work and go in Django
- [ ] Understand How Care plug works and figure out / Can't we do SMS/EMAIL providers configuration from some config ? https://github.com/roaldnefs/django-sms

---

![image](https://gist.github.com/user-attachments/assets/1ef04fac-d382-41f6-9882-f927b312836e)

### References

- [Dump for CEP](https://gist.github.com/yash-learner/b9cd90662d5dfc087f2be9fbc9d23817/)
- [pyotp](https://pypi.org/project/pyotp/)

```

```