Security Is a Spectrum: How to Choose Session Lifetimes in Duende IdentityServer
Summary: Session lifetimes in Duende IdentityServer are a deliberate, risk-aware decision. This guide moves you beyond default settings, helping you align your configuration with your specific risk profile:
• Tailor token and session lifetimes to match the sensitivity of your data, rather than relying on generic defaults.
• Enable monitoring and termination of active sessions when device security is compromised.
• Document intentional decisions that stand up to audit requirements, moving beyond inherited templates.
Anders Abel, technical partner at Sustainsys, puts it plainly: of all the decisions developers face when hardening Duende IdentityServer, session lifetimes are the ones most likely to be guessed at rather than decided.
Duende's Joe DeCock puts it this way: security is on a spectrum of risk tolerance. A lemonade stand needs a different security model from that of a national security agency. Both can be correct. The lemonade stand doesn't need to force re-authentication every 15 minutes. The security agency probably does.
The problem isn't that teams get the configuration wrong. It's that they don't decide at all. They ship with defaults, inherit settings from tutorials, and never revisit them. The defaults in Duende IdentityServer are designed for broad compatibility, not your specific risk tolerance. They're a starting point, not a recommendation.
This guide won't tell you what your lifetimes should be. What it will do is give you the questions you need to answer before you configure anything.
Quick Start Checklist: Decide These Deliberately
For folks who want to jump in right away, I've provided a quick start guide you can print and follow. This isn't a pass/fail test. It's a prompt for a conversation your team should have before shipping and revisit periodically afterward.
SESSION AND TOKEN SECURITY REVIEW
----------------------------------
[ ] 1. Access token lifetime
I know what it is, and chose it for our risk profile.
I know what our tokens authorize and whether the lifetime
is an acceptable exposure window if one is stolen.
[ ] 2. Refresh token expiration
I know why and whether we use absolute expiration, sliding
expiration, or both.
[ ] 3. Refresh token rotation
I know whether we use ReUse or OneTime rotation,
and I understand the trade-offs of each.
[ ] 4. Session lifetime
I know how long a session lives and where that number
came from. It was not inherited from a template.
[ ] 5. Session observability
I know whether we can query, enumerate, or remotely
terminate active sessions, and whether we need to.
[ ] 6. Inactivity timeout
I know whether we distinguish active from idle users.
If we use CoordinateClientLifetimesWithUserSession,
I have verified that access token lifetime is shorter
than the inactivity window.
[ ] 7. JWT vs reference tokens
I know which our clients use and whether revocability
matters for any of them. Sensitive operations have
been considered separately.
[ ] 8. Back-channel logout
I know whether logout propagates to all client apps.
I have tested it end-to-end.
[ ] 9. Persistent sessions
"Remember me" behavior was a deliberate UX and
security decision, not a default left in place.
[ ] 10. Compliance constraints
I know which (if any) industry standards or
regulations constrain our configuration, and I
involved the right people in those decisions.If you can check all ten, you've made the decisions that are yours to make. Now, let's break down how to approach these answers in team discussions.
Know Your Risk Profile
Before working through the sections below, place yourself on this spectrum. Each section references these profiles directly.
[Low-Stakes] -- Consumer apps, blogs, portfolios, hobby SaaS. The cost of compromising a session is low. User friction is a real concern.
[Business] -- B2B SaaS, internal tooling, e-commerce. Some sensitive data is in play. Compliance obligations may exist. Employee and customer access need different treatment.
[High-Assurance] -- Fintech, healthcare, government, regulated industries. The cost of a compromised session is high. Regulatory constraints may make some decisions for you.
You probably have multiple tiers of users and clients. A [High-Assurance] financial platform may have [Business] internal admin tools and [Low-Stakes] public-facing marketing pages. That's expected. Per-client configuration is a feature, not an edge case.
Section 1: Access Token Lifetime
The question that matters: if your access token were stolen right now, how long does the attacker have a valid credential?
Access tokens are the most important lifetime to get right, and the easiest to misconfigure by inaction. The default in Duende IdentityServer is one hour.
JWT access tokens are self-contained: once issued, they cannot be revoked before expiration. An attacker who intercepts a JWT has the full lifetime to act, and there is no call you can make to stop them.
Ask your team:
- What does our access token actually authorize? Read access to public data, or write access to financial transactions or protected health information?
- Is a 60-minute exposure window acceptable for what our tokens protect?
- Do our APIs validate tokens offline (JWT) or by calling back to Duende IdentityServer on every request (reference tokens)?
For [High-Assurance] apps handling regulated or sensitive data, a 1-hour JWT lifetime is an anti-pattern. A stolen token grants up to 60 minutes of irrevocable access to whatever that token authorizes. Shorten the lifetime, or switch to reference tokens for the clients that need immediate revocability.
For [Low-Stakes] apps, the default is probably fine. For [Business] apps, it's worth discussing with your team.
Archetype guide:
- [Low-Stakes] 1 hour is likely fine.
- [Business] Examine what tokens authorize and adjust down for sensitive operations.
- [High-Assurance] Consider 5-15 minutes with reference tokens for anything touching regulated data.
Go deeper: Token lifetime configuration in the client model
Section 2: Refresh Token Strategy
The question that matters: if a refresh token is stolen, how long can an attacker use it to keep minting new access tokens?
Refresh tokens let clients obtain new access tokens without user interaction. They're essential for good user experience: re-authenticating every 15 minutes is not acceptable in most applications. They're also longer-lived and more powerful than access tokens, which makes the configuration decisions more consequential.
There are two decisions to make here, and they're independent.
Decision 1: Expiration model
- Absolute expiration -- the token is valid for a fixed period from issuance, full stop.
- Sliding expiration -- the lifetime extends each time the token is used, up to an absolute ceiling.
Decision 2: Rotation behavior
-
ReUse(the default in Duende IdentityServer v7+) -- the same refresh token is reused across requests. -
OneTime-- a new refresh token is issued on each use, and the old one is consumed.
OneTime rotation sounds more secure. It's counterintuitive, but it's often worse in practice. If the network drops between the moment Duende IdentityServer issues the new token and the moment your client receives it, the old token is already consumed, and the new one is lost. The user is locked out. The OneTime model trades a theoretical security improvement for a concrete reliability failure mode.
The ReUse default is a deliberate, reasoned choice. More rotation is not always more security.
Ask your team:
- Do our users expect to stay logged in across days or weeks without re-authenticating?
- What happens in our app if a session is suddenly terminated -- mild friction, data loss, or a situation where the disruption is actually the right call?
- Have we thought through what a stolen refresh token enables, compared to a stolen access token?
Archetype guide:
- [Low-Stakes] Sliding expiration with ReUse and a generous absolute ceiling is fine.
- [Business] Set an absolute ceiling that fits your data sensitivity.
- [High-Assurance] Absolute expiration only, shorter lifetimes, and a clear answer for what happens when a token is potentially replayed.
Go deeper: Refresh tokens: expiration, rotation, and replay detection
Section 3: Session Lifetime and Observability
The question that matters: can you answer right now -- how many active sessions does your application have?
By default, all session state in Duende IdentityServer lives in a cookie. That cookie is opaque to the server. You cannot query active sessions, see who is logged in, or terminate a session without the user's browser.
Cookie-only sessions work for many applications. The limitations surface when someone needs to answer any of the following:
- A user's device was stolen at a coffee shop. Can you end their session before someone walks through the door with it?
- A former employee's access needs to be revoked immediately. Does logging them out of your identity provider actually propagate?
- Your security team wants to audit active sessions after a suspected credential compromise. Can you give them anything?
Server-side sessions store authentication state on the server and keep only a reference in the cookie. They make sessions visible, queryable, and revocable from outside the browser.
The device theft scenario is worth taking seriously. A stolen phone or laptop is not a hypothetical: your security team will face it eventually. How fast can you respond, and does your current configuration give you any tools to help?
Session lifetime itself also deserves deliberate attention. Without ASP.NET Core Identity, Duende IdentityServer's cookie lifetime defaults to 10 hours. With ASP.NET Core Identity, the default climbs to 14 days. Both of those numbers were inherited from defaults set somewhere upstream. Are they the right numbers for your application?
Ask your team:
- If a user's device were stolen right now, what could we do, and how long would it take?
- Does our session lifetime reflect a decision we made, or one we inherited from a template?
- Do we need administrative visibility into who is logged in?
Server-side sessions are a feature of Duende IdentityServer Business and Enterprise editions. If your risk profile requires session observability and revocation -- and for many [High-Assurance] applications it does -- that capability requires a higher-tier license.
Archetype guide:
- [Low-Stakes] Cookie-only sessions are likely sufficient.
- [Business] Consider server-side sessions if you have multiple user populations or admin users whose access may need to be revoked.
- [High-Assurance] Server-side sessions are not optional.
Go deeper: Server-side sessions: setup, querying, and lifetime
Section 4: Inactivity Timeout
The question that matters: do you distinguish between a user who has been actively working for eight hours and one who logged in eight hours ago and walked away?
OAuth and OpenID Connect have no native concept of inactivity. The protocols don't know if the user is at their keyboard or their session is sitting open on a shared device in a break room. Coordinating inactivity timeouts across multiple tokens and a session cookie is something your application must configure explicitly.
Duende IdentityServer supports inactivity timeout through server-side sessions and the CoordinateClientLifetimesWithUserSession setting. When a client's access token expires, and it uses a refresh token, that refresh request signals activity to the server. No activity within the timeout window triggers session expiration, back-channel logout, and token revocation.
Most teams don't know this feature exists. Of the teams that enable it, many configure it incorrectly.
The most common misconfiguration: the access token lifetime is set longer than the inactivity timeout window. The client never needs to refresh, so no activity is ever signaled, so the inactivity feature silently does nothing. Access token lifetime must be shorter than the inactivity timeout for this to work.
Ask your team:
- If a user leaves a session open on a shared device, when does it expire?
- Have we tested what actually happens when a session times out mid-workflow?
- Do we have a policy on idle sessions, and does our configuration enforce it?
Archetype guide:
- [Low-Stakes] Probably not needed.
- [Business] Worth considering for shared-device environments, multi-user machines, or enterprise deployments.
- [High-Assurance] Likely required, and worth testing explicitly before going to production.
Go deeper: Inactivity timeout with server-side sessions
Section 5: JWT vs Reference Tokens
The question that matters: when you revoke access, does your API find out immediately, or just eventually?
JWTs validate offline. The API checks the token's signature and expiration locally. No network call, no dependency on Duende IdentityServer availability. Fast, scalable, and once issued, impossible to revoke before expiration.
Reference tokens are pointers. The API calls Duende IdentityServer's introspection endpoint on every request to validate the token. Slower, adds a network dependency, and supports immediate revocation.
Most teams default to JWTs everywhere and never revisit it. That's often fine. It becomes a problem when revocation matters.
Token type is configured per client in Duende IdentityServer, so the answer doesn't have to be the same for every API. JWT tokens for most APIs, reference tokens for the one or two clients that handle sensitive operations -- payment processing, protected health information, admin actions -- where immediate revocability justifies the introspection overhead.
Ask your team:
- Do our APIs need to act on token revocation in real time, or is "expired soon" acceptable?
- Can our sensitive APIs tolerate a network call to Duende IdentityServer on every request?
- Are all our clients equal, or do some handle operations where instant revocation has real value?
Archetype guide:
- [Low-Stakes] Using JWTs everywhere is fine.
- [Business] Mixed approach: JWTs for most clients, reference tokens for admin or high-privilege operations.
- [High-Assurance] Reference tokens for any client handling regulated or sensitive data.
Go deeper: Reference tokens and introspection
Section 6: Back-Channel Logout
The question that matters: when a user logs out of your authorization server, do all their downstream apps find out?
Front-channel logout, the classic approach using hidden iframes, is increasingly unreliable. Modern browsers restrict third-party cookies by default, which breaks iframe-based logout notifications. If your logout implementation relies on front-channel mechanisms, you may have already discovered that "logged out" in one place doesn't always mean logged out everywhere.
Back-channel logout sends an HTTP POST directly to each registered client's logout endpoint when a session ends. It doesn't depend on the browser, doesn't break with cookie restrictions, and works for clients that have no UI at all.
One way to check: log out of your authorization server, then open one of your client applications without going through the login flow. Are you still authenticated? The answer tells you whether your logout propagates.
Ask your team:
- When a user logs out centrally, does that propagate to all their active client sessions?
- Do we have background services or long-running processes that need to react to logout events?
- Have we actually tested a full logout end-to-end across all client applications?
Archetype guide:
- [Low-Stakes] May not matter if users have only one client.
- [Business] Relevant when users have multiple active applications.
- [High-Assurance] Required. A logout that doesn't propagate is a security gap in regulated contexts.
Go deeper: Back-channel logout notifications
Section 7: Persistent Sessions and "Remember Me"
The question that matters: "remember me" is a user experience feature. Have you decided what security trade-off it represents?
Persistent sessions, enabled via AuthenticationProperties.IsPersistent in ASP.NET Core, extend session lifetime beyond the browser session. The cookie survives browser restarts. The user stays logged in across days or weeks.
Users dislike re-authenticating. Attackers appreciate persistent sessions on unattended devices.
There's no right answer here, but the answer should be deliberate and should match your user population. A consumer app accessed from personal phones carries different risks than an enterprise tool running on shared workstations. The right policy for a developer portal is different from the right policy for a payroll system.
Ask your team:
- Is the user most likely to enable "remember me" on a personal device or a shared one?
- Do we have different user populations who warrant different defaults? Think about employees vs consumers, admins vs standard users, etc.
- Have we thought through what "remember me" actually means in our app, and do we communicate it to users?
Archetype guide:
- [Low-Stakes] Reasonable to enable with a sensible absolute ceiling.
- [Business] Consider making it opt-in with a clear UX explanation of what it does.
- [High-Assurance] Consider disabling entirely, or restricting to specific client types where the risk is understood.
Go deeper: Session establishment and cookie configuration
Section 8: Regulatory and Compliance Constraints
The question that matters: has your compliance team ever handed you a maximum session timeout requirement? If not, have you asked?
In some industries, these decisions are not entirely yours to make. Compliance frameworks and regulatory requirements can constrain token lifetimes, mandate session audit trails, or require specific logout behaviors. The specifics vary by industry, jurisdiction, and certification: they're outside the scope of this post and change often enough that you shouldn't rely on any single source.
What matters is that you know which constraints apply to your application before you finalize any configuration.
The cost of finding out afterward is high. Retrofitting session management policies into a running production system is harder than designing them up front. And "we weren't aware of the requirement" is rarely a satisfactory audit response.
Ask your team:
- Does our industry have published standards or regulations that constrain token lifetimes or require session audit trails?
- Have we involved legal or compliance in these configuration decisions?
- If we were audited tomorrow, could we explain why our session lifetime is what it is?
Archetype guide:
- [Low-Stakes] Likely not applicable.
- [Business] Check contractual obligations with enterprise customers.
- [High-Assurance] Non-negotiable. Involve legal and compliance before finalizing configuration.
The Process Is the Point
These questions don't have universal answers. The right access token lifetime for a healthcare records system is not the right lifetime for a recipe app. The right refresh token expiration for an enterprise SaaS is not the right expiration for a weekend side project.
They do have something in common: each one requires a conversation between developers, security engineers, product owners, and sometimes legal teams. The output of that conversation is a configuration that reflects deliberate decisions, not inherited defaults.
The goal isn't paranoia. It's intentionality. Working through these questions as a team is worth more than any specific number in a config file.
Where to Go Next
The Duende IdentityServer documentation covers each of these areas in depth. Start with what felt most unfamiliar in this post:
- Token lifetime and access token type configuration
- Refresh token configuration and rotation behavior
- Server-side sessions
- Inactivity timeout
- Reference tokens and introspection
- Back-channel logout
- Session establishment and persistent cookies
- Operational store and token cleanup
- Production deployment checklist -- once you've made these decisions, this covers the infrastructure configuration needed to ship
Questions about how any of this applies to your specific setup? The Duende community forums are a good place to start.