public async Task Updates_with_refresh_token() { // setup var auth0serverUrl = "https://localhost"; var apiClient = new Mock <IAuthenticationApiClient>(MockBehavior.Strict); RefreshTokenDelegationRequestDto delegationRequest = null; apiClient.Setup(ac => ac.GetDelegationTokenAsync(It.IsAny <RefreshTokenDelegationRequestDto>(), auth0serverUrl)) .Callback((DelegationRequestBaseDto token, string server) => delegationRequest = token as RefreshTokenDelegationRequestDto) .Returns(Task.FromResult(new AccessToken { IdToken = Guid.NewGuid().ToString() })); var tokenProvider = new Auth0TokenProvider(loggerFactor.Object, new Auth0ClientSettings { Auth0ServerUrl = auth0serverUrl }, apiClient.Object, autoScheduler.Object); var auth0ClientSettings = new Auth0ClientSettings { Auth0ClientId = Guid.NewGuid().ToString(), Auth0RefreshToken = Guid.NewGuid().ToString() }; // execute await tokenProvider.AddOrUpdateClientAsync(auth0ClientSettings); // validate apiClient.Verify(ac => ac.GetDelegationTokenAsync(It.IsAny <DelegationRequestBaseDto>(), auth0serverUrl), Times.Once); Assert.NotNull(delegationRequest); delegationRequest.RefreshToken.Should().Be(auth0ClientSettings.Auth0RefreshToken); delegationRequest.SourceClientId.Should().Be(auth0ClientSettings.Auth0ClientId); delegationRequest.TargetClientId.Should().Be(auth0ClientSettings.Auth0ClientId); }
/// <summary> /// Updates the authentication header using the refresh token asynchronous. /// </summary> /// <param name="clientId">The client identifier.</param> /// <param name="forceRefresh">if set to <c>true</c> [force refresh].</param> /// <exception cref="System.Collections.Generic.KeyNotFoundException"></exception> private async Task UpdateAuthHeaderWithRefreshTokenAsync(string clientId, bool forceRefresh = false) { if (await syncObject.WaitAsync(5000)) { try { if (!clientTokenCache.ContainsKey(clientId)) { throw new KeyNotFoundException($"Cannot update the auth token for client {clientId}, because of missing information."); } // Only update if really needed. // Especially when multiple tasks are invoked at the same time we only need to update once. // Testing for a valid token happens within GetAuthHeaderForClient but outside of the locked section. // Therefore it might happen that the token was already updated once entering the locked section. if (clientTokenCache[clientId].LastRefresh > DateTimeOffset.Now.AddSeconds(-5) && !forceRefresh) { return; } var refreshRequest = new RefreshTokenDelegationRequestDto(clientId, clientId, clientTokenCache[clientId].Auth0RefreshToken); // authenticate with auth0 var authToken = await authenticationApiClient.GetDelegationTokenAsync(refreshRequest, clientTokenCache[clientId].Auth0ServerUrl); // set the authorization header clientTokenCache[clientId].Auth0HeaderValue = new AuthenticationHeaderValue("Bearer", authToken.IdToken); clientTokenCache[clientId].LastRefresh = DateTimeOffset.Now; logger.LogInformation($"Successfully authenticated with the service client id {clientId} with refresh token."); ScheduleAutoRefresh(clientTokenCache[clientId]); } catch (Exception ex) { // any exceptions during authentication are logged here logger.LogError($"Error authenticating with service: {clientId} using refresh token {clientTokenCache[clientId].Auth0RefreshToken}.", ex); } finally { syncObject.Release(); } } else { logger.LogWarning("Auth0TokenProvider could not get lock for retrieving an authentication token."); } }