Ejemplo n.º 1
0
        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));
        }
Ejemplo n.º 2
0
        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)));
        }
Ejemplo n.º 3
0
        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)));
        }