Who can use the AI feature? Access control for SaaS
You add an AI assistant to your SaaS product. It can read customer records, draft replies, and trigger actions like issuing a refund or updating a deal stage. Then an account with a viewer role asks it to change a record, and it does, because the assistant runs with your service credentials and never checked whether that user was allowed to make the change.
This is the access-control gap that shows up in almost every AI feature we review. The product already has roles and permissions for its normal screens. The AI layer bypasses all of them because it was bolted on as a single privileged integration. Before you ship an AI feature that reads data or takes actions, it needs to respect the same authorization your buttons and API already enforce.
- An AI feature needs three separate access decisions: who can see the feature, which data the model may read, and which tools the agent may call.
- Roles alone are not enough. You need resource-level checks so a user reaches only the specific records, projects, and documents they already have rights to.
- Enforce authorization in your own backend on every tool call, not in the prompt. A model instruction is a suggestion, not a permission boundary.
Why AI features break your existing permission model
Traditional screens are safe almost by accident. A viewer never sees the edit button, and the edit endpoint checks the role again on the server. The paths are narrow and each one was secured on its own.
An AI feature collapses those narrow paths into one wide surface. A single chat endpoint might expose a dozen tools with wildly different sensitivity, from read a document to delete a workspace. If you wire the agent to your backend with one admin token, every user who can open the chat box now has the union of every permission that token holds. The role system you spent months building is still there; the AI just walks around it.
Multi-tenant products have a sharper version of this problem. The model that answers for tenant A is often the same deployment that answers for tenant B, and a careless retrieval query can pull the wrong tenant rows into a prompt. We wrote about the data side of this in multi-tenant RAG data isolation; access control is the action side of the same concern.
Three layers of access an AI feature needs
Who can see the feature
The first decision is the coarsest: which plans, roles, and users get the feature at all. This is normal feature gating, and most teams already have it. The mistake is stopping here and assuming that because a user can open the assistant, everything it does on their behalf is automatically fine.
Which data the model can read
Every retrieval the feature performs must be scoped to what the current user could already query directly. If a sales rep cannot see other regions in the CRM, the assistant must not retrieve those records into its context to answer a question. The cleanest way to guarantee this is to run retrieval as the user: pass their identity into the query, filter at the data layer, and never let the model see rows the user could not fetch through the normal API.
Which tools the agent can call
The highest-risk layer is action. An agent endpoint that exposes refund, delete, and export should check, per call, whether this specific user in this specific tenant is allowed to perform that action on that object. Without tool-level checks, every user who can talk to the agent inherits every tool the agent has, regardless of their role. Bind the allowed tool set to the caller, not to the agent.
Resource-level, not just tenant-level
Tenant isolation keeps company A out of company B. It does nothing about the fact that inside company A, a junior support agent should not be able to have the assistant export the full customer list. Real AI authorization is resource-level: this user, this action, this object.
The practical pattern is to treat the AI feature as just another client of your existing authorization service. When the agent wants to call a tool, it asks the same policy engine your REST API asks: can user X do action Y on resource Z. If the answer is no, the tool call fails and the model is told the action was not permitted, which it can explain to the user. The model never becomes the thing that decides permissions; it only proposes actions that your backend approves or rejects.
For actions that are sensitive but sometimes legitimate, add a human in the loop rather than a hard block. A pattern we like for high-stakes tools is to let the agent stage the action and require an authorized user to confirm it, which we covered in human-in-the-loop approval for AI agents. That keeps a low-privilege user productive while an approver owns the risky commit.
How to add this without a rewrite
You almost never need a new permission system. You need to route the AI feature through the one you have.
Start by inventorying the tools the feature exposes and tagging each with the permission it should require, using the exact same permission names your API already checks. Then wrap every tool handler so it runs the authorization check before doing any work, using the caller identity rather than the service account. Make retrieval identity-aware so the model only ever sees rows the user could fetch. Finally, log every tool call with the user, the tenant, the tool, and the decision, so you have an audit trail when someone asks who told the assistant to do that.
Two guardrails make this durable. Never put the real authorization logic in the system prompt, because a prompt is advisory and users will talk the model into ignoring it; keep the enforcement in code. And default deny, so a newly added tool is unreachable until you explicitly grant it, rather than exposed to everyone the moment it ships. These fit naturally into the same pre-launch review as your other safety checks; the broader list lives in our AI agent security checklist for SaaS founders and the launch-time gates in AI feature guardrails before launch.
Frequently asked questions
Can I just tell the model in the prompt which users are allowed to do what?
No. The prompt is not a security boundary. A determined user can often coax the model into ignoring an instruction, and even without an attack, model behavior drifts. Enforce every permission in your backend code on the actual tool call, and use the prompt only to help the model explain a denial gracefully.
How is this different from the data isolation I already do for RAG?
Data isolation controls which rows the model can read. Access control also covers which actions it can take on the user behalf. A feature can be perfectly isolated on reads and still let a low-privilege user trigger a privileged write, so you need both the retrieval scoping and the tool-level checks.
Do read-only AI features need this too?
Yes, on the data layer. A read-only assistant that retrieves records still has to scope those reads to what the current user is allowed to see, or it becomes a way to exfiltrate data the user could not otherwise reach. It just does not need the tool-authorization layer, since it takes no actions.
Where should the authorization check live?
In the same policy layer your normal API already uses. The AI feature should be a client of that service, asking can this user do this action on this resource before every sensitive tool call, so there is one source of truth rather than a second permission model that drifts out of sync.
Rather we just build it?
Book a free scoping call and we'll ship your production-safe AI feature this week.