Quarterly Auth0 access review board for SOC 2 evidence
Certify who still has privileged access in one sitting, revoke what is stale, and export a decision log your auditor will actually accept.
Build me an internal access review board that our security lead opens once a quarter to certify who still has privileged access in our Auth0 tenant. A review session starts with the reviewer entering their name and their own Auth0 user id or email address. That name stamps every decision they record, and their identity powers the self revocation guard described below. The app has two tabs: Roles (the default) and Organizations.
The Roles tab lists every tenant role using List Roles. For each role show the permissions attached to it via List Role Permissions, as a count with the full list revealed on expand. Sort privileged roles to the top: treat any role whose name contains admin or owner, case insensitive, as privileged and give it a clear Privileged badge. Everything else sorts alphabetically underneath. Each row should also show how many people hold the role.
Expanding a role shows every holder from List Role Users. Enrich each holder with their last login timestamp and email verification status using Search Users, batching lookups by user id or email rather than firing one call per holder. For each person show name, email, last login as both an absolute date and a days ago figure, and a verified or unverified badge. Highlight anyone whose last login is 90 or more days ago, or who has never logged in, in a warning style labelled likely revoke candidate. That highlight is the whole point of the screen, so make it impossible to miss.
The Organizations tab does the same thing for organizations. List them with List Organizations, which uses checkpoint pagination: pass take, then pass from set to the id of the last item you received, rather than page numbers. Selecting an organization lists its members via List Organization Members. Expanding a member shows the roles they hold inside that organization via List Organization Member Roles, with the same Search Users enrichment, the same privileged sorting, and the same stale access highlighting.
Every holder row has two buttons: keep and revoke. Keep simply records the decision and makes no API call. Revoke asks for confirmation naming the person and the role, then calls Remove Roles from User on the Roles tab, or Remove Organization Member Roles on the Organizations tab, and records the decision. Both outcomes append to a running decision list for the whole session, shown in a side panel with a live count. The decision list survives switching between tabs, expanding and collapsing roles, and moving between organizations.
Never let a reviewer revoke their own admin role. Match the session reviewer's user id or email against each holder, and when they are the same person on a privileged role, disable the revoke button with a tooltip explaining why instead of hiding it. Enforce the same rule in the handler so it cannot be bypassed from the client.
An Export button appends the whole decision log to a Google Sheets tab using Append Values, one row per decision with reviewer name, review date, role name, user email, and decision (keep or revoke). Let the reviewer choose or paste the spreadsheet and the tab name, and write a header row first if the tab is empty. After exporting, confirm how many rows were appended and keep the log on screen rather than clearing it, so a reviewer can export again without losing their work.
A few technical details to get right. Auth0 user ids embed the identity provider, like auth0|66f1... or google-oauth2|1057..., and must be URL encoded when used in a path segment. Page based pagination is capped at the first 1,000 results, so for wide tenants refine the query rather than paging forever, and prefer loading people role by role over enumerating all users. Roles returned by List User Roles are direct assignments only, so if you surface that anywhere, say so in the UI rather than implying it includes organization scoped grants. Expanding several roles fans out into many calls, so respect Auth0 rate limits with backoff and show a loading state per role instead of blocking the whole screen.
The reason this app exists is SOC 2 CC6.3, which requires periodic review of user access rights and expects documentation of who approved each grant and when, tied back to the identity provider. Most teams run this quarterly out of a hand built spreadsheet. This app should replace that ritual end to end, so favour a dense, scannable review surface over a pretty dashboard.
What does this prompt do?
- Lists every role in your Auth0 tenant with the permissions attached to it, and pushes anything named admin or owner to the top so privileged access gets reviewed first
- Expands any role to show every person who holds it, with their last login date and whether their email is verified, so dormant accounts are obvious at a glance
- Flags anyone who has not logged in for 90 days or more as a likely revoke candidate
- Gives the reviewer a keep or revoke button on every person, and actually removes the role in Auth0 when they choose revoke
- Covers organizations on a second tab, so you can review who holds which role inside each customer or business unit
- Exports the full decision log to a Google Sheet with reviewer name, review date, role, user email, and decision, which is the evidence an auditor asks for
What do I need to use this?
- An Auth0 tenant, and permission for General Input to read and change users, roles, and organizations in it
- A Google account with a spreadsheet where the review log should be stored
- The name of the person running the review, entered at the start of each session
- Roughly an hour per quarter from whoever owns access reviews, usually a security or IT lead
How can I customize it?
- Change what counts as privileged: the default treats any role whose name contains admin or owner as privileged, but you can add your own keywords like billing or superuser
- Adjust the stale access threshold from 90 days to whatever your policy says, for example 30 days for highly privileged roles
- Add columns to the exported log, such as a justification note per decision or the reviewer's manager, and point the export at a new tab each quarter
FAQs
Does this actually remove access, or just record a decision?
Can a reviewer accidentally remove their own admin access?
Why does the export go to a spreadsheet instead of staying in the app?
Will this work if we have thousands of users?
Do we need to be doing SOC 2 for this to be useful?
Related templates
Stop buying stale lists. Reps run a saved search, work the results like an inbox, and only the accounts they approve ever reach your CRM.
Drag creators through Sourced to Wrapped on a board grouped by campaign, with audience stats on every card and a one-click brief for each creator.
Pick a repricing rule, send an assistant out to check competitor pages, then approve the new prices that clear your margin floor.
See the projected bounce rate for any outbound send before it goes out, and keep the launch button locked until the list is clean enough to be safe.
Pick any date range and see what each device in your home actually cost to run, not just how many kilowatt-hours it used.
Search three months of global coverage on your topic, rank the outlets actually writing about it, and draft a tailored pitch for each one.
Stop running access reviews out of a hand-built spreadsheet.
Give your security lead one screen to certify every privileged role, revoke stale access on the spot, and hand the auditor a clean log.