示例#1
0
    protected virtual async Task <IdentityUser> CreateExternalUserAsync(ExternalLoginInfo info)
    {
        await IdentityOptions.SetAsync();

        var emailAddress = info.Principal.FindFirstValue(AbpClaimTypes.Email);

        var user = new IdentityUser(GuidGenerator.Create(), emailAddress, emailAddress, CurrentTenant.Id);

        CheckIdentityErrors(await UserManager.CreateAsync(user));
        CheckIdentityErrors(await UserManager.SetEmailAsync(user, emailAddress));
        CheckIdentityErrors(await UserManager.AddLoginAsync(user, info));
        CheckIdentityErrors(await UserManager.AddDefaultRolesAsync(user));

        user.Name    = info.Principal.FindFirstValue(AbpClaimTypes.Name);
        user.Surname = info.Principal.FindFirstValue(AbpClaimTypes.SurName);

        var phoneNumber = info.Principal.FindFirstValue(AbpClaimTypes.PhoneNumber);

        if (!phoneNumber.IsNullOrWhiteSpace())
        {
            var phoneNumberConfirmed = string.Equals(info.Principal.FindFirstValue(AbpClaimTypes.PhoneNumberVerified), "true", StringComparison.InvariantCultureIgnoreCase);
            user.SetPhoneNumber(phoneNumber, phoneNumberConfirmed);
        }

        await UserManager.UpdateAsync(user);

        return(user);
    }
示例#2
0
    protected virtual async Task RegisterExternalUserAsync(ExternalLoginInfo externalLoginInfo, string emailAddress)
    {
        await IdentityOptions.SetAsync();

        var user = new IdentityUser(GuidGenerator.Create(), emailAddress, emailAddress, CurrentTenant.Id);

        (await UserManager.CreateAsync(user)).CheckErrors();
        (await UserManager.AddDefaultRolesAsync(user)).CheckErrors();

        var userLoginAlreadyExists = user.Logins.Any(x =>
                                                     x.TenantId == user.TenantId &&
                                                     x.LoginProvider == externalLoginInfo.LoginProvider &&
                                                     x.ProviderKey == externalLoginInfo.ProviderKey);

        if (!userLoginAlreadyExists)
        {
            (await UserManager.AddLoginAsync(user, new UserLoginInfo(
                                                 externalLoginInfo.LoginProvider,
                                                 externalLoginInfo.ProviderKey,
                                                 externalLoginInfo.ProviderDisplayName
                                                 ))).CheckErrors();
        }

        await SignInManager.SignInAsync(user, isPersistent : true);
    }
示例#3
0
        protected override async Task RegisterExternalUserAsync(ExternalLoginInfo externalLoginInfo, string emailAddress)
        {
            await IdentityOptions.SetAsync();

            var user = new Volo.Abp.Identity.IdentityUser(GuidGenerator.Create(), emailAddress, emailAddress, CurrentTenant.Id);

            (await UserManager.CreateAsync(user)).CheckErrors();
            (await UserManager.AddDefaultRolesAsync(user)).CheckErrors();

            var userLoginAlreadyExists = user.Logins.Any(x =>
                                                         x.TenantId == user.TenantId &&
                                                         x.LoginProvider == externalLoginInfo.LoginProvider &&
                                                         x.ProviderKey == externalLoginInfo.ProviderKey);

            if (!userLoginAlreadyExists)
            {
                (await UserManager.AddLoginAsync(user, new UserLoginInfo(
                                                     externalLoginInfo.LoginProvider,
                                                     externalLoginInfo.ProviderKey,
                                                     externalLoginInfo.ProviderDisplayName
                                                     ))).CheckErrors();
            }

            await SendEmailToAskForEmailConfirmationAsync(user);
        }
示例#4
0
        public virtual async Task ResetPasswordAsync(PhoneResetPasswordDto input)
        {
            var securityTokenCacheKey  = SmsSecurityTokenCacheItem.CalculateCacheKey(input.PhoneNumber, "SmsVerifyCode");
            var securityTokenCacheItem = await SecurityTokenCache.GetAsync(securityTokenCacheKey);

            if (securityTokenCacheItem == null)
            {
                throw new UserFriendlyException(L["InvalidSmsVerifyCode"]);
            }
            await IdentityOptions.SetAsync();

            // 传递 isConfirmed 用户必须是已确认过手机号的
            var user = await GetUserByPhoneNumberAsync(input.PhoneNumber, isConfirmed : true);

            // 验证二次认证码
            if (!await UserManager.VerifyTwoFactorTokenAsync(user, TokenOptions.DefaultPhoneProvider, input.Code))
            {
                // 验证码无效
                throw new UserFriendlyException(L["InvalidSmsVerifyCode"]);
            }
            // 生成真正的重置密码Token
            var resetPwdToken = await UserManager.GeneratePasswordResetTokenAsync(user);

            // 重置密码
            (await UserManager.ResetPasswordAsync(user, resetPwdToken, input.NewPassword)).CheckErrors();
            // 移除缓存项
            await SecurityTokenCache.RemoveAsync(securityTokenCacheKey);

            await CurrentUnitOfWork.SaveChangesAsync();
        }
示例#5
0
    public virtual async Task <IActionResult> OnPostAsync(string action)
    {
        await CheckLocalLoginAsync();

        ValidateModel();

        ExternalProviders = await GetExternalProviders();

        EnableLocalLogin = await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin);

        await ReplaceEmailToUsernameOfInputIfNeeds();

        await IdentityOptions.SetAsync();

        var result = await SignInManager.PasswordSignInAsync(
            LoginInput.UserNameOrEmailAddress,
            LoginInput.Password,
            LoginInput.RememberMe,
            true
            );

        await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
        {
            Identity = IdentitySecurityLogIdentityConsts.Identity,
            Action   = result.ToIdentitySecurityLogAction(),
            UserName = LoginInput.UserNameOrEmailAddress
        });

        if (result.RequiresTwoFactor)
        {
            return(await TwoFactorLoginResultAsync());
        }

        if (result.IsLockedOut)
        {
            Alerts.Warning(L["UserLockedOutMessage"]);
            return(Page());
        }

        if (result.IsNotAllowed)
        {
            Alerts.Warning(L["LoginIsNotAllowed"]);
            return(Page());
        }

        if (!result.Succeeded)
        {
            Alerts.Danger(L["InvalidUserNameOrPassword"]);
            return(Page());
        }

        //TODO: Find a way of getting user's id from the logged in user and do not query it again like that!
        var user = await UserManager.FindByNameAsync(LoginInput.UserNameOrEmailAddress) ??
                   await UserManager.FindByEmailAsync(LoginInput.UserNameOrEmailAddress);

        Debug.Assert(user != null, nameof(user) + " != null");

        return(RedirectSafely(ReturnUrl, ReturnUrlHash));
    }
    public async Task <IdentityUser> CreateUserAsync(string userName, string providerName, string plainPassword)
    {
        if (CanObtainUserInfoWithoutPassword)
        {
            return(await CreateUserAsync(userName, providerName));
        }

        await IdentityOptions.SetAsync();

        var externalUser = await GetUserInfoAsync(userName, plainPassword);

        return(await CreateUserAsync(externalUser, userName, providerName));
    }
示例#7
0
        public virtual async Task RegisterAsync(PhoneRegisterDto input)
        {
            await CheckSelfRegistrationAsync();

            await IdentityOptions.SetAsync();

            await CheckNewUserPhoneNumberNotBeUsedAsync(input.PhoneNumber);

            var securityTokenCacheKey  = SmsSecurityTokenCacheItem.CalculateCacheKey(input.PhoneNumber, "SmsVerifyCode");
            var securityTokenCacheItem = await SecurityTokenCache.GetAsync(securityTokenCacheKey);

            if (securityTokenCacheItem == null)
            {
                // 验证码过期
                throw new UserFriendlyException(L["InvalidSmsVerifyCode"]);
            }

            // 验证码是否有效
            if (input.Code.Equals(securityTokenCacheItem.Token) && int.TryParse(input.Code, out int token))
            {
                var securityToken = Encoding.Unicode.GetBytes(securityTokenCacheItem.SecurityToken);
                // 校验totp验证码
                if (TotpService.ValidateCode(securityToken, token, securityTokenCacheKey))
                {
                    var userEmail = input.EmailAddress ?? $"{input.PhoneNumber}@{CurrentTenant.Name ?? "default"}.io";//如果邮件地址不验证,随意写入一个
                    var userName  = input.UserName ?? input.PhoneNumber;
                    var user      = new IdentityUser(GuidGenerator.Create(), userName, userEmail, CurrentTenant.Id)
                    {
                        Name = input.Name ?? input.PhoneNumber
                    };

                    await UserStore.SetPhoneNumberAsync(user, input.PhoneNumber);

                    await UserStore.SetPhoneNumberConfirmedAsync(user, true);

                    (await UserManager.CreateAsync(user, input.Password)).CheckErrors();

                    (await UserManager.AddDefaultRolesAsync(user)).CheckErrors();

                    await SecurityTokenCache.RemoveAsync(securityTokenCacheKey);

                    await CurrentUnitOfWork.SaveChangesAsync();

                    return;
                }
            }
            // 验证码无效
            throw new UserFriendlyException(L["InvalidSmsVerifyCode"]);
        }
