Как авторизовать пользователя после подтверждения адреса электронной почты? - PullRequest
0 голосов

Я пишу API для приложения Задача состоит в том, чтобы перенаправить на страницу профиля на клиенте после подтверждения электронной почты.Пока электронная почта не подтверждена, я не могу дать токен доступа к api.На данный момент на клиенте живет костыль: имя пользователя и пароль временно хранятся локально, так что после того, как клиент может сделать скрытый вход. (Что небезопасно)

Как решить эту проблему?

У меня есть одна не очень приятная идея: после регистрации дайте токен доступа и после каждого запроса на проверку - emailConfirmed (bool) Но - каждый раз выполняйте дополнительный запрос ...

Пример небольшого кодасо спины:

ApplicationOAuthProvider:

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {
            var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();

            ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
            var a = await userManager.FindByIdAsync(context.ClientId);

            if (user == null)
            {
                context.SetError("invalid_grant", "Username or Password is incorrect.");
                return;
            }

            if (!user.EmailConfirmed)
            {
                context.SetError("invalid_grant", "Email not confirmed.");
                return;
            }

            ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
               OAuthDefaults.AuthenticationType);
            ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager,
                CookieAuthenticationDefaults.AuthenticationType);

            AuthenticationProperties properties = CreateProperties(user.UserName);
            AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
            context.Validated(ticket);
            context.Request.Context.Authentication.SignIn(cookiesIdentity);
        }

Отправьте код на электронную почту:

[AllowAnonymous]
        [HttpPost]
        [Route("Users/{userId}/emailConfirmation")]
        public async Task<IHttpActionResult> SendConfirmationCode(string userId)
        {
            if (userId == null)
            {
                return BadRequest("UserId were not transferred");
            }

            var user = await UserManager.FindByIdAsync(userId);
            if (user == null)
            {
                return Content(HttpStatusCode.NotFound, "User not found");
            }
            var code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
            var url = $"{clientBaseUrl}confirm_email?userId={user.Id}&code={WebUtility.UrlEncode(code)}";
            await MailHelper.SendConfirmationLinkOnEmail(url, user.Email);

            return Content(HttpStatusCode.OK, new { Message = "Confirmation code was sent on email" });
        }

Подтверждение по электронной почте с помощью кода:

[AllowAnonymous]
        [HttpPost]
        [Route("Users/{userId}/emailConfirmationCode")]
        public async Task<IHttpActionResult> ConfirmEmail(string userId, [FromBody]EmailConfirmationDTO input)
        {
            if (userId == null || input == null)
            {
                return BadRequest("UserId or code were not transferred");
            }

            try
            {
                var isConfirmed = await UserManager.IsEmailConfirmedAsync(userId);
                if (isConfirmed)
                {
                    return Content(HttpStatusCode.Forbidden, new { Message = "This user already confirmed email" });
                }

                var result = await UserManager.ConfirmEmailAsync(userId, input.Code);
                if (result.Succeeded)
                {
                    var user = Db.Users.FirstOrDefaultAsync(u => u.Id == userId);
                    return Content(HttpStatusCode.OK, new { responseObj = user });
                }
            }
            catch (Exception e)
            {
                // ignored
            }

            return Content(HttpStatusCode.InternalServerError, new { Message = "Error confirmation." });
        }

ConfigureAuth:

OAuthOptions = new OAuthAuthorizationServerOptions
            {
                TokenEndpointPath = new PathString("/Token"),
                Provider = new ApplicationOAuthProvider(PublicClientId),
                AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(5),
#if (!DEBUG)
                AllowInsecureHttp = false
#else
                AllowInsecureHttp = true
#endif
            };
...