DEV Community

Auth By Example
Auth By Example

Posted on

A new group with an old group's name can inherit everything the old one could access

Plenty of apps store access grants against a group name that comes from the identity provider: engineering-leads can edit the roadmap, finance can see invoices. When someone deletes the group in Okta or Entra ID, the app usually never hears about it, so the grant rows stay in its database.

Months later somebody creates a new group and happens to pick the same name. Maybe it's a different team, or a contractor group someone named carelessly. The next time its members sign in, their token carries groups: ["finance"], the app matches on the string, and they can open every invoice the old finance group could.

Key grants on the IdP's immutable group ID (the object ID in Entra ID, the group id in Okta) and keep the display name only for showing in the UI. When a directory sync or SCIM push reports a group as deleted, delete its grants in the same transaction. If you can't get delete events, run a periodic job that compares the groups you hold grants for against the IdP and flags the ones that no longer exist.

To test it, grant a test group access to one record, delete the group in your IdP, create a new group with the same name, add a user to it and sign in as that user. If they can open the record, your app is trusting the name.

Top comments (1)

Collapse
 
cekuu35 profile image
Cenk KURTOĞLU •

Keying on the IdP’s immutable group id is exactly right, and the same name-reuse bug lives one layer down, in the database. If those grants are mirrored in Postgres (Supabase), there are two more places a reused name wins:

  1. Role names are global and reusable. If the app does create role finance; grant select on invoices to finance, dropping the role on SCIM delete only helps if you also clean up pg_default_acl. Default privileges apply to future objects, so a stale alter default privileges ... grant ... to finance silently re-grants to the next object that takes the name — no membership needed.
  2. Delete the grant row and the role membership in the same transaction as the SCIM delete. The authorization decision is often made in the database, not in app code, so a leftover membership means the app “correctly” removed its grant while Postgres still says yes.

Your test (grant, delete the group, recreate the same name, sign in) is the right one; I’d add a variant that also asserts pg_default_acl and pg_auth_members are clean after the delete, not just the grant rows. A two-account probe for the database side: github.com/cekuu35/supabase-rls-le...