Skip to content

TIGER-359: authenticated 403 → redirect to dashboard + log the attempt - #347

Merged
WebTigers merged 1 commit into
mainfrom
feat/tiger-359-forbidden-redirect-dashboard
Oct 21, 2026
Merged

WebTigers merged 1 commit into
mainfrom
feat/tiger-359-forbidden-redirect-dashboard

Conversation

@WebTigers

Copy link
Copy Markdown
Owner

What

A signed-in user who hits a page above their role currently gets a full-page themed 403 (lock icon, "You don't have access to that", Back to home / Switch account). That's the wrong UX for someone who merely clicked something above their role.

Now Tiger_Controller_Plugin_Authorization::_deny(), for an authenticated-but-forbidden caller:

  1. Logs the attempt — Tiger_Log::warn('acl.denied', {resource, action, path, role}) (auto-enriched with user/org/request_id).
  2. Redirects to their own dashboard — Tiger_Service_Authentication::homeFor(): /admin for an admin-class role, else /account.

Guests still → /auth/login, a locked screen still → /auth/lock (unchanged). A loop guard falls back to the themed 403 only when the forbidden resource is the caller's own dashboard, so no redirect loop can form. The themed 403 page stays for that fallback + direct error dispatches.

Design

homeFor() is a single authority shared by AuthController::_roleHome() (login landing) and the gate, so "where does this person belong" is answered the same way everywhere. The redirect decision is extracted into a testable _forbiddenRedirect() (the full redirect path calls gotoUrlAndExit, a real process exit, so its target is pinned by unit assertions).

Tests

homeFor + _forbiddenRedirect decision logic (AuthorizationPluginTest) and the loop-guard 403 fallback + the acl.denied audit (AuthorizationPluginExtraTest, old 403-forward test retargeted). Full suite green locally: 1128 unit + 1481 integration.

🤖 Generated with Claude Code

https://claude.ai/code/session_01ASauLLscjqdsNqBNsx2Typ

…t (v1.29.0)

A signed-in user who reached a page above their role got the themed 403 wall ("You don't have
access to that", Back to home / Switch account) — wrong UX for someone who just clicked something
above their role. Now Tiger_Controller_Plugin_Authorization::_deny(), for an authenticated-but-
forbidden caller, LOGS the attempt (Tiger_Log::warn('acl.denied', {resource,action,path,role}),
auto-enriched with user/org/role) and REDIRECTS to their own dashboard instead of rendering a 403.

- New Tiger_Service_Authentication::homeFor($identity) — one authority for the identity's dashboard
  (/admin for admin-class roles, else /account), shared by AuthController::_roleHome() and the gate.
- Loop guard: if the forbidden resource IS the caller's dashboard, fall back to the themed 403 (no
  redirect loop). Guests still → /auth/login, locked → /auth/lock, unchanged. The themed 403 page
  remains for the loop-guard fallback + direct error dispatches.
- Tests: homeFor + _forbiddenRedirect decision logic (sibling AuthorizationPluginTest) and the
  loop-guard 403 fallback (AuthorizationPluginExtraTest, old 403-forward test retargeted). Full suite
  green: 1128 unit + 1481 integration.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ASauLLscjqdsNqBNsx2Typ
@WebTigers
WebTigers merged commit f4b4592 into main Oct 21, 2026
14 checks passed
@WebTigers
WebTigers deleted the feat/tiger-359-forbidden-redirect-dashboard branch October 21, 2026 13:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant