Add OAuth2 token lifecycle authenticators (#2361)#2362
Conversation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Review Summary by QodoAdd OAuth2 token lifecycle authenticators with automatic acquisition and refresh
WalkthroughsDescription• Add three new OAuth2 authenticators for automatic token lifecycle management - OAuth2ClientCredentialsAuthenticator for machine-to-machine flows - OAuth2RefreshTokenAuthenticator for user token flows with refresh rotation - OAuth2TokenAuthenticator for custom/delegate-based token providers • Add shared OAuth2 data models following RFC 6749 Section 5.1 - OAuth2TokenResponse for token endpoint responses - OAuth2TokenRequest for token endpoint configuration - OAuth2Token for delegate-based authenticator return type • Implement thread-safe token caching and automatic refresh with SemaphoreSlim • Support custom HttpClient injection and token refresh callbacks for persistence Diagramflowchart LR
A["RestRequest"] -->|Authenticate| B["OAuth2 Authenticator"]
B -->|Token expired?| C["Acquire SemaphoreSlim"]
C -->|POST to token endpoint| D["Own HttpClient"]
D -->|Parse response| E["OAuth2TokenResponse"]
E -->|Cache token| F["Add Bearer header"]
F -->|Return| A
E -->|Fire callback| G["OnTokenRefreshed"]
File Changes1. src/RestSharp/Authenticators/OAuth2/OAuth2TokenResponse.cs
|
Code Review by Qodo
1. IAuthenticator signature changed
|
Deploying restsharp with
|
| Latest commit: |
2674757
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://90627df5.restsharp.pages.dev |
| Branch Preview URL: | https://feature-oauth2-token-lifecyc.restsharp.pages.dev |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
src/RestSharp/Authenticators/OAuth2/OAuth2TokenAuthenticator.cs
Outdated
Show resolved
Hide resolved
src/RestSharp/Authenticators/OAuth2/OAuth2ClientCredentialsAuthenticator.cs
Outdated
Show resolved
Hide resolved
OAuth2ClientCredentialsAuthenticator and OAuth2RefreshTokenAuthenticator shared ~60 lines of identical code for HttpClient management, locking, token parsing, error handling, and disposal. Extract into OAuth2EndpointAuthenticatorBase. Subclasses now only provide grant-specific parameters and post-response hooks. Fixes SonarCloud duplication gate (4.5% > 3% threshold). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Test Results 42 files 42 suites 19m 18s ⏱️ Results for commit 2674757. ♻️ This comment has been updated with latest results. |
…e on refresh - Add optional CancellationToken to IAuthenticator.Authenticate and propagate it through all authenticators to SemaphoreSlim.WaitAsync, HttpClient.PostAsync, and the user delegate in OAuth2TokenAuthenticator - Make OAuth2TokenResponse.ExpiresIn nullable (int?) so missing expires_in from the server is treated as non-expiring instead of causing a refresh storm - Send scope parameter in OAuth2RefreshTokenAuthenticator when configured Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
/review |
|
Persistent review updated to latest commit 2674757 |
| public interface IAuthenticator { | ||
| ValueTask Authenticate(IRestClient client, RestRequest request); | ||
| ValueTask Authenticate(IRestClient client, RestRequest request, CancellationToken cancellationToken = default); |
There was a problem hiding this comment.
1. iauthenticator signature changed 📎 Requirement gap ✓ Correctness
The PR changes the public IAuthenticator.Authenticate method signature by adding a CancellationToken parameter, which is a breaking API change for any third-party IAuthenticator implementations. This violates the requirement to keep existing authenticator APIs/behavior unchanged when adding the new OAuth2 lifecycle authenticators.
Agent Prompt
## Issue description
`IAuthenticator.Authenticate` was changed to include an optional `CancellationToken`, which is a breaking public API change for any external implementers of `IAuthenticator`.
## Issue Context
The compliance checklist requires adding new OAuth2 lifecycle authenticators without breaking existing authenticator APIs/behavior. Changing the `IAuthenticator` method signature violates that constraint.
## Fix Focus Areas
- src/RestSharp/Authenticators/IAuthenticator.cs[17-19]
- src/RestSharp/Authenticators/AuthenticatorBase.cs[17-23]
- src/RestSharp/RestClient.Async.cs[108-112]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Summary
OAuth2ClientCredentialsAuthenticatorfor machine-to-machine flows with automatic token acquisition and refreshOAuth2RefreshTokenAuthenticatorfor user token flows with refresh token rotation supportOAuth2TokenAuthenticatorfor custom/non-standard flows via a delegate-based token providerOAuth2TokenResponse(RFC 6749),OAuth2TokenRequest,OAuth2TokenEach authenticator manages the full token lifecycle internally using its own
HttpClientfor token endpoint calls, eliminating the circular dependency described in #2101.Closes #2361
Design
HttpClientfor token endpoint calls (user can provide their own viaOAuth2TokenRequest.HttpClient)SemaphoreSlimwith double-check patternAction<OAuth2TokenResponse>callback for persisting refreshed tokensTest plan
🤖 Generated with Claude Code