SaaS user deprovisioning is one of those responsibilities that's easy to overlook when you're building an authentication system. A user leaves a customer’s company, an administrator removes their account, and everyone assumes their access has been taken care of.
But has it?
Imagine your SaaS product has 10,000 users across hundreds of customer organizations. One of those customers tells you that an employee has left the company. Their administrator removes the employee from the organization, expecting their access to disappear immediately.
What happens next depends on how your application handles account status, active sessions, access tokens, and connected services. If those pieces aren't coordinated, a user who should have lost access may still be able to reach parts of your product.
This becomes harder to manage as your customer base grows. Enterprise customers may use single sign-on (SSO), central identity providers, and automated user provisioning. Your SaaS application still needs a reliable way to respond when someone loses access, changes roles, or leaves the organization entirely.
TL;DR
The customer's administrator or identity provider may initiate the process, but your SaaS application must enforce the removal of access to its own resources. Your identity platform can help coordinate the process, depending on how you've implemented authentication and provisioning.
- When an employee leaves: The customer's identity provider or administrator can disable the account or remove the user from the relevant application.
- When your SaaS receives the change: Your application must update the user's access, revoke applicable sessions, and prevent further unauthorized requests.
- When SSO is enabled: Blocking sign-in at the identity provider helps, but existing application sessions and issued tokens need to be handled too.
- When customers use SCIM: Automated provisioning and deprovisioning can communicate user and membership changes between an identity provider and your application.
- When your SaaS grows: Keycloak can provide a centralized identity layer for authentication across customer organizations. If you want to use Keycloak without operating the identity infrastructure yourself, Skycloak offers managed Keycloak hosting. Your application still needs to handle provisioning, authorization, and access revocation according to your architecture.
The key takeaway: removing a user's ability to sign in again doesn't automatically guarantee that every existing session or permission has been revoked.
Your SaaS needs a defined offboarding process that covers the access your application actually controls.
What Happens When a SaaS User Leaves?
Let's follow a realistic example. A company uses your SaaS product to manage internal projects. One of its employees leaves, and the company's IT administrator disables that employee's account in the corporate identity provider.
That action changes what the employee can do, but the result depends on how your product integrates with the identity provider.
Blocking the Next Login Is Only the First Step
If the employee tries to sign in again through the corporate identity provider, the disabled account should prevent a successful new login. That's an important first step, but your SaaS may already have an authenticated session for that user.
For example, the application may have issued its own session cookie after the original SSO login. Disabling the identity-provider account doesn't necessarily invalidate that application session automatically. The application needs a way to detect the account's changed status and reject access when appropriate.
The same concern applies to access tokens. A self-contained token, such as a JWT, can remain valid until it expires unless the resource server has a mechanism to check revocation or current authorization. The exact behavior depends on your token design and validation process.
Removing Access Across the Product
There's another layer to consider: what the user was allowed to do after signing in.
A former employee might have had access to shared projects, customer records, API credentials, or administrative functions. If their membership or role remains active in your application, blocking their next login alone doesn't clean up those permissions.
A reliable offboarding flow needs to address the relevant parts of the account lifecycle:
- Authentication: Prevent the user from establishing new sessions when their account is disabled or access is withdrawn.
- Active sessions: Invalidate applicable sessions and account for tokens that may remain valid.
- Authorization: Remove organization membership, roles, and permissions that the user should no longer have.
- Connected systems: Revoke or update access to integrations, API keys, and other resources where your application manages those credentials or permissions.
Not every product needs the same implementation. A simple SaaS application may have a single user account and a few organization roles. An enterprise platform with multiple integrations may need a coordinated workflow across several systems.
The important part is defining what offboarding means for your product and ensuring that each relevant layer enforces it.
Why Manual Offboarding Breaks as Your SaaS Grows
When you have a handful of customers, removing a user might be a simple database update. An administrator disables the account, your application blocks access, and the process is complete. At 10,000 users across hundreds of organizations, the same approach becomes harder to maintain.
The problem is that user changes can originate in different places. One customer manages accounts directly in your product, another relies on Microsoft Entra ID or Okta, and a third connects an external identity provider through SSO. Each setup creates a different path for communicating that a user's access has changed.
Manual processes also introduce delays. An IT administrator might disable an employee's corporate account but forget to remove their membership from your SaaS application. A customer might notify your support team, which then has to locate the correct account and make the change manually. Every additional step creates another opportunity for access to remain active longer than intended.
Three challenges tend to become more significant as your customer base grows:
- Inconsistent account management: Different customers use different identity providers, account policies, and offboarding procedures.
- Delayed access removal: Your application may not learn about an account change until someone manually updates it or the user attempts to sign in again.
- Unclear ownership: Your team may assume the customer's identity provider handles everything, while the customer assumes your application removes all access automatically.
A scalable approach needs a clear source of identity information, a reliable way to communicate account changes, and application logic that applies those changes correctly. That's where automated provisioning becomes useful.
How SCIM Helps Automate SaaS User Deprovisioning
System for Cross-domain Identity Management (SCIM) is a standard for exchanging identity information between systems. It allows an identity provider to create, update, and deactivate user accounts in a connected application through a defined API.
For enterprise SaaS products, SCIM can reduce the manual work involved in managing customer users throughout their lifecycle. When an employee joins an organization, the identity provider can provision an account in your product. When that employee changes roles or leaves, the provider can send an update that your application processes.
A typical workflow looks like this:
- An administrator changes the user's status. The customer's IT team disables the employee or removes their assignment to your application in the identity provider.
- The identity provider sends a provisioning request. Depending on the provider and configuration, it may deactivate the SCIM user resource, delete it, or update its attributes.
- Your application processes the change. It identifies the correct user and organization, updates the account's status, and applies the appropriate access-removal rules.
- The application handles existing access. It invalidates applicable sessions, updates memberships and permissions, and addresses tokens or credentials according to its security design.
- The operation is recorded. Logs and provisioning status help administrators investigate failures and confirm whether the change was applied.
SCIM standardizes communication between systems, but it doesn't automatically secure every layer of your application. Your implementation must correctly interpret incoming changes, handle errors, and enforce the resulting access decisions.
What Happens When a SCIM Request Fails?
Consider an identity provider that sends a deactivation request while your application is temporarily unavailable. If your endpoint returns an error and the provider retries the request, the change may eventually succeed. If your system drops the event without recording it, the user could remain active.
For that reason, a production-ready implementation should handle retries, duplicate requests, and partial failures. Processing the same deactivation request more than once should not cause problems, and your system should make failures visible to the appropriate administrators.
You should also distinguish between disabling a user account and deleting its record. Deactivation can preserve the user's historical activity, audit records, and references in shared resources. Permanent deletion may be appropriate in some situations, but it can introduce complications when other records depend on that user.
The right behavior depends on your product's data model, retention requirements, and customer agreements. Define these rules before connecting SCIM to your production environment.
The key benefit is consistency. SCIM gives your SaaS a standard way to receive identity lifecycle changes, while your application remains responsible for enforcing those changes.
Where Keycloak Fits Into SaaS User Deprovisioning
If your SaaS supports enterprise SSO, a centralized identity platform can simplify authentication across customer organizations. Keycloak is one option for managing authentication, identity brokering, and access-related configuration through a common identity layer.
For example, your application can use OpenID Connect (OIDC) or SAML to authenticate users through Keycloak. Depending on your configuration, Keycloak can connect to an external identity provider and manage the authentication flow between that provider and your application.
This provides a useful foundation, but authentication and deprovisioning are related responsibilities, not the same operation.
Centralized Authentication Doesn't Remove Every Application Permission
Imagine a customer uses its corporate identity provider to authenticate employees through Keycloak. When an employee leaves, the corporate account is disabled. Your SaaS still needs to determine how that change reaches Keycloak and the application, and what happens to existing access.
Depending on the integration, you may need to account for:
- Identity synchronization: How changes from the customer's identity provider reach Keycloak or your application.
- Session management: How applicable Keycloak sessions and application sessions are invalidated when access is withdrawn.
- Application authorization: How your product removes organization memberships, roles, and permissions that are no longer appropriate.
- Provisioning integrations: How users and their lifecycle changes are synchronized through SCIM or another supported mechanism.
The exact setup depends on your architecture. Keycloak's authentication protocols don't, by themselves, guarantee that every customer identity change will trigger complete deprovisioning in every connected system. Keycloak 26.6 and later includes a native SCIM 2.0 API for user and group provisioning. Skycloak makes SCIM provisioning available on all plans, allowing teams to synchronize user lifecycle changes through a standard interface.
How Keycloak Handles User Logout and Token Expiration
When an administrator disables a user in Keycloak, the user cannot establish new authenticated sessions, and refresh-token requests for that disabled user fail. However, an access token that has already been issued can remain valid until it expires. Keycloak's default access-token lifespan is five minutes, although this value can be changed in the realm settings.
To terminate the user's Keycloak sessions immediately, an administrator can open Users → select the user → Sessions → Sign out. The same operation is available through the Admin REST API:
POST /admin/realms/{realm}/users/{id}/logout
To close the user's application session as well, configure the client's Backchannel Logout URL and implement the corresponding logout endpoint in your application. Keycloak can then send a logout request to the application when the user's session is terminated. Your application must process that request and invalidate its own session.
This distinction matters for SaaS user deprovisioning: terminating a Keycloak session and revoking access to every application resource are separate steps. Your application must also enforce its authorization rules and account for access tokens that remain valid until expiration.
Managing Your Keycloak Infrastructure with Skycloak
Building a reliable SaaS user deprovisioning workflow requires an identity platform that supports your authentication and provisioning needs as your customer base grows.
Self-hosting Keycloak gives your team control over the deployment, but your team is also responsible for the infrastructure, updates, monitoring, and ongoing maintenance.
Skycloak provides managed Keycloak hosting, handling the identity infrastructure while your team focuses on its application. Every plan includes unlimited users and full Keycloak admin access. Skycloak supports deployments in the US, EU, Canada, and Australia, giving teams regional hosting options. You can also start a 21-day free trial without a credit card.
Skycloak includes SCIM 2.0 provisioning on all plans, with support for automated user provisioning, deprovisioning, and group synchronization with compatible identity providers.
How Managed Keycloak Fits Into User Offboarding
Your team can use Keycloak to manage authentication while its application handles the consequences of account changes: organization memberships, roles, permissions, active sessions, and access to connected resources.
Skycloak manages the Keycloak hosting infrastructure. Your application remains responsible for applying account status changes and enforcing authorization rules, including revoking access that the application controls.
For example, when an employee leaves a customer's organization, SCIM can communicate the lifecycle change to the connected identity system. Your SaaS application must then process that change, update the relevant account and membership records, and handle existing sessions and access tokens according to its security design.
Is Managed Keycloak Right for Your SaaS?
Skycloak offers unlimited users and full Keycloak admin access on every plan, with regional hosting options in the US, EU, Canada, and Australia. Its 21-day free trial does not require a credit card.
Explore Skycloak's managed Keycloak hosting plans to compare the available options for your SaaS.
Managed identity infrastructure reduces the operational work involved in running Keycloak. Pairing it with a well-defined offboarding process helps your application enforce access changes consistently across users, sessions, memberships, and protected resources.
Designing a Reliable Offboarding Flow
A dependable SaaS user deprovisioning process starts with a simple question: When an organization removes a user, what must happen before that user's access is considered revoked?
Write down the expected behavior for each type of account your product supports. A user managed directly by a customer administrator may follow a different path from a user provisioned through SCIM or authenticated through an external identity provider. Those paths should still lead to a consistent security outcome.
Use the following checklist when designing your flow:
- Identify the source of the change. Determine whether the request comes from your own admin interface, an identity provider, a SCIM endpoint, or another trusted integration.
- Verify the affected account and organization. Make sure a change for one customer cannot disable a user or remove permissions in another customer's organization.
- Update account status and memberships. Apply the change to the correct user record, organization membership, roles, and permissions.
- Handle active access. Invalidate applicable sessions and account for outstanding tokens or credentials based on your authentication architecture.
- Protect connected resources. Revoke or update API keys, integration credentials, and other access mechanisms your application controls.
- Record the outcome. Log the request, its source, the actions performed, and any failures without exposing secrets or sensitive token values.
- Make failures recoverable. Use retries, idempotent processing, and monitoring so a temporary error doesn't silently leave an account active.
- Test the full lifecycle. Verify what happens after account deactivation, organization removal, role changes, and provisioning failures, not only whether a new login is blocked.
You should also decide how quickly access must be revoked. Some products can tolerate a short delay for routine synchronization, while applications handling sensitive customer or financial data may require more immediate enforcement. Your architecture should reflect that requirement, including how frequently it checks authorization state and how long issued tokens remain usable.
Finally, test the flow from end to end. Disable a test user in the source identity provider, verify that the change reaches your application, and confirm that the user cannot access protected resources through an existing session or previously issued credential. Check the logs as well, so your team can establish what happened and identify any failed step.
A successful sign-in test is only one part. Your SaaS should be able to demonstrate that an offboarding request reaches the right account, changes the relevant permissions, and prevents access through the paths your application supports.
Common SaaS User Deprovisioning Mistakes to Avoid
Even with SSO, SCIM, and a centralized identity platform in place, gaps can remain in your offboarding process. The most common problems happen when teams assume one successful action automatically handles every other layer of access.
Here are five mistakes worth checking in your SaaS application.
1. Assuming SSO Automatically Revokes Existing Access
Disabling a user in an external identity provider can prevent future authentication, but it doesn't necessarily terminate every session already established in your application. Define how your application responds to account changes and how it handles sessions and tokens that remain valid.
2. Treating Account Deactivation as Complete Permission Cleanup
A disabled account may still have organization memberships, assigned roles, API keys, or integration credentials recorded in your system. Your offboarding workflow should identify which of these resources need to be removed, disabled, or transferred.
3. Ignoring Failed Provisioning Events
A SCIM request can fail because of a network problem, an invalid resource, or an application error. Without monitoring and a recovery process, your team might never notice that a deactivation was not applied. Log failures, retry safely, and alert the right people when intervention is needed.
4. Deleting Accounts Without Considering Audit History
Permanent deletion can break references to past actions, reports, and shared resources. For many SaaS products, deactivating an account and preserving the necessary audit history is a better default. Apply your retention and deletion policies carefully, including any relevant contractual or legal requirements.
5. Failing to Test Real Offboarding Scenarios
Testing whether a user can sign in after deactivation is useful, but it doesn't cover every access path. Test existing sessions, protected API endpoints, organization membership, privileged actions, and any connected resources your product manages. Include failures and retries in your test cases.
A strong SaaS user deprovisioning process is one you can test, monitor, and explain. You should be able to identify where a request originated, what your application changed, and whether any step failed.
Frequently Asked Questions
What is SaaS user deprovisioning?
SaaS user deprovisioning is the process of removing or disabling a person's access to a software-as-a-service application when they leave an organization, change roles, or no longer need the product. Depending on the application, this can include deactivating the account, removing organization memberships and permissions, terminating sessions, and addressing associated credentials.
Does disabling a user in SSO remove their access immediately?
Not necessarily. Disabling the account in an identity provider can block future authentication, but existing application sessions or previously issued tokens may remain usable, depending on how the application validates them. To enforce timely access removal, your SaaS needs an appropriate session invalidation, token validation, and authorization strategy.
How does SCIM automate user deprovisioning?
SCIM allows an identity provider to communicate user lifecycle changes to a connected application through a standardized API. When a user is deactivated or removed from an application assignment, the provider can send a corresponding request. The SaaS application must process that request correctly and apply its own account, membership, and access-removal rules.
Can Keycloak handle SaaS user deprovisioning?
Keycloak can provide identity and authentication capabilities as part of a SaaS user deprovisioning workflow. When a user is disabled, new logins and refresh-token requests for the terminated session fail, but an access token already issued can remain valid until expiration. Keycloak's default access-token lifespan is five minutes, although it is configurable. Administrators can terminate the user's Keycloak sessions and configure backchannel logout so the application can invalidate its own session. The application must still enforce its authorization rules and handle access to protected resources. Teams that want Keycloak without operating its infrastructure can use Skycloak's managed Keycloak hosting. Skycloak includes SCIM 2.0 provisioning on all plans.
Should a SaaS application delete a user or deactivate their account?
Deactivation is often a practical first step because it can prevent access while preserving audit history and references to previous activity. Permanent deletion may be appropriate when required by a retention policy, customer request, or applicable legal obligation. The right approach depends on your data model, security requirements, and obligations to your customers.
Final Thoughts
When your SaaS has 10,000 users, removing one person's access should not depend on someone remembering every system they might be able to reach. The process needs to work consistently whether the change begins with a customer administrator, an external identity provider, or an automated provisioning workflow.
SSO helps manage authentication, SCIM 2.0 communicates user lifecycle changes, and Keycloak provides a centralized identity layer. Skycloak offers managed Keycloak hosting with unlimited users, full admin access, and SCIM provisioning on every plan. Whichever deployment model you choose, your application still needs clear rules for account status, organization membership, permissions, and the invalidation of existing access.
Start by mapping the complete offboarding journey in your product. Decide what should happen when a user is disabled, identify which systems must receive the change, and test what happens when a request fails. Then add monitoring so your team can detect and investigate incomplete operations.
| Thanks for reading! 🙏🏻 I hope you found this useful ✅ Please react and follow for more 😍 Made with 💙 by Hadil Ben Abdallah |
|
|---|



