diff --git a/src/Api.Rest/Common/Utilities/OAuthHelper.cs b/src/Api.Rest/Common/Utilities/OAuthHelper.cs
index de8c3277..10a27027 100644
--- a/src/Api.Rest/Common/Utilities/OAuthHelper.cs
+++ b/src/Api.Rest/Common/Utilities/OAuthHelper.cs
@@ -18,6 +18,7 @@ namespace Zeiss.PiWeb.Api.Rest.Common.Utilities
 	using System.IO;
 	using System.Linq;
 	using System.Security.Claims;
+	using System.Threading;
 	using System.Threading.Tasks;
 	using JetBrains.Annotations;
 	using Zeiss.PiWeb.Api.Rest.HttpClient.OAuth;
@@ -225,14 +226,14 @@ private static OAuthTokenCredential TryGetCurrentOAuthToken( string instanceUrl,
 		///     <cref>https://openid.net/specs/openid-connect-discovery-1_0.html#IssuerDiscovery</cref>
 		/// </seealso>
 		/// </summary>
-		private static async Task<OAuthConfiguration> GetOAuthConfigurationAsync( string instanceUrl )
+		private static async Task<OAuthConfiguration> GetOAuthConfigurationAsync( string instanceUrl, CancellationToken cancellationToken = default )
 		{
 			var oauthServiceRest = new OAuthServiceRestClient( new Uri( instanceUrl ) )
 			{
 				UseDefaultWebProxy = true
 			};
 
-			var tokenInformation = await oauthServiceRest.GetOAuthConfiguration().ConfigureAwait( false );
+			var tokenInformation = await oauthServiceRest.GetOAuthConfiguration( cancellationToken ).ConfigureAwait( false );
 
 			if( tokenInformation == null )
 				throw new InvalidOperationException( "Cannot detect OpenID token information from resource URL." );
@@ -256,12 +257,14 @@ private static IOidcAuthenticationFlow ChooseSuitableAuthenticationFlow( OAuthCo
 		/// <param name="refreshToken">Optional refresh token that is used to renew the authentication information.</param>
 		/// <param name="requestCallbackAsync">Optional callback to request the user to interactively authenticate.</param>
 		/// <param name="bypassLocalCache">Defines whether locally cached token information are neither used nor updated.</param>
+		/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to cancel the operation.</param>
 		/// <returns>A new <see cref="OAuthTokenCredential"/> instance, or <c>null</c>, if no token could be retrieved.</returns>
 		public static async Task<OAuthTokenCredential> GetAuthenticationInformationForDatabaseUrlAsync(
 			string databaseUrl,
 			string refreshToken = null,
 			Func<OAuthRequest, Task<OAuthResponse>> requestCallbackAsync = null,
-			bool bypassLocalCache = false )
+			bool bypassLocalCache = false,
+			CancellationToken cancellationToken = default )
 		{
 			var instanceUrl = GetInstanceUrl( databaseUrl );
 
@@ -272,16 +275,15 @@ public static async Task<OAuthTokenCredential> GetAuthenticationInformationForDa
 					return cachedToken;
 			}
 
-			var tokenInformation = await GetOAuthConfigurationAsync( instanceUrl ).ConfigureAwait( false );
+			var tokenInformation = await GetOAuthConfigurationAsync( instanceUrl, cancellationToken ).ConfigureAwait( false );
 
 			var authenticationFlow = ChooseSuitableAuthenticationFlow( tokenInformation );
-			var result = await authenticationFlow.ExecuteAuthenticationFlowAsync( refreshToken, tokenInformation, requestCallbackAsync ).ConfigureAwait( false );
+			var result = await authenticationFlow.ExecuteAuthenticationFlowAsync( refreshToken, tokenInformation, requestCallbackAsync, cancellationToken ).ConfigureAwait( false );
 
 			if( result == null )
 				return null;
 
-			if( !bypassLocalCache )
-				AccessTokenCache.Store( instanceUrl, result );
+			AccessTokenCache.Store( instanceUrl, result );
 
 			return result;
 		}
@@ -317,8 +319,7 @@ public static OAuthTokenCredential GetAuthenticationInformationForDatabaseUrl(
 			if( result == null )
 				return null;
 
-			if( !bypassLocalCache )
-				AccessTokenCache.Store( instanceUrl, result );
+			AccessTokenCache.Store( instanceUrl, result );
 
 			return result;
 		}
diff --git a/src/Api.Rest/HttpClient/OAuth/AuthenticationFlows/AuthorizationCodeFlow.cs b/src/Api.Rest/HttpClient/OAuth/AuthenticationFlows/AuthorizationCodeFlow.cs
index 7509cc89..153025f7 100644
--- a/src/Api.Rest/HttpClient/OAuth/AuthenticationFlows/AuthorizationCodeFlow.cs
+++ b/src/Api.Rest/HttpClient/OAuth/AuthenticationFlows/AuthorizationCodeFlow.cs
@@ -14,6 +14,7 @@ namespace Zeiss.PiWeb.Api.Rest.HttpClient.OAuth.AuthenticationFlows;
 
 using System;
 using System.Linq;
+using System.Threading;
 using System.Threading.Tasks;
 using IdentityModel.Client;
 using Zeiss.PiWeb.Api.Rest.Common.Utilities;
@@ -32,7 +33,8 @@ private static async Task<OAuthTokenCredential> TryGetOAuthTokenFromAuthorizeRes
 		CryptoNumbers cryptoNumbers,
 		AuthorizeResponse response,
 		OAuthConfiguration configuration,
-		DiscoveryDocumentResponse discoveryDocument )
+		DiscoveryDocumentResponse discoveryDocument,
+		CancellationToken cancellationToken = default )
 	{
 		if( response?.Code == null )
 			return null;
@@ -44,11 +46,14 @@ private static async Task<OAuthTokenCredential> TryGetOAuthTokenFromAuthorizeRes
 		var tokenResponse = await tokenClient.RequestAuthorizationCodeTokenAsync(
 			code: response.Code,
 			redirectUri: tokenInformation.RedirectUri,
-			codeVerifier: cryptoNumbers.Verifier ).ConfigureAwait( false );
+			codeVerifier: cryptoNumbers.Verifier,
+			cancellationToken: cancellationToken ).ConfigureAwait( false );
 
 		if( tokenResponse.IsError )
