Aman-Mittal opened a new issue, #369:
URL: https://github.com/apache/fineract-backoffice-ui/issues/369
## Summary
`settings/two-factor-config.component.ts` lets an administrator configure
two-factor
authentication. Nothing in the login flow honours it. Turn it on and **every
screen breaks**:
sign-in still appears to succeed, and then every request the application
makes returns 403.
The application ships the switch for a feature it cannot then survive.
## Reproduced against a real Fineract
Restart the e2e backend with 2FA on:
```yaml
# deploy/docker-compose-e2e.yml → fineract-backend → environment
- FINERACT_SECURITY_2FA_ENABLED=true
```
Then, authenticated as `mifos` (who holds `ALL_FUNCTIONS`):
| Request | 2FA off | 2FA on |
|---|---|---|
| `GET /v1/offices` | 200 | **403** |
| `GET /v1/clients` | 200 | **403** |
| `GET /v1/loans` | 200 | **403** |
| `GET /v1/glaccounts` | 200 | **403** |
| `GET /v1/twofactor/configure` | 404 | **403** |
| `GET /v1/twofactor` | 404 | **200** |
Only `/v1/twofactor` answers. Everything else is refused until a second
factor is validated —
including the configuration screen the application already has.
And `POST /v1/authentication` grows a field the client never reads:
```jsonc
{
"username": "mifos",
"authenticated": true, // ← the UI believes it is done here
"base64EncodedAuthenticationKey": "…",
"permissions": ["ALL_FUNCTIONS", …],
"shouldRenewPassword": false,
"isTwoFactorAuthenticationRequired": true // ← never inspected
}
```
`AuthService.login()` stores the session and reports success on
`authenticated: true`. The user
lands on the dashboard, every widget 403s, and — since #368 — those 403s are
correctly reported as
"you do not have permission". Which is *true*, and completely unactionable:
the user holds every
permission Fineract defines. There is no way forward from that screen and no
way to reach the
configuration page to turn it back off, because that 403s too.
## Business Value
- **A configuration screen that bricks the product is worse than no screen
at all.** An
administrator enabling 2FA — a control their own security review very
likely asked for — takes
the institution offline, with no in-product way back. The recovery is a
backend restart with an
environment variable, which is not something a branch can do.
- **2FA is table stakes for a security review of a core-banking back
office.** Its absence is a
finding on its own; shipping the configuration for it while the login
cannot honour it is a
worse finding, because it reads as an implemented control that does not
work.
- **The endpoints already exist and are already in the generated client.**
The remaining work is a
login step and one header, not a platform integration.
## The contract
All six operations are already generated. Four in `TwoFactorService`:
| Operation | Endpoint | Purpose |
|---|---|---|
| `getTwofactor()` | `GET /v1/twofactor` | delivery methods available to
this user |
| `postTwofactor(deliveryMethod, extendedToken)` | `POST /v1/twofactor` |
send the one-time token |
| `postTwofactorValidate()` | `POST /v1/twofactor/validate` | exchange the
token for a TFA token |
| `postTwofactorInvalidate()` | `POST /v1/twofactor/invalidate` | end the
second factor |
and two on `DefaultService` — `getTwofactorConfigure()` /
`putTwofactorConfigure()`
(`GET`/`PUT /v1/twofactor/configure`), which the existing settings screen
already calls.
`GET /v1/twofactor` on the seeded tenant returns:
```json
[{ "name": "email", "target": "[email protected]" }]
```
The validated token then travels on subsequent requests. That header is
**not** currently set by
`auth.interceptor.ts`, which only attaches `Authorization`.
## Scope
- `AuthService.login()` must branch on `isTwoFactorAuthenticationRequired`
rather than treat
`authenticated: true` as the end of the flow.
- A second-factor step in the login feature: choose a delivery method,
request the token, submit
it, handle expiry and a wrong code without dropping the first factor.
- The validated TFA token joins the session and is sent on every subsequent
request, alongside the
existing `Authorization` header, from the same interceptor.
- Sign-out should invalidate it (`POST /v1/twofactor/invalidate`), not just
drop it locally.
- The existing settings screen should be reachable *after* the second
factor, and should say
plainly what enabling this does — it is currently a switch with no warning
attached.
- A deployment with 2FA off must behave exactly as it does today. That is
the regression risk.
## Tests — required, not optional
**Unit.** `auth.service.spec.ts` and the login component:
`isTwoFactorAuthenticationRequired` true
and false; a wrong token; an expired token; the session carrying the TFA
token; sign-out
invalidating it. The interceptor spec must cover the header being attached
when a TFA token exists
and absent when it does not.
**E2E, mocked** — a new spec beside `e2e/rbac-route-protection.spec.ts`,
mocking
`POST /v1/authentication` to return `isTwoFactorAuthenticationRequired:
true`. This is where the
matrix belongs, because it needs no mail server: the second-factor step
appears, a wrong code is
rejected without losing the session, a correct one lands on the dashboard,
and with the flag absent
the login flow is unchanged.
**E2E, real backend** — one spec proving the flow against Fineract with
`FINERACT_SECURITY_2FA_ENABLED=true`. Two things make this awkward and both
have answers:
- The stack has no SMTP, so `POST /v1/twofactor?deliveryMethod=email`
returns **500**. The token is
written to `twofactor_access_token` (`token`, `appuser_id`, `valid_from`,
`valid_to`, `enabled`)
regardless — read it the way the suite already reaches the database,
rather than adding a mail
catcher.
- 2FA is process-wide, so it cannot be toggled per test. It needs its own
compose override and its
own project in `playwright.config.ts`, kept out of the default run.
**Regression.** The full suite must stay green with 2FA off. That is the
case that protects every
existing deployment.
## Documentation
- `DOCS/` — how the second factor works, what the TFA token is, how to
enable it locally, and how
to run the real-backend spec. `DOCS/RBAC.md` is the model for the level of
detail.
- The security policy should record 2FA as supported once it is, since its
absence is currently a
reasonable finding against the product.
- A migration note: deployments that have *already* enabled 2FA on the
backend are broken today and
will be fixed by this, which is worth saying out loud rather than leaving
to be discovered.
## Out of scope
OIDC / external identity login, which is a separate gap with a separate
failure mode. Filed
separately.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]