On this page
In short
- Let the identity provider prove who someone is. Let the app decide what they can do, and enforce it on the server, not just in the interface.
- Use OIDC for new apps. SAML is fine where a tool only supports it. Don't build another password store.
- Manage access through groups or app roles in the identity provider, so joiners, movers and leavers are handled in one place.
- Scope permissions by job and by data, such as plant, line or department, and give every service its own least-privilege identity.
Why internal apps are a common gap
Internal apps get less scrutiny than anything facing the internet, and they often hold the data that matters most: production records, quality results, pricing, employee information. When they keep their own accounts, access doesn't follow the company's joiners-and-leavers process, multi-factor authentication isn't enforced, and nobody can easily answer "who can see this?"
Single sign-on fixes the first half of that by moving sign-in to the identity provider you already manage, most often Microsoft Entra ID (formerly Azure AD) at companies that run Microsoft 365, or Okta, Google Workspace or similar. Least privilege fixes the second half: what each signed-in person and each service is allowed to do once they're in.
OIDC, SAML and the older options
Sign-in protocols for internal apps
OpenID Connect (OIDC)
- Good fit
- New web apps, single-page apps, mobile apps and APIs
- Notes
- Built on OAuth 2.0. Use the authorization code flow with PKCE; access tokens from the same sign-in can secure the app's API
SAML 2.0
- Good fit
- Tools and older apps that only support SAML
- Notes
- Widely supported for browser sign-in, but a poor fit for APIs and native mobile apps
Windows integrated authentication
- Good fit
- Legacy intranet apps on domain-joined PCs
- Notes
- Works on the office network; awkward for mobile, remote users and cloud hosting
App-managed passwords
- Good fit
- Almost never
- Notes
- A second password store to secure, reset and audit, outside your leaver process
| Protocol | Good fit | Notes |
|---|---|---|
| OpenID Connect (OIDC) | New web apps, single-page apps, mobile apps and APIs | Built on OAuth 2.0. Use the authorization code flow with PKCE; access tokens from the same sign-in can secure the app's API |
| SAML 2.0 | Tools and older apps that only support SAML | Widely supported for browser sign-in, but a poor fit for APIs and native mobile apps |
| Windows integrated authentication | Legacy intranet apps on domain-joined PCs | Works on the office network; awkward for mobile, remote users and cloud hosting |
| App-managed passwords | Almost never | A second password store to secure, reset and audit, outside your leaver process |
For a new app, OIDC through your identity provider's standard libraries is the default. If the app runs on AWS and you want AWS to handle the token exchange, Amazon Cognito user pools can federate to Entra ID, Okta and others over OIDC or SAML, so staff still sign in with their company account.
Authentication vs. authorization, and where roles live
The identity provider answers "who is this?" The app answers "what may they do here?" The design question is where the information behind that second answer is stored.
Options for managing an internal app's roles
App roles in the identity provider
- How it works
- Roles such as Viewer or Approver are defined on the app registration and assigned to groups; they arrive in the token's roles claim
- Watch for
- Assigning groups, rather than individual users, to an app requires Microsoft Entra ID P1 or P2; check your licensing before designing around it
Group claims
- How it works
- The token lists the user's security groups, and the app maps groups to permissions
- Watch for
- Groups usually arrive as IDs, not names, and users in more groups than the token allows (in Entra ID, 200 in a JWT or 150 in a SAML token) get an overage claim instead, so the app has to look them up another way
Roles in the app's database
- How it works
- The identity provider signs people in; an admin screen in the app assigns roles
- Watch for
- Access changes happen outside the identity provider, so leavers and movers need a separate process
| Option | How it works | Watch for |
|---|---|---|
| App roles in the identity provider | Roles such as Viewer or Approver are defined on the app registration and assigned to groups; they arrive in the token's roles claim | Assigning groups, rather than individual users, to an app requires Microsoft Entra ID P1 or P2; check your licensing before designing around it |
| Group claims | The token lists the user's security groups, and the app maps groups to permissions | Groups usually arrive as IDs, not names, and users in more groups than the token allows (in Entra ID, 200 in a JWT or 150 in a SAML token) get an overage claim instead, so the app has to look them up another way |
| Roles in the app's database | The identity provider signs people in; an admin screen in the app assigns roles | Access changes happen outside the identity provider, so leavers and movers need a separate process |
App roles assigned to groups are usually the cleanest choice: the app sees a short, stable list of role names, and IT manages membership in one place. Keep data scope, such as which plants or departments a person covers, either in groups as well or in the app's database with its own audit trail.
Designing least-privilege permissions
- Roles by job, not by person. Operator, supervisor, quality engineer, approver, administrator. Individual exceptions become roles or they become gaps.
- Scope by data as well as action. A supervisor may approve records, but only for their plant or line. Make the scope part of every query, not a filter the interface applies.
- Separate duties that check each other. The person who enters a record and the person who approves it should need different roles, and the app should stop one person doing both where the process requires it.
- Deny by default. A new screen or API endpoint is closed until a role is explicitly granted it.
- Enforce on the server. Hiding a button is a convenience. The API must check the role and scope on every request.
- Keep administration small. Few people hold the admin role, it's separate from their day-to-day role, and its use is logged.
A permission matrix to agree with the business
- Every role, with a one-line description of the job it serves.
- For each screen and action: which roles can view, create, edit, approve and delete.
- For each role: which data scope applies (plant, line, department, customer).
- Which actions need a second person, and which need a reason recorded.
- Who approves changes to the matrix itself.
APIs, tokens and service accounts
- Validate access tokens on the API. Check the signature, issuer, audience, expiry and the roles or scopes on every call, using a maintained library rather than hand-written parsing.
- Don't send ID tokens to APIs. The ID token tells the front end who signed in. The API should accept only access tokens issued for it.
- One identity per service. Background jobs and integrations use their own identities: a client-credentials app registration, a managed identity on Azure, or an IAM role on AWS. No shared service passwords, and never a person's account.
- Least privilege downstream too. The app's database login and cloud permissions are as narrow as its user roles.
- Secrets in a vault. Client secrets and certificates live in a secrets manager with rotation dates, or are avoided entirely by using managed identities and roles.
Shared devices on the plant floor
Plant-floor kiosks and shared tablets break the assumption that one device belongs to one person. A shared login signed in all shift makes every record anonymous. Better patterns:
Station identities get only the permissions the station's forms need. Approvals and administration require a personal sign-in.
- Station identity plus operator attribution. The device signs in as a station with a narrow role; each operator identifies themselves with a badge or PIN, so every record says who and where.
- Short sessions. Operator sessions end after inactivity or when the next person badges in.
- Personal sign-in for higher-risk actions. Approvals, corrections and anything administrative require the person's own company sign-in.
- Vendor features where they fit. Microsoft Entra ID offers a shared device mode for iOS and Android apps built to support it, which signs one person out and the next in across supported apps.
Our guide to mobile apps for plant-floor and field teams covers offline work and device management on the same shared devices.
Joiners, movers, leavers and audit
- Group membership drives access. HR-driven processes that already update groups in the identity provider then grant and remove app access automatically.
- Movers lose old access. When someone changes plant or job, the old group comes off, not just the new one on.
- Leavers and live sessions. Disabling an account stops new sign-ins, but a session the app already issued can last until it expires. Keep app sessions reasonably short and re-check the user with the identity provider when they're renewed.
- MFA and sign-in policy at the identity provider. Multi-factor authentication and, where your licensing includes it, Entra ID Conditional Access apply to the app automatically once it uses SSO.
- Periodic access reviews. Owners confirm who holds each role, especially admin and approver roles.
- Two kinds of logs. The identity provider logs sign-ins. The app logs what people did: who viewed, changed or approved which record, and when.
- Break-glass access. A documented, monitored way in for when the identity provider is unavailable, held by a very small number of people.
Putting an internal app behind SSO?
Tell us which identity provider you use and how the app handles sign-in and roles today. On a scoping call we'll talk through the protocol, the role model and the migration, and what a fixed-price quote would cover.
Not ready to talk yet? Draft a project brief first
Checklist for your security review
Before an internal app goes live
- Sign-in through the company identity provider over OIDC or SAML; no app-managed passwords.
- Sign-in limited to assigned users and groups.
- Roles and data scopes documented in a permission matrix the business has approved.
- Authorization enforced on the server for every API call, deny by default.
- Access tokens validated for signature, issuer, audience and expiry.
- Each service and integration using its own least-privilege identity, with secrets in a vault.
- Shared devices using station identities and per-operator attribution, not shared personal accounts.
- Sign-in logs at the identity provider and activity logs in the app, retained as policy requires.
To show those rules hold before launch, our guide to security testing a custom web or mobile app covers automated access tests for each role and planning an independent penetration test.
Our experience includes OAuth and OIDC authentication flows and AWS Cognito, which our own product, Round Table, uses for sign-in. We build web applications with single sign-on over standard OIDC or SAML, so staff sign in with the identity provider your company already uses. For the AWS side of access control, see AWS foundations for your first custom apps.
Sources
- RFC 9700: Best Current Practice for OAuth 2.0 Security (IETF)
- Federation with SAML and OIDC identity providers in Amazon Cognito user pools (AWS)
- Microsoft Entra ID: app roles, assigning users and groups to an app, group claims, enterprise application properties, access tokens and shared device mode (Microsoft)
See it applied
- Illustrative sample. Not client work.See a sample scope for an internal tool →An invented request and approval portal that replaces a spreadsheet and email, on an existing SQL Server database with the company's existing single sign-on.
- Illustrative sample. Not client work.See a sample handover package →The handover index for an invented plant-floor dashboard: repositories, infrastructure as code, the pipeline, runbooks, a data dictionary, the credential handover list, alerts, known limitations and sign-off.
Share this guide
Related services
- Web application development Portals, dashboards and internal tools with single sign-on through OAuth and OIDC.
- Custom software development Internal tools and integrations built to work with the systems you already run.
- AWS cloud & DevOps Cognito, IAM roles, CloudWatch monitoring and security hardening for what we build.
Topics