+		{
 			throw new InvalidOperationException(
 				$"Error during request of access token using authorization code: {tokenResponse.Error}. {tokenResponse.ErrorDescription}." );
+		}
 
 		// decode the IdentityToken claims
 		var claims = OAuthHelper.DecodeSecurityToken( tokenResponse.IdentityToken ).Claims.ToArray();
@@ -108,13 +113,13 @@ public OAuthTokenCredential ExecuteAuthenticationFlow( string refreshToken, OAut
 	}
 
 	/// <inheritdoc />
-	public async Task<OAuthTokenCredential> ExecuteAuthenticationFlowAsync( string refreshToken, OAuthConfiguration configuration, Func<OAuthRequest, Task<OAuthResponse>> requestCallbackAsync )
+	public async Task<OAuthTokenCredential> ExecuteAuthenticationFlowAsync( string refreshToken, OAuthConfiguration configuration, Func<OAuthRequest, Task<OAuthResponse>> requestCallbackAsync, CancellationToken cancellationToken )
 	{
 		var discoveryInfo = await GetDiscoveryInfoAsync( configuration.UpstreamTokenInformation ).ConfigureAwait( false );
 		ThrowOnInvalidDiscoveryDocument( discoveryInfo );
 
 		var tokenClient = CreateTokenClient( discoveryInfo.TokenEndpoint, configuration.UpstreamTokenInformation.ClientID );
-		var result = await TryGetOAuthTokenFromRefreshTokenAsync( tokenClient, discoveryInfo.UserInfoEndpoint, refreshToken, configuration ).ConfigureAwait( false );
+		var result = await TryGetOAuthTokenFromRefreshTokenAsync( tokenClient, discoveryInfo.UserInfoEndpoint, refreshToken, configuration, cancellationToken ).ConfigureAwait( false );
 		if( result != null )
 			return result;
 
@@ -130,7 +135,7 @@ public async Task<OAuthTokenCredential> ExecuteAuthenticationFlowAsync( string r
 
 		ThrowOnInvalidAuthorizeResponse( response );
 
-		result = await TryGetOAuthTokenFromAuthorizeResponseAsync( tokenClient, cryptoNumbers, response, configuration, discoveryInfo ).ConfigureAwait( false );
+		result = await TryGetOAuthTokenFromAuthorizeResponseAsync( tokenClient, cryptoNumbers, response, configuration, discoveryInfo, cancellationToken ).ConfigureAwait( false );
 
 		return result;
 	}
diff --git a/src/Api.Rest/HttpClient/OAuth/AuthenticationFlows/HybridFlow.cs b/src/Api.Rest/HttpClient/OAuth/AuthenticationFlows/HybridFlow.cs
index 46b80891..16e78089 100644
--- a/src/Api.Rest/HttpClient/OAuth/AuthenticationFlows/HybridFlow.cs
+++ b/src/Api.Rest/HttpClient/OAuth/AuthenticationFlows/HybridFlow.cs
@@ -15,6 +15,7 @@ namespace Zeiss.PiWeb.Api.Rest.HttpClient.OAuth.AuthenticationFlows;
 
 using System;
 using System.Linq;
+using System.Threading;
 using System.Threading.Tasks;
 using IdentityModel.Client;
 using Zeiss.PiWeb.Api.Rest.Common.Utilities;
@@ -33,7 +34,8 @@ private static async Task<OAuthTokenCredential> TryGetOAuthTokenFromAuthorizeRes
 		CryptoNumbers cryptoNumbers,
 		AuthorizeResponse response,
 		OAuthConfiguration configuration,
-		DiscoveryDocumentResponse discoveryDocument )
+		DiscoveryDocumentResponse discoveryDocument,
+		CancellationToken cancellationToken = default )
 	{
 		if( response == null )
 			return null;
@@ -69,7 +71,8 @@ private static async Task<OAuthTokenCredential> TryGetOAuthTokenFromAuthorizeRes
 		var tokenResponse = await tokenClient.RequestAuthorizationCodeTokenAsync(
 			code: response.Code!,
 			redirectUri: tokenInformation.RedirectUri,
-			codeVerifier: cryptoNumbers.Verifier ).ConfigureAwait( false );
+			codeVerifier: cryptoNumbers.Verifier,
+			cancellationToken: cancellationToken ).ConfigureAwait( false );
 
 		if( tokenResponse.IsError )
 			throw new InvalidOperationException( $"Error during request of access token using authorization code: {tokenResponse.Error}." );
