User Roles and Permissions: How to Design Access Control for a Business Application
Every business application eventually has to answer the same question: who is allowed to see and do what? The answer shapes the database, the screens, the sales conversations and the cost of support. Yet it is often left until late in a project, when a developer adds an "is admin" checkbox and moves on.
This guide explains how to design user roles and permissions before any code is written. It is aimed at founders, product managers and operations leads who are planning a web application or SaaS product, whether they build in-house or commission custom software development from an outside team.
Access control is a business decision first
Access rules describe how your organization works: who approves refunds, who can see salaries, who may export the customer list, and what a contractor should never touch. A developer can implement any of these rules, but cannot know them. If the business does not decide, the developer guesses, and the guess becomes policy.
The stakes are real. The OWASP Top 10:2025 lists Broken Access Control as its first category, and describes access control as enforcing policy "such that users cannot act outside of their intended permissions". The key word is intended. Software can only enforce an intention that somebody has written down.
Roles and permissions are not the same thing
A permission is a single thing a user may do, such as "view invoices", "issue a refund" or "invite a user". A role is a named bundle of permissions that matches a job, such as "Finance manager". Users are given roles, and roles carry permissions.
This is role-based access control, or RBAC. The US National Institute of Standards and Technology, whose researchers David Ferraiolo and Rick Kuhn formalized the model in 1992, summarizes it this way on its RBAC project page: each user is assigned one or more roles, and each role is assigned one or more privileges that are permitted to users in that role. The same page notes that the NIST model was adopted as an American National Standard in 2004 and revised in 2012.
The practical benefit is administrative. When a new salesperson joins, you assign the "Sales" role instead of ticking forty boxes. When the policy changes, you change the role once and everyone who holds it follows.
Least privilege and deny by default
Two principles should guide every decision. The first is least privilege, which the NIST glossary defines as restricting the access privileges of users to the minimum necessary to accomplish assigned tasks. In practice: start each role with nothing, then add only what the job needs.
The second is deny by default. If no rule grants access, the answer is no. The OWASP Authorization Cheat Sheet recommends both, and adds that permissions should be validated on every request and enforced on the server. Hiding a button in the interface is a convenience for the user, not a security control.
A sensible starting set of roles
Most business applications can launch with a small set of roles. The names vary, but the pattern is consistent:
- Owner: controls billing, can delete the account and can transfer ownership. Usually one or two people.
- Admin: manages users, roles and settings, but not necessarily billing.
- Manager: sees and edits the work of a team, approves requests, runs reports.
- Member: does day-to-day work on their own records.
- Read-only: can view but not change anything. Useful for auditors, executives and finance.
- External: a client, supplier or contractor who sees only what has been explicitly shared.
Treat the split between Owner and Admin as important. The person who manages users day to day should not automatically be able to cancel the subscription or delete all data. Plan for External users from the start as well, because adding outsiders later tends to expose data that was never meant to leave the company.
Record-level rules: "only my team's customers"
Roles answer the question "what can this person do?". They do not answer "to which records?". A sales representative may be allowed to edit customers, but only the customers assigned to them or their team. This second layer is often called record-level or row-level access, and it is where most of the real complexity lives.
Decide the scopes you need in plain language. Typical ones are: own records, own team, own region or branch, and everything in the organization. Then pair each permission with a scope, for example "Manager: edit customers, own team". If your product is sold to multiple companies, there is a further boundary above all of this: one customer organization must never see another's data, whatever the role.
Record-level rules are also where mistakes hide. OWASP's list of common weaknesses includes viewing or editing someone else's account simply by supplying its identifier. A user who changes the number in a web address should get a refusal, not another person's invoice. Our web application security checklist covers related checks.
Admin impersonation and audit logs
Support teams often need to "log in as" a customer to reproduce a problem. Impersonation is useful and risky in equal measure, so set the rules early: who may do it, whether the customer must consent, whether the session is time-limited, which actions are blocked while impersonating (changing passwords and payment details are common candidates), and whether a visible banner shows that the session is impersonated.
Every impersonated action should be recorded against both the real staff member and the account they acted as. More broadly, an audit log should capture who did what, to which record, and when, for sensitive actions such as role changes, exports, deletions and permission edits. Decide how long logs are kept and who may read them, since the log itself contains sensitive information.
What business customers ask for
If you sell software to other companies, their buyers and IT teams will ask about access control during evaluation. Expect questions about whether they can define their own roles, restrict access by team or location, sign in through their company identity provider, remove a departing employee's access quickly, and export an audit trail. Larger customers may also ask for separation of duties, meaning the person who creates a payment cannot be the one who approves it.
You do not need all of this at launch. You do need a design that will not block it later, which mainly means storing permissions as data that can be reassigned, not as role names hard-coded throughout the application.
Common mistakes: how permission models go wrong
The most frequent failure is too much flexibility too early. A fully configurable permission matrix sounds attractive, but every extra switch is something to build, test, document and explain to a confused customer. When nobody can predict what a given user will see, the model has stopped protecting anyone.
The opposite failure is creating a new role for every exception: "Manager (no exports)", "Manager (London)", and so on. OWASP calls this role explosion and points out that attribute-based or relationship-based rules handle such cases better than roles alone. In plain terms, use roles for job functions and scopes or attributes for "which records", not more roles.
Other recurring problems include one all-powerful admin role held by many people, accounts that are never deactivated, and temporary access that quietly becomes permanent.
What to do next: how to brief developers
A good brief is short and concrete. Before the first design meeting, prepare:
- A list of the types of people who will use the system, including outsiders.
- A grid of roles against actions, with a scope for each (own, team, all).
- The sensitive actions that need approval, extra confirmation or an audit entry.
- Your rules for impersonation, user invitations and offboarding.
- What customers may configure themselves, now and later.
Then ask the developers how permissions will be stored, where they are checked, how the rules will be tested automatically, and what it would take to add a new role in a year. Clear answers at this stage reduce rework, which is one of the larger drivers of project cost.
Conclusion
Good access control starts with business decisions: who does what, on which records, with what oversight. Use roles for job functions, permissions for individual actions, scopes for record-level rules, and least privilege as the default. Keep the first version small, log the sensitive actions, and avoid configurability that nobody has asked for.
If you are planning an application and want a second opinion on your roles and permissions before development begins, you can request a quote and include your draft role grid.