Skip to content

Conversation

@foliv57
Copy link

@foliv57 foliv57 commented Nov 29, 2025

  • Introduces a DisableCredentialsCachePersistence() builder method in client CamundaCloudClientBuilder to prevent persisting token cache in file system. The goal is to allow users to setup an in-memory only cache for e.g. serverless usage of the client.
  • Fixes concurrent access issue to AccessToken cache. The introduction of a SemaphoreSlim will protect concurrent accesses to the dictionary and the file system, and prevent concurrent token fetching. The choice of SemaphoreSlim is done because it is the lock mechanism that fits the best with async/await model. The implementation is optimized to prevent locking when a valid token is in cache.
  • Introduces a UseAccessTokenDueDateTolerance(TimeSpan tolerance) builder method in client CamundaCloudClientBuilder. The goal of this option is to allow the user to refresh the AccessToken slightly before expiration to prevent that, because of network latency, a token considered valid by the client is expired when validated by the authorization server.

This change also solves partially issue 637. But the issue rather mentions introducing different implementation of the IAccessTokenCache. This approach is more impacting for the PersistedAccessTokenCache for just an in-memory only alternative, as this implementation already have its in-memory cache. To limit the impact, I chose to only improve the existing implementation.

closes #415 #642

…ntials cache persistence and add tolerance for token expiration

- Adds a DisableCredentialsCachePersistence() method in client CamundaCloudClientBuilder to prevent persisting token cache in file system to keep only in-memory cache.
- Fixes concurrent access issue to AccessToken cache.
- Adds AccessToken due date tolerance.

Refs: camunda-community-hub#415 camunda-community-hub#642
@foliv57 foliv57 requested a review from ChrisKujawa as a code owner November 29, 2025 09:46
@CLAassistant
Copy link

CLAassistant commented Nov 29, 2025

CLA assistant check
All committers have signed the CLA.

@ChrisKujawa ChrisKujawa requested a review from Copilot December 4, 2025 08:51
Copilot finished reviewing on behalf of ChrisKujawa December 4, 2025 08:54
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enhances the CamundaCloudTokenProvider with three key improvements: (1) an option to disable file system persistence for serverless/ephemeral environments, (2) thread-safety improvements using SemaphoreSlim to prevent concurrent access issues, and (3) a configurable tolerance period to refresh tokens before expiration to account for network latency.

  • Adds DisableCredentialsCachePersistence() and UseAccessTokenDueDateTolerance() builder methods to both ICamundaCloudClientBuilder and ICamundaCloudTokenProviderBuilder interfaces
  • Implements SemaphoreSlim-based locking in PersistedAccessTokenCache to protect concurrent access to the token cache dictionary and file system
  • Refactors token validation logic to support early refresh based on a configurable tolerance period

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
Client/Impl/Misc/PersistedAccessTokenCache.cs Core implementation of concurrency protection, persistence flag, and tolerance-based token validation
Client/Impl/Builder/CamundaCloudTokenProviderBuilder.cs Adds builder methods for new features and passes parameters to token provider
Client/Impl/Builder/CamundaCloudClientBuilder.cs Exposes new builder methods through the client builder interface
Client/Impl/Builder/CamundaCloudTokenProvider.cs Updates constructor to accept and forward new configuration parameters
Client/Api/Builder/ICamundaCloudTokenProviderBuilder.cs Defines interface for new token provider builder methods with documentation
Client/Api/Builder/ICamundaCloudClientBuilder.cs Defines interface for new client builder methods with documentation
Client.UnitTests/Impl/Misc/PersistedAccessTokenCacheTest.cs Adds comprehensive tests for tolerance feature and persistence disabling
Client.UnitTests/Impl/Builder/CamundaCloudTokenProviderTest.cs Adds validation tests for tolerance parameter

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

ICamundaCloudClientBuilderFinalStep UsePersistedStoragePath(string path);

/// <summary>
/// Disables credentials cache persitence to file system.
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling error: "persitence" should be "persistence"

Suggested change
/// Disables credentials cache persitence to file system.
/// Disables credentials cache persistence to file system.

Copilot uses AI. Check for mistakes.
Comment on lines +70 to +80
public ICamundaCloudClientBuilderFinalStep DisableCredentialsCachePersistence()
{
_ = camundaCloudTokenProviderBuilder.DisableCredentialsCachePersistence();
return this;
}

public ICamundaCloudClientBuilderFinalStep UseAccessTokenDueDateTolerance(TimeSpan tolerance)
{
_ = camundaCloudTokenProviderBuilder.UseAccessTokenDueDateTolerance(tolerance);
return this;
}
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing XML documentation comment. The public methods DisableCredentialsCachePersistence() and UseAccessTokenDueDateTolerance() should have XML documentation comments (/// summary tags) consistent with other methods in this class.

Copilot uses AI. Check for mistakes.

private readonly string tokenStoragePath;
private readonly bool persistedCredentialsCacheEnabled;
private readonly SemaphoreSlim mutex = new SemaphoreSlim(1, 1);
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SemaphoreSlim instance should be disposed to free unmanaged resources. The class should implement IDisposable and dispose the semaphore in the Dispose method. SemaphoreSlim implements IDisposable and should be properly disposed to avoid potential resource leaks.

Copilot uses AI. Check for mistakes.
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Security.Cryptography;
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The using System.Security.Cryptography; statement is unused and should be removed. There are no references to any types from this namespace in the file.

Suggested change
using System.Security.Cryptography;

Copilot uses AI. Check for mistakes.
Comment on lines +57 to +58
if (this.CachedCredentials.TryGetValue(audience, out var currentAccessToken)
&& this.IsValid(currentAccessToken))
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential race condition: The dictionary read at line 57-58 (outside the lock) could race with the write at line 147 (inside the lock). Although this optimization attempts to avoid locking for valid tokens, Dictionary<TKey, TValue> is not thread-safe for concurrent reads and writes. Consider using ConcurrentDictionary<TKey, TValue> instead, or performing the initial check inside the lock.

Copilot uses AI. Check for mistakes.
Comment on lines +123 to +127
this.logger?.LogTrace(
"Access token is no longer valid (now: {Now} > dueTime{DueDateTolerance}: {DueTime}), request new one",
now,
tolerance,
dueDate);
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The log message shows {Now} which includes the tolerance adjustment, making it potentially confusing. The logged value will be UtcNow + tolerance, not the actual current time. Consider logging the actual UTC time and separately noting the tolerance, or clarifying in the message that this is the adjusted time for comparison purposes.

Copilot uses AI. Check for mistakes.
ICamundaCloudTokenProviderBuilderFinalStep UsePath(string path);

/// <summary>
/// Disables credentials cache persitence to file system.
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling error: "persitence" should be "persistence"

Suggested change
/// Disables credentials cache persitence to file system.
/// Disables credentials cache persistence to file system.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unable to run on Azure Function - CamundaCloudTokenProvider makes unauthorised writes to local file system

3 participants