Skip to main content

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 → CarolGroups 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 memberOf attribute in AD doesn't include the group. Sometimes group memberships in AD live in a separate member attribute 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-editorsPermissions 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=42 only allows that one dashboard
  • A row with target_id IS NULL allows 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