lablup / lablup/backend.ai

Make TOTP OTP enforcement configurable per authentication path (password vs hook/sToken)

Open
#11,205 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
670
Forks
183
Avg merge
17h 7m
Merged PRs (30d)
358

Description

## Background

When the keypair auth plugin and the TOTP plugin are both active, a TOTP-enabled user can authenticate via two different paths during the AUTHORIZE phase:

- \***Password-based login**\* — the user proves identity with a password.

- \***Hook-authenticated login (sToken / token-login)**\* — an AUTHORIZE hook plugin authenticates the user directly (SSO / edu-app redirect). When the hook returns a user, that user is already trusted.

Today the TOTP plugin's POST_AUTHORIZE handler (`validate_otp`) enforces OTP unconditionally for every TOTP-activated user, with no awareness of which auth path was taken in AUTHORIZE. As a result, hook-authenticated logins (which have no UI to input an OTP code) are required to provide an OTP and cannot complete. This is not a defect in a single flow but a missing capability: there is no way to express which authentication paths should trigger TOTP enforcement.

## Goal

Allow operators to configure, per authentication path, whether the TOTP plugin enforces OTP verification. For example, enforce TOTP on password-based logins while skipping it on hook-authenticated (sToken) logins, or any other combination the deployment requires.

## Scope

- Introduce a TOTP plugin configuration option (`TOTPConfig`) that selects which auth methods OTP verification applies to (e.g. `password`, `hook`).

- Propagate the authentication method determined in the AUTHORIZE phase down to the POST_AUTHORIZE hook so the plugin can make the decision. In `_verify_user`, a non-empty hook result means the user was hook-authenticated; otherwise the user was password-authenticated.

- `validate_otp` consults the configured set of enforced auth methods before requiring/validating OTP.

## Relevant Code

- `src/ai/backend/manager/plugin/totp/hook.py` — `validate_otp` (POST_AUTHORIZE handler) and `TOTPConfig`.

- `src/ai/backend/manager/services/auth/service.py` — `_verify_user` (AUTHORIZE dispatch; distinguishes hook vs password auth) and `_post_check` (POST_AUTHORIZE dispatch; currently passes no auth-method signal).

- `src/ai/backend/web/server.py` — `token_login_handler` (sToken token-login path).

## Acceptance Criteria

- TOTP enforcement can be configured per authentication path via plugin config.

- With the default/recommended configuration, a TOTP-enabled user logging in via sToken succeeds without OTP input, while password-based login of the same user still requires OTP.

- Behavior is driven by configuration, not hardcoded per-flow special-casing.

## Related

- BA-5791: Fix TOTP login failure due to OTP value leaking into sToken (separate bug, already fixed).

JIRA Issue: BA-5792

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.