public override async Task <string> UpdateRefreshTokenAsync(RefreshTokenUpdateRequest request) { Logger.LogDebug("Updating refresh token"); var refreshTokenExtra = request.RefreshToken as RefreshTokenExtra; var client = request.Client; var clientExtra = client as ClientExtra; var handle = request.Handle.Substring(2); bool needsCreate = false; bool needsUpdate = request.MustUpdate; if (request.Client.RefreshTokenUsage == TokenUsage.OneTimeOnly) { Logger.LogDebug("Token usage is one-time only. Setting current handle as consumed, and generating new handle"); // flag as consumed if (request.RefreshToken.ConsumedTime == null) { request.RefreshToken.ConsumedTime = Clock.UtcNow.UtcDateTime; } // increment the attempts used refreshTokenExtra.ConsumedAttempts += 1; if (!clientExtra.RefreshTokenGraceEnabled) { await RefreshTokenStore.UpdateRefreshTokenAsync(handle, refreshTokenExtra); } // create new one needsCreate = true; } if (request.Client.RefreshTokenExpiration == TokenExpiration.Sliding) { Logger.LogDebug("Refresh token expiration is sliding - extending lifetime"); // if absolute exp > 0, make sure we don't exceed absolute exp // if absolute exp = 0, allow indefinite slide var currentLifetime = request.RefreshToken.CreationTime.GetLifetimeInSeconds(Clock.UtcNow.UtcDateTime); Logger.LogDebug("Current lifetime: {currentLifetime}", currentLifetime.ToString()); var newLifetime = currentLifetime + request.Client.SlidingRefreshTokenLifetime; Logger.LogDebug("New lifetime: {slidingLifetime}", newLifetime.ToString()); // zero absolute refresh token lifetime represents unbounded absolute lifetime // if absolute lifetime > 0, cap at absolute lifetime if (request.Client.AbsoluteRefreshTokenLifetime > 0 && newLifetime > request.Client.AbsoluteRefreshTokenLifetime) { newLifetime = request.Client.AbsoluteRefreshTokenLifetime; Logger.LogDebug("New lifetime exceeds absolute lifetime, capping it to {newLifetime}", newLifetime.ToString()); } request.RefreshToken.Lifetime = newLifetime; needsUpdate = true; } if (needsCreate) { var oldChild = refreshTokenExtra.RefeshTokenChild; var oldParent = refreshTokenExtra.RefeshTokenParent; var savedConsumedTime = refreshTokenExtra.ConsumedTime; var savedConsumedAttempts = refreshTokenExtra.ConsumedAttempts; // set it to null so that we save non-consumed token refreshTokenExtra.ConsumedTime = null; refreshTokenExtra.ConsumedAttempts = 0; refreshTokenExtra.RefeshTokenChild = null; // carry forward the parent. refreshTokenExtra.RefeshTokenParent = handle; var newHandle = await RefreshTokenStore.StoreRefreshTokenAsync(refreshTokenExtra); refreshTokenExtra.ConsumedTime = savedConsumedTime; refreshTokenExtra.ConsumedAttempts = savedConsumedAttempts; refreshTokenExtra.RefeshTokenParent = null; if (client.RefreshTokenUsage == TokenUsage.OneTimeOnly) { Logger.LogDebug("Token usage is one-time only. Setting current handle as consumed, and generating new handle"); if (clientExtra.RefreshTokenGraceEnabled) { refreshTokenExtra.RefeshTokenChild = newHandle; } await RefreshTokenStore.UpdateRefreshTokenAsync( handle, refreshTokenExtra); if (clientExtra.RefreshTokenGraceEnabled) { if (!string.IsNullOrWhiteSpace(oldChild)) { await RefreshTokenStore.RemoveRefreshTokenAsync(oldChild); } if (!string.IsNullOrWhiteSpace(oldParent)) { await RefreshTokenStore.RemoveRefreshTokenAsync(oldParent); } } } handle = newHandle; Logger.LogDebug("Created refresh token in store"); } else if (needsUpdate) { await RefreshTokenStore.UpdateRefreshTokenAsync(handle, request.RefreshToken); Logger.LogDebug("Updated refresh token in store"); } else { Logger.LogDebug("No updates to refresh token done"); } return(handle); }
/// <inheritdoc/> public Task <string> UpdateRefreshTokenAsync(RefreshTokenUpdateRequest request) { return(Inner.UpdateRefreshTokenAsync(request)); }
/// <summary> /// Updates the refresh token. /// </summary> /// <returns> /// The refresh token handle /// </returns> public virtual async Task <string> UpdateRefreshTokenAsync(RefreshTokenUpdateRequest request) { Logger.LogDebug("Updating refresh token"); var handle = request.Handle; bool needsCreate = false; bool needsUpdate = request.MustUpdate; if (request.Client.RefreshTokenUsage == TokenUsage.OneTimeOnly) { Logger.LogDebug("Token usage is one-time only. Setting current handle as consumed, and generating new handle"); // flag as consumed if (request.RefreshToken.ConsumedTime == null) { request.RefreshToken.ConsumedTime = Clock.UtcNow.UtcDateTime; await RefreshTokenStore.UpdateRefreshTokenAsync(handle, request.RefreshToken); } // create new one needsCreate = true; } if (request.Client.RefreshTokenExpiration == TokenExpiration.Sliding) { Logger.LogDebug("Refresh token expiration is sliding - extending lifetime"); // if absolute exp > 0, make sure we don't exceed absolute exp // if absolute exp = 0, allow indefinite slide var currentLifetime = request.RefreshToken.CreationTime.GetLifetimeInSeconds(Clock.UtcNow.UtcDateTime); Logger.LogDebug("Current lifetime: {currentLifetime}", currentLifetime.ToString()); var newLifetime = currentLifetime + request.Client.SlidingRefreshTokenLifetime; Logger.LogDebug("New lifetime: {slidingLifetime}", newLifetime.ToString()); // zero absolute refresh token lifetime represents unbounded absolute lifetime // if absolute lifetime > 0, cap at absolute lifetime if (request.Client.AbsoluteRefreshTokenLifetime > 0 && newLifetime > request.Client.AbsoluteRefreshTokenLifetime) { newLifetime = request.Client.AbsoluteRefreshTokenLifetime; Logger.LogDebug("New lifetime exceeds absolute lifetime, capping it to {newLifetime}", newLifetime.ToString()); } request.RefreshToken.Lifetime = newLifetime; needsUpdate = true; } if (needsCreate) { // set it to null so that we save non-consumed token request.RefreshToken.ConsumedTime = null; handle = await RefreshTokenStore.StoreRefreshTokenAsync(request.RefreshToken); Logger.LogDebug("Created refresh token in store"); } else if (needsUpdate) { await RefreshTokenStore.UpdateRefreshTokenAsync(handle, request.RefreshToken); Logger.LogDebug("Updated refresh token in store"); } else { Logger.LogDebug("No updates to refresh token done"); } return(handle); }