Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 0 additions & 63 deletions Brokerages/Authentication/AccessTokenMetaDataRequest.cs

This file was deleted.

54 changes: 0 additions & 54 deletions Brokerages/Authentication/AccessTokenMetaDataResponse.cs

This file was deleted.

27 changes: 13 additions & 14 deletions Brokerages/Authentication/LeanOAuthTokenHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ namespace QuantConnect.Brokerages.Authentication
/// </summary>
public class LeanOAuthTokenHandler : LeanOAuthTokenHandler<LeanTokenCredentials>
{
/// <summary>
/// Initializes a new instance of the <see cref="LeanOAuthTokenHandler"/> class with default token credentials type.
/// </summary>
/// <param name="apiClient">The API client used to communicate with the Lean platform.</param>
/// <param name="request">The request model used to generate the access token.</param>
/// <param name="tokenLifetime">
/// The expected lifetime of a fetched token. A 1-minute safety buffer is applied before expiry.
/// Must be provided explicitly — each brokerage has a different token lifetime.
/// </param>
public LeanOAuthTokenHandler(ApiConnection apiClient, OAuthTokenRequest request, TimeSpan tokenLifetime)
: base(apiClient, request, tokenLifetime)
{
Expand Down Expand Up @@ -71,14 +80,13 @@ public class LeanOAuthTokenHandler<T> : LeanTokenHandler<T>

/// <summary>
/// Stores the current access token and its type used for authenticating requests to the Lean platform.
/// Written inside <see cref="_lock"/>; read outside the lock via volatile fast path.
/// Always accessed inside <see cref="_lock"/>.
/// </summary>
private T _tokenCredentials;

/// <summary>
/// The UTC timestamp after which the cached token should be refreshed.
/// Always written inside <see cref="_lock"/> before <see cref="_tokenCredentials"/> is set,
/// so that a volatile read of <see cref="_tokenCredentials"/> guarantees visibility of this field.
/// Always accessed inside <see cref="_lock"/>.
/// </summary>
private DateTime _tokenExpiresAt;

Expand Down Expand Up @@ -106,21 +114,14 @@ public LeanOAuthTokenHandler(ApiConnection apiClient, OAuthTokenRequest request,
/// <summary>
/// Retrieves a valid access token from the Lean platform.
/// Caches and reuses tokens until expiration to minimize unnecessary requests.
/// Retries up to <see cref="MaxRetryCount"/> times on failure, and is thread-safe via double-checked locking.
/// Retries up to <see cref="MaxRetryCount"/> times on failure. Thread-safe via a lock.
/// </summary>
/// <param name="cancellationToken">A token used to observe cancellation requests.</param>
/// <returns>A <see cref="TokenCredentials"/> containing the token type and access token string.</returns>
/// <returns>A <see cref="LeanTokenCredentials"/> instance containing the token type and access token string.</returns>
public override T GetAccessToken(CancellationToken cancellationToken)
{
// Fast path: return cached token without acquiring the lock
if (_tokenCredentials != null && DateTime.UtcNow < _tokenExpiresAt)
{
return _tokenCredentials;
}

lock (_lock)
{
// Second check: another thread may have refreshed while we waited for the lock
if (_tokenCredentials != null && DateTime.UtcNow < _tokenExpiresAt)
{
return _tokenCredentials;
Expand All @@ -136,8 +137,6 @@ public override T GetAccessToken(CancellationToken cancellationToken)
{
if (response.Success)
{
// Write expiry before credentials — the volatile write of _tokenCredentials
// acts as a release fence, ensuring the fast-path reader sees _tokenExpiresAt.
_tokenExpiresAt = DateTime.UtcNow + _tokenLifetime - OffsetBeforeExpiration;
return _tokenCredentials = response;
}
Expand Down
7 changes: 3 additions & 4 deletions Brokerages/Authentication/LeanTokenHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,13 @@ public abstract class LeanTokenHandler<T> : DelegatingHandler
private readonly Func<TokenType, string, AuthenticationHeaderValue> _createAuthHeader;

/// <summary>
/// Initializes a new instance of the <see cref="LeanTokenHandler"/> class.
/// Initializes a new instance of the <see cref="LeanTokenHandler{T}"/> class.
/// </summary>
/// <param name="createAuthHeader">
/// An optional delegate for creating an <see cref="AuthenticationHeaderValue"/>
/// from the token type and access token. If not provided, a default implementation is used.
/// </param>
/// <param name="handler">An optional inner <see cref="HttpMessageHandler"/>. If not provided, a default <see cref="HttpClientHandler"/> is used.</param>
protected LeanTokenHandler(Func<TokenType, string, AuthenticationHeaderValue> createAuthHeader = null, HttpClientHandler handler = null)
: base(handler ?? new HttpClientHandler())
{
Expand All @@ -59,9 +60,7 @@ protected LeanTokenHandler(Func<TokenType, string, AuthenticationHeaderValue> cr
/// with optional support for caching and refresh logic.
/// </summary>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the token retrieval operation.</param>
/// <returns>
/// A <see cref="TokenCredentials"/> instance containing the token type and access token string.
/// </returns>
/// <returns>A <see cref="LeanTokenCredentials"/> instance containing the token type and access token string.</returns>
public abstract T GetAccessToken(CancellationToken cancellationToken);

/// <summary>
Expand Down
100 changes: 0 additions & 100 deletions Brokerages/Authentication/OAuthTokenHandler.cs

This file was deleted.

45 changes: 0 additions & 45 deletions Brokerages/Authentication/TokenCredentials.cs

This file was deleted.

Loading
Loading