MCPcopy Index your code
hub / github.com/coder/coder / RefreshOAuth2Token

Function RefreshOAuth2Token

coderd/x/chatd/mcpclient/mcpclient.go:840–889  ·  view source on GitHub ↗

RefreshOAuth2Token checks whether the given MCP user token is expired (or within 10 seconds of expiry) and refreshes it using the OAuth2 credentials from the server config. If the token is still valid, no network call is made and Refreshed is false. The caller is responsible for persisting the resu

(
	ctx context.Context,
	cfg database.MCPServerConfig,
	tok database.MCPServerUserToken,
)

Source from the content-addressed store, hash-verified

838// The caller is responsible for persisting the result when
839// Refreshed is true.
840func RefreshOAuth2Token(
841 ctx context.Context,
842 cfg database.MCPServerConfig,
843 tok database.MCPServerUserToken,
844) (RefreshResult, error) {
845 oauth2Cfg := &oauth2.Config{
846 ClientID: cfg.OAuth2ClientID,
847 ClientSecret: cfg.OAuth2ClientSecret,
848 Endpoint: oauth2.Endpoint{
849 TokenURL: cfg.OAuth2TokenURL,
850 },
851 }
852
853 oldToken := &oauth2.Token{
854 AccessToken: tok.AccessToken,
855 RefreshToken: tok.RefreshToken,
856 TokenType: tok.TokenType,
857 }
858 if tok.Expiry.Valid {
859 oldToken.Expiry = tok.Expiry.Time
860 }
861
862 // Cap the refresh HTTP call so a stalled token endpoint
863 // cannot block the entire MCP connection phase. The timeout
864 // matches connectTimeout used for MCP server connections.
865 refreshCtx, cancel := context.WithTimeout(ctx, connectTimeout)
866 defer cancel()
867
868 // TokenSource automatically refreshes expired tokens. It
869 // uses a 10-second expiry window, so tokens about to expire
870 // are also refreshed proactively.
871 newToken, err := oauth2Cfg.TokenSource(refreshCtx, oldToken).Token()
872 if err != nil {
873 return RefreshResult{}, xerrors.Errorf("refresh oauth2 token: %w", err)
874 }
875
876 refreshed := newToken.AccessToken != tok.AccessToken
877
878 // Preserve the old refresh token when the provider doesn't
879 // rotate (returns empty).
880 refreshToken := cmp.Or(newToken.RefreshToken, tok.RefreshToken)
881
882 return RefreshResult{
883 AccessToken: newToken.AccessToken,
884 RefreshToken: refreshToken,
885 TokenType: newToken.TokenType,
886 Expiry: newToken.Expiry,
887 Refreshed: refreshed,
888 }, nil
889}

Callers 2

refreshMCPUserTokenMethod · 0.92

Calls 3

TokenSourceMethod · 0.95
TokenMethod · 0.65
ErrorfMethod · 0.45

Tested by

no test coverage detected