示例#8
0
    protected virtual async Task <IdentityUser> CreateExternalUserAsync(ExternalLoginInfo info)
    {
        await IdentityOptions.SetAsync();

        var emailAddress = info.Principal.FindFirstValue(AbpClaimTypes.Email);

        var user = new IdentityUser(GuidGenerator.Create(), emailAddress, emailAddress, CurrentTenant.Id);

        CheckIdentityErrors(await UserManager.CreateAsync(user));
        CheckIdentityErrors(await UserManager.SetEmailAsync(user, emailAddress));
        CheckIdentityErrors(await UserManager.AddLoginAsync(user, info));
        CheckIdentityErrors(await UserManager.AddDefaultRolesAsync(user));

        return(user);
    }
    public async Task UpdateUserAsync(IdentityUser user, string providerName, string plainPassword)
    {
        if (CanObtainUserInfoWithoutPassword)
        {
            await UpdateUserAsync(user, providerName);

            return;
        }

        await IdentityOptions.SetAsync();

        var externalUser = await GetUserInfoAsync(user, plainPassword);

        await UpdateUserAsync(user, externalUser, providerName);
    }
示例#10
0
        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="input">The parameters.</param>
        /// <returns>Task&lt;ClaimsPrincipal&gt;.</returns>
        public async Task <ClaimsPrincipal> SignInAsync(SignInDto input)
        {
            await IdentityOptions.SetAsync();

            var user = await UserManager.FindByNameAsync(input.UserName);

            if (user != null)
            {
                var check = await UserManager.CheckPasswordAsync(user, input.Passowrd);

                if (check)
                {
                    return(await UserClaimsPrincipalFactory.CreateAsync(user));
                }
            }

            throw new UserFriendlyException("用户名或密码错误");
        }
示例#11
0
        public virtual async Task RegisterAsync(WeChatRegisterDto input)
        {
            ThowIfInvalidEmailAddress(input.EmailAddress);

            await CheckSelfRegistrationAsync();

            await IdentityOptions.SetAsync();

            var options = await MiniProgramOptionsFactory.CreateAsync();

            var wehchatOpenId = await WeChatOpenIdFinder.FindAsync(input.Code, options.AppId, options.AppSecret);

            var user = await UserManager.FindByLoginAsync(AbpWeChatMiniProgramConsts.ProviderKey, wehchatOpenId.OpenId);

            if (user != null)
            {
                // 应该要抛出微信号已注册异常,而不是直接返回注册用户数据,否则造成用户信息泄露
                throw new UserFriendlyException(L["DuplicateWeChat"]);
            }
            var userName = input.UserName;

            if (userName.IsNullOrWhiteSpace())
            {
                userName = "******" + wehchatOpenId.OpenId.ToMd5().ToLower();
            }

            var userEmail = input.EmailAddress;//如果邮件地址不验证,随意写入一个

            if (userEmail.IsNullOrWhiteSpace())
            {
                userEmail = $"{userName}@{CurrentTenant.Name ?? "default"}.io";
            }

            user = new IdentityUser(GuidGenerator.Create(), userName, userEmail, CurrentTenant.Id);
            (await UserManager.CreateAsync(user, input.Password)).CheckErrors();

            (await UserManager.AddDefaultRolesAsync(user)).CheckErrors();

            var userLogin = new UserLoginInfo(AbpWeChatMiniProgramConsts.ProviderKey, wehchatOpenId.OpenId, AbpWeChatGlobalConsts.DisplayName);

            (await UserManager.AddLoginAsync(user, userLogin)).CheckErrors();

            await CurrentUnitOfWork.SaveChangesAsync();
        }
