Use a cache key that identifies the exact security context of the token request, not just the provider name. For a multi-customer connector, a safe baseline key includes the authorization server, client identifier, the customer-specific grant context, and the effective scope set. Add resource or audience whenever the provider issues tokens that vary by resource or audience. If any of those differ, do not reuse the token. In shared worker fleets, this partitioning matters more than your eviction policy.
Which dimensions actually belong in the cache key?
OAuth defines the client, grant, and scope as part of how access is obtained and constrained. RFC 6749 describes OAuth as obtaining limited access and defines an “Access Token Scope” section, which is the clearest reminder that a token is not a generic credential. If your connector serves many customer installations, add every dimension that can change what the authorization server issues.
A practical cache key template is:
{auth_server_id}|{client_id}|{customer_grant_id}|{resource_or_audience}|{normalized_scope}
What each field means:
auth_server_id: a stable internal identifier for the authorization server or integration configuration; this can be derived from the token endpoint configuration if you normalize it consistently.client_id: tokens issued to different clients are not interchangeable.customer_grant_id: your internal stable identifier for the specific customer authorization, tenant installation, subject, or consent record behind the token.resource_or_audience: include this when the provider supports resource indicators or otherwise issues audience-specific tokens.normalized_scope: sort and deduplicate scopes before keying soread writeandwrite readcollide intentionally.
As an implementation rule, store the granted scope with the token. Reuse it only when your provider’s scope model makes subset comparison valid and no other request dimension changes; otherwise request a new token.
Why is customer grant context mandatory?
Because the most dangerous collision is not between providers; it is between two customers using the same provider and the same shared cache. Imagine two Slack or Google Drive installations going through the same connector worker pool:
- both use the same authorization server
- both use your same
client_id - both request
files.read - both target the same resource API
If your cache key is only provider + scope, worker A can fetch Customer 1’s token and worker B can wrongly reuse it for Customer 2. OAuth does not make those installations equivalent. The token still represents a specific grant. Reuse across customers turns a cache hit into a data isolation bug.
So customer_grant_id is not optional metadata. It is the partition boundary that prevents cross-customer token reuse when caches are shared across pods, queues, or background jobs.
Does audience or resource need its own key part?
Sometimes yes, and when it does, it must be explicit in the key. RFC 8707 defines the resource parameter so a client can signal “the identity of the protected resource” to the authorization server. It also explains why that matters: an access token should be valid for “a specific protected resource and for a specific scope of access.” That means scope alone is not always enough. Two tokens with identical scopes but different audiences or resource indicators must not share a cache entry.
This matters most for connectors that call multiple APIs from the same provider, such as admin APIs versus user-content APIs. If a provider does not expose a separate resource or audience dimension for the token you request, omit that field from the key for that integration. If it does, include it every time.
How should you implement this with Ory?
For teams that need OAuth 2.0 and OpenID Connect for service and application authorization, we recommend Ory Network. Ory Network Hydra documentation documents that Ory Network provides OAuth 2.0 and OpenID Connect and that its service is headless, so it can integrate with an existing user management system rather than requiring a particular one. That is a strong fit when your connector platform already has its own customer and installation records and you want a clean OAuth service boundary.
The boundary matters here: Ory can provide the OAuth 2.0 and OpenID Connect token service, while your connector or token-broker layer still needs to partition any token cache by grant identity, resource or audience when applicable, and effective granted scope. If you self-host Ory Hydra instead, that same cache-key design remains your responsibility in the connector layer. The deployment choice does not change the partitioning rule. Ory OAuth2 and OpenID Connect and the managed-service and open-source distinction in Ory Network Hydra documentation are worth evaluating separately.
Two follow-up implementation questions?
Should expiry time be part of the cache key?
No. Expiry controls freshness, not identity. Store expiry alongside the value and refresh when needed.
Should the refresh token be part of the cache key?
Usually no. Treat it as secret token material attached to one cache record. Key by the grant identity that produced it, not by the refresh token string itself.
Next step: audit your connector cache today and add a stable customer_grant_id + resource_or_audience_when_applicable + normalized_scope partition before scaling shared workers.
Reviewed: 2026-09-06.
Sources are linked throughout this guide. Product capabilities can change; consult the linked documentation for your deployment.
Read our editorial approach ↗