OAuth separates calling an API from renewing the right to call it again. Teams that blur the two tend to create broken sign-ins, wider exposure and harder support cases.
When a business app starts failing after a normal session ends, the problem is often not the login itself. It is a token boundary error: the app has tried to use a short-lived access token as though it were the credential for renewal, or it has exposed a long-lived refresh token where only request-time access should exist. That mistake turns routine expiry into broken sign-ins, repeated support tickets and, in some cases, wider security exposure than the team intended.
OAuth 2.0 draws this boundary clearly. An access token is the credential a client presents to a resource server to access protected resources. A refresh token is used at the authorisation server to obtain a new access token when the old one expires or is no longer valid. They are related, but they are not interchangeable.
That distinction matters for SaaS integrations, customer portals and internal tools tied together with OAuth. It affects where a token can safely live, which service should see it, and how much damage a compromise can do. Meta’s documentation gives a concrete implementation example: its access tokens are used by the app to make Graph API calls, and different token types exist for different use cases. The token pattern is therefore standard in principle, but provider-specific in the details.
For teams building or overseeing business apps, the practical question is not whether tokens exist. It is which token should sit near the browser, which should remain server-side, and what operational symptoms appear when that separation breaks.
What each token actually proves
An access token proves that the client has permission to call a protected API for a limited time and, usually, within a limited scope. It is a presentation credential. The resource server inspects it and decides whether to serve the request.
A refresh token proves something narrower and more sensitive: that the client may ask for a fresh access token. It is a renewal credential. It should not be sent to the API endpoint that serves user data or account actions.
The OAuth standard also makes refresh-token issuance optional at the authorisation server’s discretion. That is a useful guard against assuming every identity provider behaves the same way. Some providers issue refresh tokens broadly, some restrict them, and some use different renewal patterns altogether.
Token roles, storage and risk boundary
| Token | What it proves | Where it should live | How long it should last | Safe operations | Failure mode when confused |
|---|---|---|---|---|---|
| Access token | Permission to call a protected resource for a defined scope | Near the API call path, often in the backend or short-lived client session | Short-lived, with expiry handled by the client or backend logic | Call protected APIs, fetch user data, perform scoped actions | If treated as renewal power, expired sessions keep breaking and users are pushed into unnecessary re-authentication |
| Refresh token | Permission to ask the authorisation server for a new access token | Server-side or in another tightly controlled store, depending on client type and provider rules | Longer-lived than an access token, but provider-specific and not guaranteed to be fixed | Renew access, extend a session without re-prompting the user, replace expired access tokens | If exposed in front-end contexts, a compromise can grant ongoing renewal until the token is revoked or expires |
OAuth 2.0 is explicit that access tokens must be kept confidential in transit and storage. That confidentiality requirement is one reason teams should resist the habit of dropping long-lived credentials into front-end code, browser storage or logs just because the flow is convenient.
How vendor documentation reinforces the split
Meta’s access-token guidance is a useful vendor example because it shows the same separation in practice without pretending every platform works alike. Meta describes access tokens as opaque strings used by the app to make Graph API calls, and it documents multiple token classes, including user, app, page, system user and client tokens. That is a reminder that token handling is not just an OAuth abstract. Each ecosystem decides which token types exist, what each one can do and how long it may last.
Meta also notes that token lifetimes can vary, with short-lived access tokens typically lasting about one to two hours and long-lived tokens about 60 days, while warning developers not to depend on those lifetimes staying the same. That warning matters because teams often build support expectations around a duration they saw in one environment and then carry that assumption into another provider, tenant or product release.
What goes wrong when teams collapse the boundary
- Users are forced to log in again when the app keeps using an expired access token instead of renewing it properly.
- Support teams spend time diagnosing failures that are really token-lifetime mismatches, not account problems.
- Long-lived renewal credentials end up in user-visible or front-end contexts, which increases exposure if a device, browser session or script is compromised.
- Developers assume one provider’s token behaviour applies everywhere, then discover the renewal flow is missing or different in the next integration.
Those failures are operational, not theoretical. The first symptom is usually an API call that starts failing after a session has been active for some time. The second is a user who sees repeated prompts despite an apparently valid login. The third is a recovery process that is slower and riskier than it should be because the wrong credential class was placed in the wrong part of the system.
How to diagnose the problem quickly
- Check whether the failing request is carrying an access token that has expired or been invalidated.
- Verify whether the application stores and uses a refresh token at the authorisation server boundary, rather than trying to reuse the access token for renewal.
- Inspect where the token is stored. If a renewal credential appears in browser code, local storage or another exposed context, treat that as a design problem.
- Confirm that the provider actually supports refresh tokens for the client type you are using. OAuth allows refresh-token issuance, but it does not require it.
- If the provider documents different token classes, map your app’s behaviour to the specific class in use rather than to the word token in general.
What business teams should do instead
The safest default is simple. Keep access tokens close to the request path and keep refresh tokens away from user-visible contexts unless your architecture and provider rules explicitly require otherwise. In most business applications, that means the backend handles renewal while the frontend receives only the minimum credential needed for user interaction.
That design reduces three common risks. First, it limits the lifetime of what is exposed in the browser. Second, it makes expiry manageable without forcing users back through full authentication every time a short token lapses. Third, it creates a clearer support trail because the app can distinguish between expired access, missing renewal support and provider-specific token rules.
Teams should also document which provider behaviour they rely on. A change in token lifetime, revocation rules or issuance policy can alter session handling without any change in your own code. That is especially relevant in integrations that sit across a SaaS login, a customer portal and an internal workflow tool.
Limits and exceptions
The OAuth standard does not force one universal storage pattern. Client type, authorisation server policy and platform constraints all matter. Mobile apps, server-rendered web apps, SPAs and machine-to-machine integrations do not all handle renewal in the same way. The evidence here supports the boundary itself, not a single universal deployment recipe.
Meta’s token lifetimes are also provider-specific and may change. Their figures are useful as a working example, not as a rule for all identity systems. A team that copies those durations into another environment without checking the provider documentation will eventually run into avoidable errors.
One more limit matters: having a refresh token does not make an integration secure by itself. It only means the app can renew access without forcing the user to start again. The real security question is where that renewal credential lives, who can reach it, and how the system behaves if that storage is compromised.
The practical decision
If your app currently treats all OAuth credentials as one thing, separate them now. Put access tokens on the request side of the boundary, keep refresh tokens on the renewal side, and check the provider documentation before you assume either lifetime or storage pattern. That one decision will prevent most of the sign-in failures and credential-handling mistakes that make OAuth integrations expensive to support.