@@ -116,13 +119,13 @@ public OAuthTokenCredential ExecuteAuthenticationFlow( string refreshToken, OAut
 	}
 
 	/// <inheritdoc />
-	public async Task<OAuthTokenCredential> ExecuteAuthenticationFlowAsync( string refreshToken, OAuthConfiguration configuration, Func<OAuthRequest, Task<OAuthResponse>> requestCallbackAsync )
+	public async Task<OAuthTokenCredential> ExecuteAuthenticationFlowAsync( string refreshToken, OAuthConfiguration configuration, Func<OAuthRequest, Task<OAuthResponse>> requestCallbackAsync, CancellationToken cancellationToken )
 	{
 		var discoveryInfo = await GetDiscoveryInfoAsync( configuration.LocalTokenInformation ).ConfigureAwait( false );
 		ThrowOnInvalidDiscoveryDocument( discoveryInfo );
 
 		var tokenClient = CreateTokenClient( discoveryInfo.TokenEndpoint, configuration.LocalTokenInformation.ClientID );
-		var result = await TryGetOAuthTokenFromRefreshTokenAsync( tokenClient, discoveryInfo.UserInfoEndpoint, refreshToken, configuration ).ConfigureAwait( false );
+		var result = await TryGetOAuthTokenFromRefreshTokenAsync( tokenClient, discoveryInfo.UserInfoEndpoint, refreshToken, configuration, cancellationToken ).ConfigureAwait( false );
 		if( result != null )
 			return result;
 
@@ -138,7 +141,7 @@ public async Task<OAuthTokenCredential> ExecuteAuthenticationFlowAsync( string r
 
 		ThrowOnInvalidAuthorizeResponse( response );
 
-		result = await TryGetOAuthTokenFromAuthorizeResponseAsync( tokenClient, cryptoNumbers, response, configuration, discoveryInfo ).ConfigureAwait( false );
+		result = await TryGetOAuthTokenFromAuthorizeResponseAsync( tokenClient, cryptoNumbers, response, configuration, discoveryInfo, cancellationToken ).ConfigureAwait( false );
 
 		return result;
 	}
diff --git a/src/Api.Rest/HttpClient/OAuth/AuthenticationFlows/IOidcAuthenticationFlow.cs b/src/Api.Rest/HttpClient/OAuth/AuthenticationFlows/IOidcAuthenticationFlow.cs
index f4350b17..65b7c533 100644
--- a/src/Api.Rest/HttpClient/OAuth/AuthenticationFlows/IOidcAuthenticationFlow.cs
+++ b/src/Api.Rest/HttpClient/OAuth/AuthenticationFlows/IOidcAuthenticationFlow.cs
@@ -13,6 +13,7 @@ namespace Zeiss.PiWeb.Api.Rest.HttpClient.OAuth.AuthenticationFlows;
 #region usings
 
 using System;
+using System.Threading;
 using System.Threading.Tasks;
 using JetBrains.Annotations;
 using Zeiss.PiWeb.Api.Rest.Common.Utilities;
@@ -42,9 +43,11 @@ OAuthTokenCredential ExecuteAuthenticationFlow( [CanBeNull] string refreshToken,
 	/// <param name="refreshToken">Refresh token to acquire a new authentication token.</param>
 	/// <param name="configuration">OAuth configuration containing the settings for authentication.</param>
 	/// <param name="requestCallbackAsync">The asynchronous callback to execute for authentication, e.g opening a browser window.</param>
+	/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to cancel the operation.</param>
 	Task<OAuthTokenCredential> ExecuteAuthenticationFlowAsync( [CanBeNull] string refreshToken,
 		OAuthConfiguration configuration,
-		Func<OAuthRequest, Task<OAuthResponse>> requestCallbackAsync );
+		Func<OAuthRequest, Task<OAuthResponse>> requestCallbackAsync,
+		CancellationToken cancellationToken );
 
 	#endregion
 }
