[GH-ISSUE #5185] [Feature Request] Cache OIDC access token and refresh before expiry #4051

Closed
opened 2026-05-05 14:34:06 -06:00 by gitea-mirror · 2 comments
Owner

Originally created by @shani1998 on GitHub (Feb 25, 2026).
Original GitHub issue: https://github.com/fatedier/frp/issues/5185

Originally assigned to: @blizard863 on GitHub.

Describe the feature request

Current Behavior:
In the current OIDC implementation for frpc, a new access token is requested from the OIDC provider for every authentication event. This creates significant overhead during:

  1. Heartbeat Pings: frpc and frps frequently exchange pings to keep the connection alive. Fetching a new token for every validation cycle increases latency.
  2. Reconnections: On unstable networks, frequent OIDC handshakes can lead to rate-limiting or service denial from the OIDC provider.

Proposed Feature:
Implement a caching and proactive refresh mechanism for OIDC tokens within frpc to improve performance and reliability.

Key Components of the Proposal:

  1. Token Caching: Store the access token in memory and reuse it for subsequent heartbeats and proxy registrations until it is near expiry.
  2. Customizable Refresh Buffer: Introduce a new configuration parameter: tokenRefreshAdvanceDuration.
    • Default: 300 seconds (5 minutes).
    • Function: This defines how many seconds before actual token expiry frpc should proactively fetch a new token.
  3. Proactive Refresh: Ensure frpc always has a valid token ready before the next heartbeat, preventing connection drops due to expired credentials during transit.

This change reduces the load on OIDC providers and ensures that frpc remains connected even if the OIDC provider has temporary high latency.

I have already drafted this implementation in PR #5175 and would love to discuss the configuration logic here.

Describe alternatives you've considered

The current "fetch-on-demand" approach is the only alternative, but it is inefficient for users with high-frequency heartbeats or strict OIDC rate limits.

Affected area

  • Docs
  • Installation
  • Performance and Scalability
  • Security
  • User Experience
  • Test and Release
  • Developer Infrastructure
  • Client Plugin
  • Server Plugin
  • Extensions
  • Others
Originally created by @shani1998 on GitHub (Feb 25, 2026). Original GitHub issue: https://github.com/fatedier/frp/issues/5185 Originally assigned to: @blizard863 on GitHub. ### Describe the feature request **Current Behavior:** In the current OIDC implementation for `frpc`, a new access token is requested from the OIDC provider for every authentication event. This creates significant overhead during: 1. **Heartbeat Pings:** `frpc` and `frps` frequently exchange pings to keep the connection alive. Fetching a new token for every validation cycle increases latency. 2. **Reconnections:** On unstable networks, frequent OIDC handshakes can lead to rate-limiting or service denial from the OIDC provider. **Proposed Feature:** Implement a caching and proactive refresh mechanism for OIDC tokens within `frpc` to improve performance and reliability. **Key Components of the Proposal:** 1. **Token Caching:** Store the access token in memory and reuse it for subsequent heartbeats and proxy registrations until it is near expiry. 2. **Customizable Refresh Buffer:** Introduce a new configuration parameter: `tokenRefreshAdvanceDuration`. * **Default:** `300` seconds (5 minutes). * **Function:** This defines how many seconds *before* actual token expiry `frpc` should proactively fetch a new token. 3. **Proactive Refresh:** Ensure `frpc` always has a valid token ready before the next heartbeat, preventing connection drops due to expired credentials during transit. This change reduces the load on OIDC providers and ensures that `frpc` remains connected even if the OIDC provider has temporary high latency. *I have already drafted this implementation in PR #5175 and would love to discuss the configuration logic here.* ### Describe alternatives you've considered The current "fetch-on-demand" approach is the only alternative, but it is inefficient for users with high-frequency heartbeats or strict OIDC rate limits. ### Affected area - [ ] Docs - [ ] Installation - [x] Performance and Scalability - [x] Security - [ ] User Experience - [ ] Test and Release - [ ] Developer Infrastructure - [x] Client Plugin - [ ] Server Plugin - [ ] Extensions - [ ] Others
gitea-mirror 2026-05-05 14:34:06 -06:00
  • closed this issue
  • added the
    proposal
    label
Author
Owner

@blizard863 commented on GitHub (Feb 26, 2026):

Thanks for the contribution! The caching idea is solid and addresses a real problem. A few suggestions before merging:

  1. Remove tokenRefreshAdvanceDuration config option
    We should avoid introducing new user-facing configuration unless absolutely necessary. Every new field adds cognitive overhead for users. In practice, no mainstream OAuth2 SDK asks users to configure refresh timing — it's handled internally.

  2. Use expires_in from the token response to drive refresh
    The token endpoint response already includes expires_in, so we have everything needed to determine when to refresh. The caching and proactive refresh logic should be fully automatic — users get the optimization by default without needing to understand OAuth2 token lifecycle.

  3. Keep backward compatibility transparent
    With automatic refresh, the behavior change is purely an internal optimization. Existing users benefit automatically without any config migration, and the external API surface remains unchanged.

<!-- gh-comment-id:3964345884 --> @blizard863 commented on GitHub (Feb 26, 2026): Thanks for the contribution! The caching idea is solid and addresses a real problem. A few suggestions before merging: 1. Remove tokenRefreshAdvanceDuration config option We should avoid introducing new user-facing configuration unless absolutely necessary. Every new field adds cognitive overhead for users. In practice, no mainstream OAuth2 SDK asks users to configure refresh timing — it's handled internally. 2. Use expires_in from the token response to drive refresh The token endpoint response already includes expires_in, so we have everything needed to determine when to refresh. The caching and proactive refresh logic should be fully automatic — users get the optimization by default without needing to understand OAuth2 token lifecycle. 3. Keep backward compatibility transparent With automatic refresh, the behavior change is purely an internal optimization. Existing users benefit automatically without any config migration, and the external API surface remains unchanged.
Author
Owner

@shani1998 commented on GitHub (Feb 28, 2026):

Thanks for the contribution! The caching idea is solid and addresses a real problem. A few suggestions before merging:

  1. Remove tokenRefreshAdvanceDuration config option
    We should avoid introducing new user-facing configuration unless absolutely necessary. Every new field adds cognitive overhead for users. In practice, no mainstream OAuth2 SDK asks users to configure refresh timing — it's handled internally.
  2. Use expires_in from the token response to drive refresh
    The token endpoint response already includes expires_in, so we have everything needed to determine when to refresh. The caching and proactive refresh logic should be fully automatic — users get the optimization by default without needing to understand OAuth2 token lifecycle.
  3. Keep backward compatibility transparent
    With automatic refresh, the behavior change is purely an internal optimization. Existing users benefit automatically without any config migration, and the external API surface remains unchanged.

Thanks for making time to review the proposal. The suggestions make sense to me. I’ve updated the code to rely on the OAuth2 SDK and to use expires_in with the default 10-second delta.https://cs.opensource.google/go/x/oauth2/+/master:token.go

<!-- gh-comment-id:3976266115 --> @shani1998 commented on GitHub (Feb 28, 2026): > Thanks for the contribution! The caching idea is solid and addresses a real problem. A few suggestions before merging: > > 1. Remove tokenRefreshAdvanceDuration config option > We should avoid introducing new user-facing configuration unless absolutely necessary. Every new field adds cognitive overhead for users. In practice, no mainstream OAuth2 SDK asks users to configure refresh timing — it's handled internally. > 2. Use expires_in from the token response to drive refresh > The token endpoint response already includes expires_in, so we have everything needed to determine when to refresh. The caching and proactive refresh logic should be fully automatic — users get the optimization by default without needing to understand OAuth2 token lifecycle. > 3. Keep backward compatibility transparent > With automatic refresh, the behavior change is purely an internal optimization. Existing users benefit automatically without any config migration, and the external API surface remains unchanged. Thanks for making time to review the proposal. The suggestions make sense to me. I’ve updated the code to rely on the OAuth2 SDK and to use expires_in with the default 10-second delta.https://cs.opensource.google/go/x/oauth2/+/master:token.go
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/frp#4051
No description provided.