Expose refresh token via extension and add CacheOptions.DisableInternalCache#5947
Conversation
There was a problem hiding this comment.
Pull request overview
This PR implements issue #5942 by (1) exposing the refresh token from AuthenticationResult via a public extension method (without adding it to the public AuthenticationResult API surface) and (2) adding CacheOptions.DisableInternalCache / InternalCacheDisabled to allow callers to bypass MSAL’s internal token cache behavior.
Changes:
- Added an internal
AuthenticationResult.RefreshTokenfield, populated during result creation, and exposed viaAuthenticationResultExtensions.GetRefreshToken(). - Introduced
CacheOptions.InternalCacheDisabled+CacheOptions.DisableInternalCache, guarded cache writes, skipped key cache reads, and madeAcquireTokenSilentthrow a dedicated error when the internal cache is disabled. - Updated PublicAPI “Unshipped” files and added unit tests for the new behaviors.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Microsoft.Identity.Test.Unit/CacheTests/InternalCacheOptionsTests.cs | Adds tests for refresh token exposure and disabling internal cache behavior. |
| src/client/Microsoft.Identity.Client/AuthenticationResult.cs | Adds internal RefreshToken property to hold RT from token response. |
| src/client/Microsoft.Identity.Client/Internal/Requests/RequestBase.cs | Populates AuthenticationResult.RefreshToken from the token response. |
| src/client/Microsoft.Identity.Client/Extensibility/AuthenticationResultExtensions.cs | Adds public GetRefreshToken() extension method. |
| src/client/Microsoft.Identity.Client/AppConfig/CacheOptions.cs | Adds InternalCacheDisabled and DisableInternalCache. |
| src/client/Microsoft.Identity.Client/AppConfig/AbstractApplicationBuilder.cs | Validates mutual exclusivity of UseSharedCache vs InternalCacheDisabled. |
| src/client/Microsoft.Identity.Client/Internal/Requests/Silent/CacheSilentStrategy.cs | Throws internal_cache_disabled when AcquireTokenSilent is used with disabled cache. |
| src/client/Microsoft.Identity.Client/Cache/CacheSessionManager.cs | Skips certain cache lookups when internal cache is disabled. |
| src/client/Microsoft.Identity.Client/TokenCache.ITokenCacheInternal.cs | Skips internal cache writes and serialization events when internal cache is disabled. |
| src/client/Microsoft.Identity.Client/MsalError.cs | Adds MsalError.InternalCacheDisabled error code. |
| src/client/Microsoft.Identity.Client/MsalErrorMessage.cs | Adds guidance message for the new error. |
| src/client/Microsoft.Identity.Client/PublicApi/*/PublicAPI.Unshipped.txt | Tracks the newly added public API surface across TFMs. |
gladjohn
left a comment
There was a problem hiding this comment.
can we add an integration test?
There was a problem hiding this comment.
Pull request overview
Implements feature request #5942 by (1) exposing the refresh token via a public extension method without adding it to AuthenticationResult’s public surface, and (2) adding CacheOptions.DisableInternalCache to fully disable MSAL’s internal token cache (reads + writes) and make AcquireTokenSilent fail fast with a descriptive error.
Changes:
- Added
AuthenticationResultExtensions.GetRefreshToken()backed by a new internalAuthenticationResult.RefreshTokenpopulated from token responses. - Introduced
CacheOptions.InternalCacheDisabled/CacheOptions.DisableInternalCacheand enforced behavior across cache read/write paths plusAcquireTokenSilent. - Updated PublicAPI analyzer baselines and added/updated unit + integration tests for the new behavior.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Microsoft.Identity.Test.Unit/CacheTests/InternalCacheOptionsTests.cs | Adds unit tests covering DisableInternalCache behaviors and refresh-token exposure via extension. |
| tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/SilentAuthTests.cs | Adds integration coverage ensuring refresh token can be retrieved while internal cache stays empty. |
| src/client/Microsoft.Identity.Client/TokenCache.ITokenCacheInternal.cs | Skips all internal cache writes when InternalCacheDisabled is enabled. |
| src/client/Microsoft.Identity.Client/Cache/CacheSessionManager.cs | Short-circuits internal cache read operations when internal cache is disabled. |
| src/client/Microsoft.Identity.Client/Internal/Requests/Silent/CacheSilentStrategy.cs | Throws internal_cache_disabled when AcquireTokenSilent is used with internal cache disabled. |
| src/client/Microsoft.Identity.Client/Internal/Requests/RequestBase.cs | Populates internal refresh token on AuthenticationResult from MsalTokenResponse. |
| src/client/Microsoft.Identity.Client/Extensibility/AuthenticationResultExtensions.cs | Adds public extension API to retrieve refresh token. |
| src/client/Microsoft.Identity.Client/AuthenticationResult.cs | Adds internal RefreshToken property (not part of public surface). |
| src/client/Microsoft.Identity.Client/AppConfig/CacheOptions.cs | Adds InternalCacheDisabled + DisableInternalCache factory property. |
| src/client/Microsoft.Identity.Client/AppConfig/AbstractApplicationBuilder.cs | Validates mutual exclusivity of UseSharedCache and InternalCacheDisabled. |
| src/client/Microsoft.Identity.Client/MsalError.cs | Adds MsalError.InternalCacheDisabled constant. |
| src/client/Microsoft.Identity.Client/MsalErrorMessage.cs | Adds descriptive error message guiding callers to BYRT or interactive flows. |
| src/client/Microsoft.Identity.Client/PublicApi/*/PublicAPI.Unshipped.txt | Declares new public API surface across TFMs. |
- Downgrade 'internal cache disabled' log in SaveTokenResponseAsync from Info to Verbose to avoid log noise in high-throughput apps - Remove unused 'using Microsoft.Identity.Test.Common;' from InternalCacheOptionsTests.cs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds support for disabling MSAL’s internal token cache and exposes refresh tokens (for confidential clients) via a public extension method to enable “bring your own cache” scenarios.
Changes:
- Introduces
CacheOptions.InternalCacheDisabled+CacheOptions.DisableInternalCacheand enforces mutual exclusivity withUseSharedCache. - Prevents internal cache reads/writes when disabled and throws a dedicated
MsalError.InternalCacheDisabledforAcquireTokenSilent. - Stores refresh tokens on
AuthenticationResult(internal) and exposes them viaAuthenticationResultExtensions.GetRefreshToken(), plus adds unit/integration tests and PublicAPI entries.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Microsoft.Identity.Test.Unit/CacheTests/InternalCacheOptionsTests.cs | Adds unit tests for refresh token exposure and internal-cache-disabled behavior. |
| tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/SilentAuthTests.cs | Adds integration test validating RT exposure + disabled-cache behavior in OBO. |
| src/client/Microsoft.Identity.Client/TokenCache.ITokenCacheInternal.cs | Skips all cache writes when InternalCacheDisabled is set. |
| src/client/Microsoft.Identity.Client/PublicApi/netstandard2.0/PublicAPI.Unshipped.txt | Declares new public API surface for netstandard2.0. |
| src/client/Microsoft.Identity.Client/PublicApi/net8.0/PublicAPI.Unshipped.txt | Declares new public API surface for net8.0. |
| src/client/Microsoft.Identity.Client/PublicApi/net8.0-ios/PublicAPI.Unshipped.txt | Declares new public API surface for net8.0-ios. |
| src/client/Microsoft.Identity.Client/PublicApi/net8.0-android/PublicAPI.Unshipped.txt | Declares new public API surface for net8.0-android. |
| src/client/Microsoft.Identity.Client/PublicApi/net472/PublicAPI.Unshipped.txt | Declares new public API surface for net472. |
| src/client/Microsoft.Identity.Client/PublicApi/net462/PublicAPI.Unshipped.txt | Declares new public API surface for net462. |
| src/client/Microsoft.Identity.Client/MsalErrorMessage.cs | Adds a dedicated guidance message for internal-cache-disabled silent auth. |
| src/client/Microsoft.Identity.Client/MsalError.cs | Adds MsalError.InternalCacheDisabled constant + documentation. |
| src/client/Microsoft.Identity.Client/Internal/Requests/Silent/CacheSilentStrategy.cs | Throws MsalClientException when silent auth is attempted with cache disabled. |
| src/client/Microsoft.Identity.Client/Internal/Requests/RequestBase.cs | Captures refresh token into AuthenticationResult for confidential clients. |
| src/client/Microsoft.Identity.Client/Extensibility/AuthenticationResultExtensions.cs | New public extension method GetRefreshToken() to expose RT. |
| src/client/Microsoft.Identity.Client/Cache/CacheSessionManager.cs | Skips internal cache reads when InternalCacheDisabled is set. |
| src/client/Microsoft.Identity.Client/AuthenticationResult.cs | Adds internal RefreshToken storage on results. |
| src/client/Microsoft.Identity.Client/AppConfig/CacheOptions.cs | Adds InternalCacheDisabled and static factory DisableInternalCache. |
| src/client/Microsoft.Identity.Client/AppConfig/AbstractApplicationBuilder.cs | Validates InternalCacheDisabled and UseSharedCache are mutually exclusive. |
|
copilot why did you commit this as a change? instead of a comment to the PR? 0e2e204 |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR implements #5942 by exposing refresh tokens via a public extension method and introducing CacheOptions.DisableInternalCache to fully bypass MSAL’s internal token cache in advanced scenarios.
Changes:
- Added an internal
AuthenticationResult.RefreshTokenand a publicAuthenticationResultExtensions.GetRefreshToken()accessor. - Added
CacheOptions.InternalCacheDisabled+CacheOptions.DisableInternalCache, and guarded internal cache reads/writes accordingly. - Added error code/message and tests (unit + integration) validating the new behavior.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Microsoft.Identity.Test.Unit/CacheTests/InternalCacheOptionsTests.cs | Adds unit tests for refresh token exposure and internal cache disabling behavior. |
| tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/SilentAuthTests.cs | Adds integration coverage for RT retrieval when internal cache is disabled. |
| src/client/Microsoft.Identity.Client/TokenCache.ITokenCacheInternal.cs | Skips cache writes entirely when InternalCacheDisabled is enabled. |
| src/client/Microsoft.Identity.Client/PublicApi/netstandard2.0/PublicAPI.Unshipped.txt | Declares new public API surface for netstandard2.0. |
| src/client/Microsoft.Identity.Client/PublicApi/net8.0/PublicAPI.Unshipped.txt | Declares new public API surface for net8.0. |
| src/client/Microsoft.Identity.Client/PublicApi/net8.0-ios/PublicAPI.Unshipped.txt | Declares new public API surface for net8.0-ios. |
| src/client/Microsoft.Identity.Client/PublicApi/net8.0-android/PublicAPI.Unshipped.txt | Declares new public API surface for net8.0-android. |
| src/client/Microsoft.Identity.Client/PublicApi/net472/PublicAPI.Unshipped.txt | Declares new public API surface for net472. |
| src/client/Microsoft.Identity.Client/PublicApi/net462/PublicAPI.Unshipped.txt | Declares new public API surface for net462. |
| src/client/Microsoft.Identity.Client/MsalErrorMessage.cs | Adds error messages for internal cache disabled + mutual exclusivity. |
| src/client/Microsoft.Identity.Client/MsalError.cs | Adds MsalError.InternalCacheDisabled error code and docs. |
| src/client/Microsoft.Identity.Client/Internal/Requests/Silent/CacheSilentStrategy.cs | Throws MsalUiRequiredException early when internal cache is disabled. |
| src/client/Microsoft.Identity.Client/Internal/Requests/RequestBase.cs | Populates AuthenticationResult.RefreshToken for confidential-client flows. |
| src/client/Microsoft.Identity.Client/Extensibility/AuthenticationResultExtensions.cs | Introduces GetRefreshToken() extension method. |
| src/client/Microsoft.Identity.Client/Cache/CacheSessionManager.cs | Skips internal cache reads when disabled and returns null/empty defaults. |
| src/client/Microsoft.Identity.Client/AuthenticationResult.cs | Adds internal RefreshToken property. |
| src/client/Microsoft.Identity.Client/AppConfig/CacheOptions.cs | Adds InternalCacheDisabled and DisableInternalCache factory property. |
| src/client/Microsoft.Identity.Client/AppConfig/AbstractApplicationBuilder.cs | Validates mutual exclusivity of InternalCacheDisabled and UseSharedCache. |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Implements #5942 by exposing refresh tokens (via an extension method) and adding CacheOptions.DisableInternalCache to disable MSAL’s internal token cache reads/writes, with corresponding builder validation and error signaling for unsupported silent flows.
Changes:
- Expose refresh token on
AuthenticationResult(internally) and viaAuthenticationResultExtensions.GetRefreshToken(). - Add
CacheOptions.InternalCacheDisabled+CacheOptions.DisableInternalCacheand enforce behavior across cache reads/writes and silent strategy. - Add/update unit + integration tests and update PublicAPI surface files.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Microsoft.Identity.Test.Unit/CacheTests/InternalCacheOptionsTests.cs | Adds unit tests for refresh token exposure and internal-cache-disabled behavior/validation. |
| tests/Microsoft.Identity.Test.Integration.netcore/HeadlessTests/SilentAuthTests.cs | Adds integration coverage for refresh-token exposure when internal cache is disabled. |
| src/client/Microsoft.Identity.Client/TokenCache.ITokenCacheInternal.cs | Skips all cache writes when internal cache is disabled. |
| src/client/Microsoft.Identity.Client/PublicApi/netstandard2.0/PublicAPI.Unshipped.txt | Records new public API surface for netstandard2.0. |
| src/client/Microsoft.Identity.Client/PublicApi/net8.0/PublicAPI.Unshipped.txt | Records new public API surface for net8.0. |
| src/client/Microsoft.Identity.Client/PublicApi/net8.0-ios/PublicAPI.Unshipped.txt | Records new public API surface for net8.0-ios. |
| src/client/Microsoft.Identity.Client/PublicApi/net8.0-android/PublicAPI.Unshipped.txt | Records new public API surface for net8.0-android. |
| src/client/Microsoft.Identity.Client/PublicApi/net472/PublicAPI.Unshipped.txt | Records new public API surface for net472. |
| src/client/Microsoft.Identity.Client/PublicApi/net462/PublicAPI.Unshipped.txt | Records new public API surface for net462. |
| src/client/Microsoft.Identity.Client/MsalErrorMessage.cs | Adds guidance messages for internal-cache-disabled scenarios and mutual exclusivity. |
| src/client/Microsoft.Identity.Client/MsalError.cs | Adds MsalError.InternalCacheDisabled constant and docs. |
| src/client/Microsoft.Identity.Client/Internal/Requests/Silent/CacheSilentStrategy.cs | Throws a targeted MsalUiRequiredException when internal cache is disabled. |
| src/client/Microsoft.Identity.Client/Internal/Requests/RequestBase.cs | Captures refresh token in AuthenticationResult for confidential clients. |
| src/client/Microsoft.Identity.Client/Extensibility/AuthenticationResultExtensions.cs | Introduces GetRefreshToken() extension method. |
| src/client/Microsoft.Identity.Client/Cache/CacheSessionManager.cs | Skips cache reads when internal cache is disabled. |
| src/client/Microsoft.Identity.Client/AuthenticationResult.cs | Adds internal RefreshToken storage on AuthenticationResult. |
| src/client/Microsoft.Identity.Client/AppConfig/CacheOptions.cs | Adds InternalCacheDisabled option and DisableInternalCache factory property. |
| src/client/Microsoft.Identity.Client/AppConfig/AbstractApplicationBuilder.cs | Validates mutual exclusivity of UseSharedCache and InternalCacheDisabled. |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…s XML doc Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
gladjohn
left a comment
There was a problem hiding this comment.
Approved - Please get a sign off from @neha-bhargava for client-side telemetry before merging this in
…public client Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…_refresh_token_and_add_disableInternalCache
… or response Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…PI append-only ordering Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Summary
Implements #5942
Deliverable 1: Expose refresh token via extension method
string RefreshToken { get; set; }toAuthenticationResultRequestBase.CacheTokenResponseAndCreateAuthenticationResultAsyncAuthenticationResultExtensions.GetRefreshToken()extension method insrc/client/Microsoft.Identity.Client/Extensibility/Deliverable 2:
CacheOptions.DisableInternalCacheOptionsIsInternalCacheDisabledbool property toCacheOptionsDisableInternalCacheOptionsstatic factory property toCacheOptionsSaveTokenResponseAsync) behind!IsInternalCacheDisabledCacheSessionManager.Find*Asyncwhen disabledGetInternalCacheEntryCountForTelemetry()returns 0 instead of readingAccessor.EntryCountwhen disabledAccount.TenantProfilesfrom the freshly received ID token (no accessor reads) when disabledCacheSilentStrategy.ExecuteAsyncwithMsalError.InternalCacheDisabledAbstractApplicationBuilder.WithCacheOptionsCacheRefreshReason.CacheDisabledtelemetry assignment inOnBehalfOfRequest.csAcquireTokenInLongRunningProcessthrowsMsalUiRequiredException(InternalCacheDisabled)when cache is disabled (surfaces root cause instead of confusingOboCacheKeyNotInCacheError)Other changes
MsalError.InternalCacheDisabled = "internal_cache_disabled"error codeMsalErrorMessage.InternalCacheDisabledMessagewith guidance towardAcquireTokenByRefreshTokenPublicAPI.Unshipped.txtfiles updated with new API surfaceinternal static CacheOptions.IsDisabledFor(CacheOptions)helper — centralizes the null-safeIsInternalCacheDisabledcheck used inRequestBase,CacheSessionManager,CacheSilentStrategy, andTokenCacheprotected RequestBase.IsInternalCacheDisabledproperty so request subclasses (OnBehalfOfRequest,ClientCredentialRequest) use a single expression instead of repeating the verbose patternIsInternalCacheDisabledbranches inOnBehalfOfRequestinto one blockCacheOptions.IsInternalCacheDisabledandDisableInternalCacheOptionsXML docs to document all throwing behaviorsTests
InternalCacheOptionsTests.cs: 14 tests covering all acceptance criteria, includingGetRefreshToken()null assertion for client credentials (server never issues RTs forclient_credentialsgrant)HttpTelemetryTests.cs: 3 new tests verifyingCacheRefreshReason.CacheDisabledinx-client-current-telemetryheader (ATFC, OBO, InitiateLongRunningObo)OTelInstrumentationTests.cs: 2 new tests verifyingCacheRefreshReason.CacheDisabledin OTelMsalSuccessmetric tags (ATFC, OBO)