\ No newline at end of file
diff --git a/src/Api.Rest/HttpClient/OAuth/AuthenticationFlows/OidcAuthenticationFlowBase.cs b/src/Api.Rest/HttpClient/OAuth/AuthenticationFlows/OidcAuthenticationFlowBase.cs
index 664d14da..5afc03a0 100644
--- a/src/Api.Rest/HttpClient/OAuth/AuthenticationFlows/OidcAuthenticationFlowBase.cs
+++ b/src/Api.Rest/HttpClient/OAuth/AuthenticationFlows/OidcAuthenticationFlowBase.cs
@@ -15,6 +15,7 @@ namespace Zeiss.PiWeb.Api.Rest.HttpClient.OAuth.AuthenticationFlows;
 using System;
 using System.Linq;
 using System.Net.Http;
+using System.Threading;
 using System.Threading.Tasks;
 using IdentityModel;
 using IdentityModel.Client;
@@ -73,14 +74,14 @@ protected static string ChooseAccessToken( TokenResponse tokenResponse, OAuthCon
 	/// <param name="tokenInformation">Token information containing the discovery location and other settings.</param>
 	protected static async Task<DiscoveryDocumentResponse> GetDiscoveryInfoAsync( OAuthTokenInformation tokenInformation )
 	{
-		var discoveryCache = new DiscoveryCache( tokenInformation.OpenIdAuthority,
-			new DiscoveryPolicy
-			{
-				AdditionalEndpointBaseAddresses = tokenInformation.AdditionalEndpointBaseAddresses
-			} );
+		var discoveryPolicy = new DiscoveryPolicy
+		{
+			AdditionalEndpointBaseAddresses = tokenInformation.AdditionalEndpointBaseAddresses
+		};
+
+		var discoveryCache = new DiscoveryCache( tokenInformation.OpenIdAuthority, discoveryPolicy );
 
-		var discoveryInfo = await discoveryCache.GetAsync().ConfigureAwait( false );
-		return discoveryInfo;
+		return await discoveryCache.GetAsync().ConfigureAwait( false );
 	}
 
 	/// <summary>
@@ -128,13 +129,13 @@ protected static string CreateOAuthStartUrl( string authorizeEndpoint, string re
 	/// <param name="refreshToken">Refresh token to acquire a new authentication token.</param>
 	/// <param name="configuration">OAuth configuration of the PiWeb Server.</param>
 	/// <returns>A valid <see cref="OAuthTokenCredential"/> or <see langword="null"/> if no token could be retrieved.</returns>
-	protected static async Task<OAuthTokenCredential> TryGetOAuthTokenFromRefreshTokenAsync( TokenClient tokenClient, string userInfoEndpoint, string refreshToken, OAuthConfiguration configuration )
+	protected static async Task<OAuthTokenCredential> TryGetOAuthTokenFromRefreshTokenAsync( TokenClient tokenClient, string userInfoEndpoint, string refreshToken, OAuthConfiguration configuration, CancellationToken cancellationToken = default )
 	{
 		// when a refresh token is present try to use it to acquire a new access token
 		if( string.IsNullOrEmpty( refreshToken ) )
 			return null;
 
-		var tokenResponse = await tokenClient.RequestRefreshTokenAsync( refreshToken ).ConfigureAwait( false );
+		var tokenResponse = await tokenClient.RequestRefreshTokenAsync( refreshToken, cancellationToken: cancellationToken ).ConfigureAwait( false );
 		if( tokenResponse.IsError )
 			return null;