示例#12
0
    public virtual async Task <IActionResult> OnGetExternalLoginCallbackAsync(string returnUrl = "", string returnUrlHash = "", string remoteError = null)
    {
        //TODO: Did not implemented Identity Server 4 sample for this method (see ExternalLoginCallback in Quickstart of IDS4 sample)

        /* Also did not implement these:
         * - Logout(string logoutId)
         */

        if (remoteError != null)
        {
            Logger.LogWarning($"External login callback error: {remoteError}");
            return(RedirectToPage("./Login"));
        }

        await IdentityOptions.SetAsync();

        var loginInfo = await SignInManager.GetExternalLoginInfoAsync();

        if (loginInfo == null)
        {
            Logger.LogWarning("External login info is not available");
            return(RedirectToPage("./Login"));
        }

        var result = await SignInManager.ExternalLoginSignInAsync(
            loginInfo.LoginProvider,
            loginInfo.ProviderKey,
            isPersistent : false,
            bypassTwoFactor : true
            );

        if (!result.Succeeded)
        {
            await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
            {
                Identity = IdentitySecurityLogIdentityConsts.IdentityExternal,
                Action   = "Login" + result
            });
        }

        if (result.IsLockedOut)
        {
            Logger.LogWarning($"External login callback error: user is locked out!");
            throw new UserFriendlyException("Cannot proceed because user is locked out!");
        }

        if (result.IsNotAllowed)
        {
            Logger.LogWarning($"External login callback error: user is not allowed!");
            throw new UserFriendlyException("Cannot proceed because user is not allowed!");
        }

        if (result.Succeeded)
        {
            return(RedirectSafely(returnUrl, returnUrlHash));
        }

        //TODO: Handle other cases for result!

        var email = loginInfo.Principal.FindFirstValue(AbpClaimTypes.Email);

        if (email.IsNullOrWhiteSpace())
        {
            return(RedirectToPage("./Register", new {
                IsExternalLogin = true,
                ExternalLoginAuthSchema = loginInfo.LoginProvider,
                ReturnUrl = returnUrl
            }));
        }

        var user = await UserManager.FindByEmailAsync(email);

        if (user == null)
        {
            user = await CreateExternalUserAsync(loginInfo);
        }
        else
        {
            if (await UserManager.FindByLoginAsync(loginInfo.LoginProvider, loginInfo.ProviderKey) == null)
            {
                CheckIdentityErrors(await UserManager.AddLoginAsync(user, loginInfo));
            }
        }

        await SignInManager.SignInAsync(user, false);

        await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
        {
            Identity = IdentitySecurityLogIdentityConsts.IdentityExternal,
            Action   = result.ToIdentitySecurityLogAction(),
            UserName = user.Name
        });

        return(RedirectSafely(returnUrl, returnUrlHash));
    }
示例#13
0
        public override async Task <IActionResult> OnPostAsync(string action)
        {
            var context = await Interaction.GetAuthorizationContextAsync(ReturnUrl);

            if (action == "Cancel")
            {
                if (context == null)
                {
                    return(Redirect("~/"));
                }

                await Interaction.GrantConsentAsync(context, new ConsentResponse()
                {
                    Error = AuthorizationError.AccessDenied
                });

                return(Redirect(ReturnUrl));
            }

            await CheckLocalLoginAsync();

            ValidateModel();

            await IdentityOptions.SetAsync();

            ExternalProviders = await GetExternalProviders();

            EnableLocalLogin = await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin);

            await ReplaceEmailToUsernameOfInputIfNeeds();

            var result = await SignInManager.PasswordSignInAsync(
                LoginInput.UserNameOrEmailAddress,
                LoginInput.Password,
                LoginInput.RememberMe,
                true
                );

            await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
            {
                Identity = IdentitySecurityLogIdentityConsts.Identity,
                Action   = result.ToIdentitySecurityLogAction(),
                UserName = LoginInput.UserNameOrEmailAddress,
                ClientId = context?.Client?.ClientId
            });

            if (result.RequiresTwoFactor)
            {
                return(await TwoFactorLoginResultAsync());
            }

            if (result.IsLockedOut)
            {
                Alerts.Warning(L["UserLockedOutMessage"]);
                return(Page());
            }

            if (result.IsNotAllowed)
            {
                Alerts.Warning(L["LoginIsNotAllowed"]);
                return(Page());
            }

            if (!result.Succeeded)
            {
                Alerts.Danger(L["InvalidUserNameOrPassword"]);
                return(Page());
            }

            //TODO: Find a way of getting user's id from the logged in user and do not query it again like that!
            var user = await UserManager.FindByNameAsync(LoginInput.UserNameOrEmailAddress) ??
                       await UserManager.FindByEmailAsync(LoginInput.UserNameOrEmailAddress);

            Debug.Assert(user != null, nameof(user) + " != null");
            await IdentityServerEvents.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id.ToString(), user.UserName)); //TODO: Use user's name once implemented

            return(RedirectSafely(ReturnUrl, ReturnUrlHash));
        }
