Appearance
Historical snapshot archived 2026-09-25. This records an earlier review or plan, not current implementation or live ticket state. For current work, follow root AGENTS.md, the relevant BloxClips skill, and owning repository source/tests. Preserve approved decisions as evidence; verify their present authority before acting.
Authentication and Authorization
Authentication
Login flow
mermaid
sequenceDiagram
actor U as User
participant F as Frontend /login
participant B as Backend auth router
participant P as Discord or Google
participant D as PostgreSQL
U->>F: choose provider
F->>B: GET OAuth initiation
B->>P: redirect with state + callback
P->>B: callback authorization code
B->>P: exchange code / fetch profile
B->>D: upsert AuthAccount + WebUser
B-->>F: set HTTP-only auth_token and redirect
F->>B: GET /api/auth/me with cookie
B->>D: verify jwtVersion and ban state
B-->>F: current userOAuth state is stored in an HTTP-only, same-site cookie and can carry only a dashboard-relative return path. Discord and Google provider tokens are encrypted before persistence. Google’s verified provider email may be used to merge/link an existing verified-email user; Discord starts without verified email unless separately verified.
The backend signs a seven-day JWT and places it in the HTTP-only auth_token cookie (Secure in production, SameSite=Lax). The token contains the WebUser ID and jwtVersion. requireAuth validates the signature, checks that the database revocation version still matches, resolves user context, and rejects active bans. Logout clears the cookie; “revoke all” increments jwtVersion.
The frontend does not read the token. app/dashboard/layout.tsx calls /api/auth/me with credentials and exposes the returned user through AuthContext.
Onboarding and social verification
Authentication and onboarding are separate. New users complete profile fields and referral attribution through /api/onboarding; onboardingCompletedAt records completion. Social account ownership is another separate bio-code verification, producing LinkedSocialAccount records used during submission creation.
Email verification endpoints and UI exist. However, the EmailGate wrappers in submission/payout UI and corresponding backend action checks are commented out. Email verification is therefore not currently confirmed as an enforcement gate.
Authorization
Backend enforcement
| Boundary | Enforcement |
|---|---|
| Authenticated creator APIs | requireAuth middleware |
| Administrator APIs | requireAuth followed by requireAdmin |
| Admin identity | Discord ID in ADMIN_DISCORD_IDS, or verified email in ADMIN_EMAILS |
| Payout/tax-sensitive actions | admin middleware plus requireTOTP on selected routes |
| User-owned resources | routers query with resolved webUserId/legacy Discord ID; inspect each domain because ownership patterns are not centralized in policies |
| Banned identities | active ban check on authenticated requests; identity blacklist also affects account/profile reuse |
There is no separate policy/ability framework. Authorization is expressed by middleware placement and query predicates inside routers. When adding or changing an endpoint, copy neither a neighboring mount nor frontend visibility blindly—trace the router’s actual middleware and ownership filter.
UI visibility versus security
- Admin sidebar/routes are hidden or redirected by frontend checks.
- Every traced admin backend router also enforces admin middleware; this is the actual security boundary.
- Creator button visibility such as
canSubmit, payout eligibility displays, or disabled controls is usability guidance. Backend validation must independently enforce the rule.
Current dashboard mismatch
app/dashboard/layout.tsx always calls /api/admin/check and redirects non-admins away from the entire dashboard. This affects creator overview, campaigns, submission, payout, and profile pages. The backend counterparts generally require only an authenticated creator. Onboarding redirects toward /dashboard, making intent ambiguous. Confirm expected product access with the prior team before modifying this gate.
CSRF and browser boundaries
There is no synchronizer CSRF token. The API configures credentialed CORS, same-site cookies, JSON-only body parsing, and a production guard that rejects state-changing requests without an approved Origin (payment webhooks are handled separately). This is a layered browser defense, but any new route/middleware order must preserve it.
Ambiguities and cautions
- Legacy
userIdoften means Discord ID; newer ownership useswebUserId. Mixed fallback queries can broaden or narrow access unexpectedly. - Verified Google email can carry admin status if listed; the exact operational ownership of
ADMIN_EMAILSis outside the repo. GuildConfig.managerRoleand Discord permission helpers authorize bot commands, separate from website admin allowlists.- The source contains TOS acceptance UI/state, but the dashboard’s non-admin branch makes some intended creator behavior unreachable.
- No automated authorization regression suite was found.