apache / apache/superset

[SIP-190] Add optional email-based multi-factor authentication (MFA)

Open
#35,829 4 comments 0 reactions 0 assignees View on GitHub
extension-candidate sip
Dominant language
Python
Stars
74.8k
Forks
18.3k
Avg merge
2d 4h
Merged PRs (30d)
664

Description

## [SIP-190] Add optional email-based multi-factor authentication (MFA)

### Motivation

Superset already provides robust authentication mechanisms. The built-in AUTH_DB backend works well, but for smaller deployments or services in pre-release phases, the lack of multi-factor authentication can create compliance gaps and limit adoption.

A common alternative is to rely on enterprise IdPs (LDAP, SSO providers such as Keycloak). However, many smaller self-hosted deployments lack such infrastructure. Without MFA, these deployments may fail compliance checks. Email-based MFA offers a low barrier, out of the box solution.

### Proposed Change
The MFA is going to be email driven since email is a mandatory field for user creation. More on that later.
1. Adding a new feature flag called `ENABLE_MFA`: The user can control whether to enable MFA for their system or not. Also makes sure that existing systems without MFA have a choice to opt out (will be set to False by default).
2. Extending Superset’s configured cache backend to store the otp for a set time (ideally 5 minutes) for logging in.
3. Assigning the Superset provided Public role will allow the admin to exempt users from MFA (enforced this way because superset docs discourage admins from touching the default roles and create separate roles for their custom public roles).
4. Adding a new email configuration key for sending mails for MFA.
5. A resend feature which has a cooldown before the button enables.
### New or Changed Public Interfaces
1. A new view for getting the mfa page:

Image

2. With `/mfa` as the route base, 2 new endpoints will be called: `/verify` and `/resend`. `/resend` will have `check_only` parameter to sync the resend cooldown. The `/verify` has a `GET` method for displaying the mfa page and a `POST` method for OTP verification. `/resend` is only a `POST` call.

3. In case `ENABLE_MFA` is set to false, don't register the view itself. Takes care of itself during deployments.
### New dependencies

No new dependencies

### Migration Plan and Compatibility

ENABLE_MFA`` addition to config.py
`MFA_EMAIL_CONFIG` addition to config.py
No DB schema changes.
No mandatory service dependencies.

### Rejected Alternatives

Other methods of doing mfa were rejected for a subtle reason mentioned: The user email is _mandatory_ for user creation.
TOTP rejection scenario:
Example explanation:
- Lets say 2 companies are working together; company A and B.
- Company A provides metric dashboards to company B using superset and AUTH_DB for authentication.
- Employee X at company B is going to have their email registered with company A naturally. All OTPs are delivered to this email.
- Lets say after some time X leaves company B and this email is deactivated on company's side.
- Until and unless company B intimates company A about this, X can still access all dashboards provided by company A.
- Even if company A is intimated about this change by company B, a lapse or human error can cause company A from not deactivating said account as well.
Email based OTPs, handle this scenario perfectly and deactivating the email by company B will lead to X losing all access to company A superset dashboards.
TLDR: while TOTP provides strong security, it does not consider the user email lifecycle (term makes sense for employees and stuff). If a user leaves their organization but their Superset account is not immediately disabled by the Superset service provider, their authenticator app continues to generate valid codes. However _email_ OTP automatically loses validity when the associated email access is revoked.

SSO/ldp rejection scenario:
- Standard approach in enterprise, but not feasible for small deployments.
- In the case that even enterprise are in a phase where they are trying to tie in all their services under a single SSO, then for the time being, some services could default to compliance breakage.

SMS OTP rejection scenario:
Superset doesn't take phone numbers out of the box for users either, so rejected.

DB based OTP rejection scenario (not entirely rejected actually):
Slow and will cause performance slowdowns if many users hit login at the same time.

Contributor guide

Open the contributing guide

Research direction

Start with config.py to review ENABLE_MFA and MFA_EMAIL_CONFIG, then trace the existing authentication flow and configured cache backend. Inspect the proposed /mfa/verify and /mfa/resend entry points, including Public role exemptions and resend cooldown behavior. Done means optional email OTP login works without schema or dependency changes when the feature is enabled.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
authentication, backend, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.