colidevs / colidevs/create-coliapp

nextjs-shadcn-ecommerce-admin: admin console has no MFA/passkey, single hardcoded role

Open
#54 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
2
Forks
0
Avg merge
4h 42m
Merged PRs (30d)
43

Description

## Context

Found via a full `api-standard-check`/`frontend-standard-check` audit (ADR 0009-0013, ADR 0019-0024) of
the new `templates/nextjs-shadcn-ecommerce-admin` template, run against the final branch of the
`ecommerce-admin-template` SDD build (PR stack #43-#53, all still open/unmerged at filing time). This
does **not** block that PR stack's review — it's tracked here as follow-up hardening, matching this
repo's existing "detection now, fix later" convention.

## Finding

`apps/api/src/lib/ability.ts`'s `resolveRole()` (lines 82-84) grants **every authenticated session** the
full `"admin"` CASL role — there is no per-user role column, and no viewer/lower-privilege tier is
actually reachable in practice. Auth is `emailAndPassword` only (`src/lib/auth.ts:119-132`); no
passkey/WebAuthn or TOTP plugin is registered anywhere. The same finding shows up independently on the
frontend side (`apps/web/src/lib/ability.ts`'s mirrored `resolveRole`).

This means the entire admin console — catalog CRUD, stock, and order/buyer-PII visibility — sits behind
single-factor password auth with no real authorization tiering. Per ADR 0010
(`api-security-baseline.md`), MFA (or an AAL2-satisfying passkey) is **mandatory for admin/owner roles**,
and per ADR 0013, Passkeys/WebAuthn are already adopted-now for admin-console human sign-in.

A code comment citing `colidevs/munod#44` as precedent exists, but it's not recorded as a formal
`exception` (no `reason`/`approver`/`review_after`), so this stays an open finding rather than an
accepted, time-boxed deviation.

## Related, lower-severity finding bundled here

`apps/api/src/api.ts:71-78`: a single global rate limiter (300 req/15 min) applies uniformly to
`/api/auth/*` and every other route — no auth-endpoint-specific throttle, no CAPTCHA/Turnstile. ADR 0013
calls for tighter, endpoint-specific limits on login/auth flows given their disproportionate abuse value.

## Why this matters for a real client

This template is meant to be scaffolded directly for real client projects (e.g. the Ecuador
storefront+admin project that motivated building it). Shipping it as-is means every real deployment
starts with no real per-user roles and no MFA on the admin console — worth closing before the first real
client goes live, not necessarily before this PR stack merges.

## Suggested fix shape

- Add a real per-user role column/table (mirrors ADR 0013's `user_tenant_roles`-shaped design, minus the
tenant dimension per this template's own single-tenant deviation) and wire `resolveRole()` against it.
- Add Better Auth's `passkey` plugin (already an adopted, named pattern per ADR 0013/0014) for admin
sign-in.
- Add an endpoint-specific rate limit + Turnstile on `/api/auth/*`.

Not fixed in this issue — filing for tracking per the audit's own recommendation.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with ADRs 0010, 0013, and 0014, then inspect apps/api/src/lib/ability.ts, apps/web/src/lib/ability.ts, apps/api/src/lib/auth.ts, and apps/api/src/api.ts. Trace resolveRole(), authentication setup, and the global limiter before deciding how the proposed role, passkey, and auth-endpoint protections fit together. Done means real role-based access, admin MFA or passkey sign-in, and tighter auth throttling with Turnstile.

Written by the indexing model from the issue text.

Assessment

Tech stack
next.js, typescript
Domain
api, authentication, authorization, backend, frontend, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.