示例#14
0
        public virtual async Task <IActionResult> OnGetExternalLoginCallbackAsync(string returnUrl = "", string returnUrlHash = "", string remoteError = null)
        {
            //TODO: Did not implemented Identity Server 4 sample for this method (see ExternalLoginCallback in Quickstart of IDS4 sample)

            /* Also did not implement these:
             * - Logout(string logoutId)
             */

            if (remoteError != null)
            {
                Logger.LogWarning($"External login callback error: {remoteError}");
                return(RedirectToPage("./Login"));
            }

            await IdentityOptions.SetAsync();

            var loginInfo = await SignInManager.GetExternalLoginInfoAsync();

            if (loginInfo == null)
            {
                Logger.LogWarning("External login info is not available");
                return(RedirectToPage("./Login"));
            }

            var result = await SignInManager.ExternalLoginSignInAsync(
                loginInfo.LoginProvider,
                loginInfo.ProviderKey,
                isPersistent : false,
                bypassTwoFactor : true
                );

            if (!result.Succeeded)
            {
                await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
                {
                    Identity = IdentitySecurityLogIdentityConsts.IdentityExternal,
                    Action   = "Login" + result
                });
            }

            if (result.IsLockedOut)
            {
                Logger.LogWarning($"External login callback error: user is locked out!");
                throw new UserFriendlyException("Cannot proceed because user is locked out!");
            }

            if (result.IsNotAllowed)
            {
                Logger.LogWarning($"External login callback error: user is not allowed!");
                throw new UserFriendlyException("Cannot proceed because user is not allowed!");
            }

            if (result.Succeeded)
            {
                return(RedirectSafely(returnUrl, returnUrlHash));
            }

            //TODO: Handle other cases for result!

            // Get the information about the user from the external login provider
            var externalLoginInfo = await SignInManager.GetExternalLoginInfoAsync();

            if (externalLoginInfo == null)
            {
                throw new ApplicationException("Error loading external login information during confirmation.");
            }

            if (!IsEmailRetrievedFromExternalLogin(externalLoginInfo))
            {
                return(RedirectToPage("./Register", new
                {
                    IsExternalLogin = true,
                    ExternalLoginAuthSchema = externalLoginInfo.LoginProvider,
                    ReturnUrl = returnUrl
                }));
            }

            var user = await CreateExternalUserAsync(externalLoginInfo);

            await SignInManager.SignInAsync(user, false);

            await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
            {
                Identity = IdentitySecurityLogIdentityConsts.IdentityExternal,
                Action   = result.ToIdentitySecurityLogAction(),
                UserName = user.Name
            });

            return(RedirectSafely(returnUrl, returnUrlHash));
        }
示例#15
0
        public virtual async Task <IActionResult> OnPostAsync(string action)
        {
            ActionHelper.AddTitle(this, "Login");

            // Clean old noitify data
            ViewData["LoginError"] = null;

            await CheckLocalLoginAsync();

            ValidateModel();

            ExternalProviders = await GetExternalProviders();

            EnableLocalLogin = await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin);

            await ReplaceEmailToUsernameOfInputIfNeeds();

            await IdentityOptions.SetAsync();

            var result = await SignInManager.PasswordSignInAsync(
                LoginInput.UserNameOrEmailAddress,
                LoginInput.Password,
                LoginInput.RememberMe,
                true
                );

            await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
            {
                Identity = IdentitySecurityLogIdentityConsts.Identity,
                Action   = result.ToIdentitySecurityLogAction(),
                UserName = LoginInput.UserNameOrEmailAddress
            });

            if (result.RequiresTwoFactor)
            {
                return(await TwoFactorLoginResultAsync());
            }

            if (result.IsLockedOut)
            {
                ViewData["LoginError"] = L["Please try again after a few minutes"];
                ToastHelper.ToastError(this, L["Please try again after a few minutes"]);
                return(Page());
            }

            if (result.IsNotAllowed)
            {
                ViewData["LoginError"] = L["You are not permitted login right now"];
                ToastHelper.ToastError(this, L["You are not permitted login right now"]);
                return(Page());
            }

            if (!result.Succeeded)
            {
                ViewData["LoginError"] = L["Invalid Username/Email or Password"];
                ToastHelper.ToastError(this, L["Invalid Username/Email or Password"]);
                return(Page());
            }

            //TODO: Find a way of getting user's id from the logged in user and do not query it again like that!
            var user = await UserManager.FindByNameAsync(LoginInput.UserNameOrEmailAddress) ??
                       await UserManager.FindByEmailAsync(LoginInput.UserNameOrEmailAddress);

            Debug.Assert(user != null, nameof(user) + " != null");

            ToastHelper.ToastSuccess(this, L["Login successful"]);

            return(RedirectSafely(ReturnUrl, ReturnUrlHash));
        }