Exemple #1
0
        /// <inheritdoc/>
        public ITotpPurposeBuilder UsingDeliveryChannel(TotpDeliveryChannel deliveryChannel, string subject = null)
        {
            _totpMessageBuilder.DeliveryChannel = deliveryChannel;
            _totpMessageBuilder.Subject         = subject;
            var totpPurposeBuilder = new TotpPurposeBuilder(_totpMessageBuilder);

            return(totpPurposeBuilder);
        }
Exemple #2
0
        /// <inheritdoc />
        public async Task <TotpResult> Send(ClaimsPrincipal principal, string message, TotpDeliveryChannel channel = TotpDeliveryChannel.Sms, string purpose = null, string securityToken = null, string phoneNumberOrEmail = null)
        {
            var totpResult = ValidateParameters(principal, securityToken, phoneNumberOrEmail);

            if (!totpResult.Success)
            {
                return(totpResult);
            }
            User user         = null;
            var  hasPrincipal = principal != null;

            if (hasPrincipal)
            {
                user = await UserManager.GetUserAsync(principal);

                if (user?.PhoneNumberConfirmed == false || string.IsNullOrEmpty(user?.PhoneNumber))
                {
                    return(TotpResult.ErrorResult(Localizer["Cannot send SMS. User's phone number is not verified."]));
                }
            }
            purpose ??= TotpConstants.TokenGenerationPurpose.StrongCustomerAuthentication;
            var token            = string.Empty;
            var hasSecurityToken = !string.IsNullOrEmpty(securityToken);

            if (hasSecurityToken)
            {
                var modifier     = GetModifier(purpose, phoneNumberOrEmail);
                var encodedToken = Encoding.Unicode.GetBytes(securityToken);
                token = Rfc6238AuthenticationService.GenerateCode(encodedToken, modifier).ToString("D6", CultureInfo.InvariantCulture);
            }
            if (hasPrincipal)
            {
                token = await UserManager.GenerateUserTokenAsync(user, TokenOptions.DefaultPhoneProvider, purpose);
            }
            var userName = user?.UserName ?? "Anonymous";
            var cacheKey = $"totp{(hasPrincipal ? $":{user.Id}" : string.Empty)}:{channel}:{token}:{purpose}";

            if (await CacheKeyExists(cacheKey))
            {
                Logger.LogInformation($"User: '******' - Last token has not expired yet. Throttling.");
                return(TotpResult.ErrorResult(Localizer["Last token has not expired yet. Please wait a few seconds and try again."]));
            }
            Logger.LogInformation($"User: '******' - Token generated successfully.");
            switch (channel)
            {
            case TotpDeliveryChannel.Sms:
                await SmsService.SendAsync(user?.PhoneNumber ?? phoneNumberOrEmail, Localizer["OTP"], Localizer[message, token]);

                break;

            case TotpDeliveryChannel.Email:
            case TotpDeliveryChannel.Viber:
            case TotpDeliveryChannel.Telephone:
            case TotpDeliveryChannel.EToken:
                throw new NotSupportedException($"EToken delivery channel {channel} is not implemented.");

            default:
                break;
            }
            await AddCacheKey(cacheKey);

            return(TotpResult.SuccessResult);
        }
        /// <inheritdoc />
        public async Task <TotpResult> Send(ClaimsPrincipal principal, string message, TotpDeliveryChannel channel = TotpDeliveryChannel.Sms, string purpose = null, string securityToken = null, string phoneNumberOrEmail = null)
        {
            var userId = principal.GetSubjectId();

            if (!string.IsNullOrEmpty(userId))
            {
                var hasDeveloperTotp = await _dbContext.UserClaims.Where(x => x.UserId == userId && x.ClaimType == BasicClaimTypes.DeveloperTotp).AnyAsync();

                if (hasDeveloperTotp)
                {
                    return(TotpResult.SuccessResult);
                }
            }
            return(await _totpService.Send(principal, message, channel, purpose, securityToken, phoneNumberOrEmail));
        }
