Permission denied after LDAP sync
Common report: "I added Carol to the AD group analytics-editors, the LDAP sync ran, but Carol still gets 403 Forbidden on the dashboards she should be able to edit."
There are four places this can break. Walk through them in order.
1. Did the sync actually happen?
Admin → LDAP → Last sync. Check timestamp and status.
- Sync hasn't run since the change — sync runs on a cron (default every 15 minutes). Either wait, or trigger a manual sync (LDAP → Sync now).
- Sync ran but errored — read the error. Common: directory bind credentials expired, or the search base path is wrong.
- Sync ran cleanly — continue to step 2.
2. Is the user actually in the LDAP-mapped group on Honeyframe's side?
Admin → Users → Carol → Groups tab. The group analytics-editors should appear with an "LDAP" badge.
If it's missing:
- The LDAP DN of the group is wrong in
hubstudio.groups.ldap_dn. Check what AD returns for the group's DN, compare to what's stored. Trailing whitespace and case differences trip people up — LDAP DNs are case-insensitive in spec but the resolver does an exact string match. - The user's
memberOfattribute in AD doesn't include the group. Sometimes group memberships in AD live in a separatememberattribute on the group itself, not on the user. Check your LDAP attribute mapping under Admin → LDAP → Settings → Attribute mapping.
3. Does the group actually have the permission?
Admin → Groups → analytics-editors → Permissions tab. Look for the dashboard.edit row.
If it's missing, the group inherited a name from LDAP but no one ever assigned it permissions on the Honeyframe side. LDAP groups are not auto-permissioned — you have to grant them like any other group:
- Click Grant permission
- Pick
dashboard.edit - Pick whether it's org-wide (target_id = NULL) or scoped to specific dashboards
This is intentional. LDAP tells Honeyframe who is in what group; it doesn't tell Honeyframe what those groups should be allowed to do.
4. Is the permission cache stale?
The frontend caches permissions on login. If Carol was already logged in when the sync ran, her browser still has the pre-sync permission set.
- Quick fix — Carol logs out and back in. The login flow re-fetches
/api/groups/me/permissions. - Bulk fix — Admin → Users → Bulk → Force re-auth on next request. Invalidates all session permission caches; users re-fetch transparently on their next request.
Permission cache TTL is 5 minutes for active sessions, so worst-case Carol's cache refreshes within 5 min without manual intervention.
When all four pass and Carol still can't edit
Look at the actual 403 response payload:
{
"error": "permission_denied",
"permission": "dashboard.edit",
"target_id": "42"
}
The target_id matters. If the group has dashboard.edit granted org-wide (target_id NULL), the resolver falls back to that grant for any specific dashboard. If the group only has dashboard.edit granted on specific dashboard IDs and 42 isn't in the list, that's the gap.
The grant rules:
- A row with specific
target_id=42only allows that one dashboard - A row with
target_id IS NULLallows any dashboard (org-wide) - The resolver matches either — it doesn't take the more permissive of two rows, it just needs at least one match
See also
- Permissions Reference — the resolver order in detail
- LDAP Configuration — bind credentials, attribute mapping, sync schedule
- Users & Groups — the conceptual model