/// <summary> /// Updates the refresh token. /// </summary> /// <param name="handle">The handle.</param> /// <param name="refreshToken">The refresh token.</param> /// <param name="client">The client.</param> /// <returns> /// The refresh token handle /// </returns> public virtual async Task <string> UpdateRefreshTokenAsync(string handle, RefreshToken refreshToken, Client client) { _logger.LogDebug("Updating refresh token"); bool needsUpdate = false; if (client.RefreshTokenUsage == TokenUsage.OneTimeOnly) { _logger.LogDebug("Token usage is one-time only. Generating new handle"); // delete old one await _grants.RemoveRefreshTokenAsync(handle); // create new one handle = CryptoRandom.CreateUniqueId(); needsUpdate = true; } if (client.RefreshTokenExpiration == TokenExpiration.Sliding) { _logger.LogDebug("Refresh token expiration is sliding - extending lifetime"); // make sure we don't exceed absolute exp // cap it at absolute exp var currentLifetime = refreshToken.CreationTime.GetLifetimeInSeconds(); _logger.LogDebug("Current lifetime: " + currentLifetime.ToString()); var newLifetime = currentLifetime + client.SlidingRefreshTokenLifetime; _logger.LogDebug("New lifetime: " + newLifetime.ToString()); if (newLifetime > client.AbsoluteRefreshTokenLifetime) { newLifetime = client.AbsoluteRefreshTokenLifetime; _logger.LogDebug("New lifetime exceeds absolute lifetime, capping it to " + newLifetime.ToString()); } refreshToken.Lifetime = newLifetime; needsUpdate = true; } if (needsUpdate) { await _grants.StoreRefreshTokenAsync(handle, refreshToken); _logger.LogDebug("Updated refresh token in store"); } else { _logger.LogDebug("No updates to refresh token done"); } await RaiseRefreshTokenRefreshedEventAsync(handle, handle, refreshToken); _logger.LogDebug("No updates to refresh token done"); return(handle); }
private async Task <TokenRequestValidationResult> ValidateRefreshTokenRequestAsync(NameValueCollection parameters) { _logger.LogDebug("Start validation of refresh token request"); var refreshTokenHandle = parameters.Get(OidcConstants.TokenRequest.RefreshToken); if (refreshTokenHandle.IsMissing()) { var error = "Refresh token is missing"; LogError(error); await RaiseRefreshTokenRefreshFailureEventAsync(null, error); return(Invalid(OidcConstants.TokenErrors.InvalidRequest)); } if (refreshTokenHandle.Length > _options.InputLengthRestrictions.RefreshToken) { var error = "Refresh token too long"; LogError(error); await RaiseRefreshTokenRefreshFailureEventAsync(null, error); return(Invalid(OidcConstants.TokenErrors.InvalidGrant)); } _validatedRequest.RefreshTokenHandle = refreshTokenHandle; ///////////////////////////////////////////// // check if refresh token is valid ///////////////////////////////////////////// var refreshToken = await _grants.GetRefreshTokenAsync(refreshTokenHandle); if (refreshToken == null) { LogError("Refresh token cannot be found in store: {refreshToken}", refreshTokenHandle); var error = "Refresh token cannot be found in store: " + refreshTokenHandle; await RaiseRefreshTokenRefreshFailureEventAsync(refreshTokenHandle, error); return(Invalid(OidcConstants.TokenErrors.InvalidGrant)); } ///////////////////////////////////////////// // check if refresh token has expired ///////////////////////////////////////////// if (refreshToken.CreationTime.HasExceeded(refreshToken.Lifetime)) { var error = "Refresh token has expired"; LogError(error); await RaiseRefreshTokenRefreshFailureEventAsync(refreshTokenHandle, error); await _grants.RemoveRefreshTokenAsync(refreshTokenHandle); return(Invalid(OidcConstants.TokenErrors.InvalidGrant)); } ///////////////////////////////////////////// // check if client belongs to requested refresh token ///////////////////////////////////////////// if (_validatedRequest.Client.ClientId != refreshToken.ClientId) { LogError("{clientId} tries to refresh token belonging to {clientId}", _validatedRequest.Client.ClientId, refreshToken.ClientId); await RaiseRefreshTokenRefreshFailureEventAsync(refreshTokenHandle, "Invalid client binding"); return(Invalid(OidcConstants.TokenErrors.InvalidGrant)); } ///////////////////////////////////////////// // check if client still has offline_access scope ///////////////////////////////////////////// if (!_validatedRequest.Client.AllowAccessToAllScopes) { if (!_validatedRequest.Client.AllowedScopes.Contains(Constants.StandardScopes.OfflineAccess)) { LogError("{clientId} does not have access to offline_access scope anymore", _validatedRequest.Client.ClientId); var error = "Client does not have access to offline_access scope anymore"; await RaiseRefreshTokenRefreshFailureEventAsync(refreshTokenHandle, error); return(Invalid(OidcConstants.TokenErrors.InvalidGrant)); } } _validatedRequest.RefreshToken = refreshToken; ///////////////////////////////////////////// // make sure user is enabled ///////////////////////////////////////////// var subject = _validatedRequest.RefreshToken.Subject; var isActiveCtx = new IsActiveContext(subject, _validatedRequest.Client, IdentityServerConstants.ProfileIsActiveCallers.RefreshTokenValidation); await _profile.IsActiveAsync(isActiveCtx); if (isActiveCtx.IsActive == false) { LogError("{subjectId} has been disabled", _validatedRequest.RefreshToken.SubjectId); var error = "User has been disabled: " + _validatedRequest.RefreshToken.SubjectId; await RaiseRefreshTokenRefreshFailureEventAsync(refreshTokenHandle, error); return(Invalid(OidcConstants.TokenErrors.InvalidGrant)); } _validatedRequest.Subject = subject; _logger.LogDebug("Validation of refresh token request success"); return(Valid()); }