Top comments (12)
The point about existing sessions and tokens is so important. Disabling an account is only one part of the process; making sure that access is revoked across the application is what really matters. SCIM helps automate those changes, but the application still needs to enforce them properly.
Exactly! It’s easy to assume that disabling an account takes care of everything, but existing sessions and permissions can easily be overlooked. SCIM helps make the process more consistent, but the application still has to make sure those changes actually take effect.
The organization check in the offboarding checklist deserves its own test case. I’d use one person who belongs to two customer organizations, remove only one membership, and verify that the other organization still works. Then I’d replay the old removal after a deliberate re-invite to check how ordering is handled. How would you distinguish a stale deactivation from a fresh one when the identity provider retries an earlier request?
I love this test case! It’s easy to focus on removing access and forget to check whether the change affects other organizations or conflicts with a later re-invite. I’d use versioning or timestamps to distinguish newer changes from stale requests, so an old retry doesn’t accidentally deactivate a user who’s been reactivated.
The re invite case is exactly what I was worried about. I’d prefer a revision tied to that membership where the API supports it; timestamps need a clear ordering rule if different systems set them. Then I’d replay the old deactivation after the re-invite and check both organizations again.
Revocation is also worth testing across already-issued sessions and background jobs, not only the next login. A useful fixture disables a user and checks each access path against the same expected cutoff.
Great point! Background jobs can easily be overlooked when testing offboarding, and they may still have access even after a user is disabled. Testing every access path against the same cutoff is a really practical way to catch those gaps.
The key line for me is that blocking sign-in does not revoke what was already issued. Most teams test offboarding by trying to log in again, and that is the one path that was never the problem.
Alex Shev's fixture is a good way to make it testable: disable a user, then check every access path against the same cutoff, including existing sessions, refresh tokens, API keys and background jobs that run as that user. Aida's point holds too. SCIM can tell the application that someone left, but only the application can enforce it.
I would add one item for B2B products. Write down, per customer, how fast removal has to take effect and who confirms it, because an enterprise security review will ask for that number. Once it is written, it becomes part of the definition of done for the auth work instead of something found in the first audit.
How do you handle scheduled reports or long exports started by a user who has since been removed?
Good question! I think scheduled reports and long-running exports need to check the user’s access again when they run or before delivering the result, not just when the task is created. Otherwise, work started by someone who had access yesterday could still expose data after they’ve been removed.
Worth adding the billing clock to this runbook, because access removal and charge removal run on different timers.
Revoking sessions is immediate. The seat usually is not. On annual commitments the seat keeps billing until renewal, and the vendor's answer when you ask is basically: you signed for it. There is a Hacker News comment that quotes exactly that reply — "Unused seats? Still gotta pay for 'em... You committed to paying for 50 seats for a year" — from a team that shrank after a layoff.
So an offboarding runbook has two exits, and they belong to different owners: revoke access (security) and reconcile the seat count (finance). If nobody owns the second one by name, it surfaces at the renewal invoice, which is the most expensive possible time to notice.
One practical detail that helps: the reconciliation needs the renewal date and the per-seat price on the same line as the person, otherwise the security team closes the ticket and the seat keeps paying rent.
Would you put that reconciliation inside the same runbook, or keep it in a separate monthly audit?
The deprovisioning question has a second half that this post made me check in my own product today: what happens to the artifacts that were issued while the person was still a member.
One concrete case. A guest buyer pays without an account, and a one-time claim link is emailed to them. I defined "used" as "the organization already has a member" instead of stamping the claim itself. That works until a member is removed inside the 48-hour window: the link comes back to life, because the condition it tested for became false again. The fix was one column, claimedAt stamped on first acceptance. It surfaced only because a reader asked what happens to sessions and tokens that outlive the membership.
The general shape: deprovisioning is not only "revoke now", it is also "make every previously issued credential incapable of resurrection". Session rows, API tokens, invite links, claim links, and magic links each need their own consumed-at marker. A shared "is there still a member" predicate is a different thing, because membership is reversible and a one-time token should not be.
Your point about status, sessions, tokens, and connected services needing coordination applies to invite artifacts too. Those are usually the ones missing from the offboarding runbook.
JWTs are the trickiest part here—once issued, they're valid until expiry unless you're actively checking revocation lists. Short-lived tokens with refresh logic help, but you still need a way to invalidate them when it matters.