public async Task <Response <CheckOneTimeCodeResult, CheckOneTimeCodeStatus> > CheckOneTimeCodeAsync(string longCode, string clientNonce) { _logger.LogTrace("Checking long code"); if (string.IsNullOrEmpty(longCode) || longCode.Length > PasswordlessLoginConstants.OneTimeCode.LongCodeMaxLength) { _logger.LogError("The long code provided had an invalid format."); return(new Response <CheckOneTimeCodeResult, CheckOneTimeCodeStatus>( CheckOneTimeCodeStatus.Error(_localizer["The one time code had an invalid format."], CheckOneTimeCodeStatusCode.CodeIncorrect))); } var response = await _oneTimeCodeStore.GetOneTimeCodeByLongCodeAsync(longCode); if (response.HasError) { return(new Response <CheckOneTimeCodeResult, CheckOneTimeCodeStatus>( CheckOneTimeCodeStatus.Error(_localizer["One time code not found."], CheckOneTimeCodeStatusCode.NotFound))); } var otc = response.Result; if (otc.ExpiresUTC < DateTime.UtcNow) { _logger.LogDebug("The one time code has expired."); return(new Response <CheckOneTimeCodeResult, CheckOneTimeCodeStatus>( new CheckOneTimeCodeResult(otc), CheckOneTimeCodeStatus.Error(_localizer["The one time code has expired."], CheckOneTimeCodeStatusCode.Expired))); } return(await ExpireTokenAndValidateNonceAsync(otc, clientNonce)); }
public async Task <Response <CheckOneTimeCodeResult, CheckOneTimeCodeStatus> > CheckOneTimeCodeAsync(string sentTo, string shortCode, string clientNonce) { _logger.LogTrace("Checking short code"); var response = await _oneTimeCodeStore.GetOneTimeCodeAsync(sentTo); if (response.HasError) { return(new Response <CheckOneTimeCodeResult, CheckOneTimeCodeStatus>( CheckOneTimeCodeStatus.Error(_localizer["One time code not found."], CheckOneTimeCodeStatusCode.NotFound))); } var otc = response.Result; if (otc.ExpiresUTC < DateTime.UtcNow) { _logger.LogDebug("The one time code has expired."); return(new Response <CheckOneTimeCodeResult, CheckOneTimeCodeStatus>( CheckOneTimeCodeStatus.Error(_localizer["The one time code has expired."], CheckOneTimeCodeStatusCode.Expired))); } if (!string.IsNullOrEmpty(shortCode) && shortCode.Length == PasswordlessLoginConstants.OneTimeCode.ShortCodeLength) { if (otc.FailedAttemptCount >= PasswordlessLoginConstants.OneTimeCode.MaxFailedAttemptCount) { // maximum of 3 attempts during code validity period to prevent guessing attacks // long code remains valid, preventing account lockout attacks (and giving a fumbling but valid user another way in) _logger.LogDebug("The one time code is locked (too many failed attempts to use it)."); return(new Response <CheckOneTimeCodeResult, CheckOneTimeCodeStatus>( CheckOneTimeCodeStatus.Error(_localizer["The one time code is locked."], CheckOneTimeCodeStatusCode.ShortCodeLocked))); } if (shortCode == otc.ShortCode) { _logger.LogDebug("The one time code matches"); return(await ExpireTokenAndValidateNonceAsync(otc, clientNonce)); } } else { _logger.LogDebug("The one time code was missing or was the wrong length"); } _logger.LogDebug("Updating failure count for one time code"); await _oneTimeCodeStore.UpdateOneTimeCodeFailureAsync(sentTo, otc.FailedAttemptCount + 1); return(new Response <CheckOneTimeCodeResult, CheckOneTimeCodeStatus>( CheckOneTimeCodeStatus.Error(_localizer["The one time code was not correct."], CheckOneTimeCodeStatusCode.CodeIncorrect))); }
private async Task <Response <CheckOneTimeCodeResult, CheckOneTimeCodeStatus> > ExpireTokenAndValidateNonceAsync(OneTimeCode otc, string clientNonce) { _logger.LogTrace("Validating nonce"); _logger.LogDebug("Expiring the token so it cannot be used again and so a new token can be generated"); await _oneTimeCodeStore.ExpireOneTimeCodeAsync(otc.SentTo); if (FastHashService.ValidateHash(otc.ClientNonceHash, clientNonce, otc.SentTo)) { _logger.LogDebug("Client nonce was valid"); return(new Response <CheckOneTimeCodeResult, CheckOneTimeCodeStatus>( new CheckOneTimeCodeResult(otc), CheckOneTimeCodeStatus.Success(_localizer["The one time code was verified."], CheckOneTimeCodeStatusCode.VerifiedWithNonce))); } _logger.LogDebug("Client nonce was missing or invalid"); return(new Response <CheckOneTimeCodeResult, CheckOneTimeCodeStatus>( new CheckOneTimeCodeResult(otc), CheckOneTimeCodeStatus.Success(_localizer["The one time code was verified."], CheckOneTimeCodeStatusCode.VerifiedWithoutNonce))); }