Exemple #4
0
 /// <summary>
 /// Sends a new code via the selected channel for the given user id.
 /// </summary>
 /// <param name="service">The service to use.</param>
 /// <param name="userId">The user id.</param>
 /// <param name="message">The message to be sent in the SMS. It's important for the message to contain the {0} placeholder in the position where the OTP should be placed.</param>
 /// <param name="channel">Delivery channel.</param>
 /// <param name="reason">Optionaly pass the reason to generate the TOTP.</param>
 /// <exception cref="TotpServiceException">used to pass errors between service and the caller.</exception>
 public static Task <TotpResult> Send(this ITotpService service, string userId, string message, TotpDeliveryChannel channel = TotpDeliveryChannel.Sms, string reason = null) =>
 service.Send(new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(BasicClaimTypes.Subject, userId) })), message, channel, reason);
Exemple #5
0
 public Task <TotpResult> Send(ClaimsPrincipal principal, string message, TotpDeliveryChannel channel = TotpDeliveryChannel.Sms, string purpose = null, string securityToken = null, string phoneNumberOrEmail = null, string data = null, string classification = null, string subject = null) =>
 Task.FromResult(TotpResult.SuccessResult);
Exemple #6
0
        /// <inheritdoc />
        public async Task <TotpResult> Send(ClaimsPrincipal principal, string message, TotpDeliveryChannel channel = TotpDeliveryChannel.Sms, string purpose = null, string securityToken = null, string phoneNumberOrEmail = null, string data = null, string classification = null, string subject = null)
        {
            var totpResult = ValidateParameters(principal, securityToken, phoneNumberOrEmail);

            if (!totpResult.Success)
            {
                return(totpResult);
            }
            User user         = null;
            var  hasPrincipal = principal != null;

            if (hasPrincipal)
            {
                user = await _userManager.GetUserAsync(principal);

                if (user?.PhoneNumberConfirmed == false || string.IsNullOrEmpty(user?.PhoneNumber))
                {
                    return(TotpResult.ErrorResult(_localizer["Cannot send SMS. User's phone number is not verified."]));
                }
            }
            purpose ??= TotpConstants.TokenGenerationPurpose.StrongCustomerAuthentication;
            var token            = string.Empty;
            var hasSecurityToken = !string.IsNullOrEmpty(securityToken);

            if (hasSecurityToken)
            {
                var modifier     = GetModifier(purpose, phoneNumberOrEmail);
                var encodedToken = Encoding.Unicode.GetBytes(securityToken);
                token = _rfc6238AuthenticationService.GenerateCode(encodedToken, modifier).ToString("D6", CultureInfo.InvariantCulture);
            }
            if (hasPrincipal)
            {
                token = await _userManager.GenerateUserTokenAsync(user, TokenOptions.DefaultPhoneProvider, purpose);
            }
            var userName = user?.UserName ?? "Anonymous";
            var cacheKey = $"totp{(hasPrincipal ? $":{user.Id}" : string.Empty)}:{channel}:{token}:{purpose}";

            if (await CacheKeyExists(cacheKey))
            {
                _logger.LogInformation("User: '******' - Last token has not expired yet. Throttling", userName);
                return(TotpResult.ErrorResult(_localizer["Last token has not expired yet. Please wait a few seconds and try again."]));
            }
            _logger.LogInformation("User: '******' - Token generated successfully", userName);
            switch (channel)
            {
            case TotpDeliveryChannel.Sms:
            case TotpDeliveryChannel.Viber:
                var smsService = _smsServiceFactory.Create(channel.ToString());
                await smsService.SendAsync(user?.PhoneNumber ?? phoneNumberOrEmail, _localizer[subject ?? "OTP"], _localizer[message, token]);

                break;

            case TotpDeliveryChannel.Email:
            case TotpDeliveryChannel.Telephone:
            case TotpDeliveryChannel.EToken:
                throw new NotSupportedException($"Delivery channel '{channel}' is not supported.");

            case TotpDeliveryChannel.PushNotification:
                if (_pushNotificationService == null)
                {
                    throw new ArgumentNullException(nameof(_pushNotificationService), $"Cannot send push notification since there is no implementation of {nameof(IPushNotificationService)}.");
                }
                await _pushNotificationService.SendAsync(builder =>
                                                         builder.To(user?.Id)
                                                         .WithToken(token)
                                                         .WithTitle(string.Format(message, token))
                                                         .WithData(data)
                                                         .WithClassification(classification));

                break;

            default:
                break;
            }
            await AddCacheKey(cacheKey);

            return(TotpResult.SuccessResult);
        }