UseOAuthBearerAuthentication - сохранение состояния между запросами с одним и тем же токеном. - PullRequest
0 голосов
/ 27 марта 2020

Я настроил Овина UseOAuthBearerAuthentication, чтобы пользователи указывали имя пользователя и пароль и получали токен доступа. После проверки подлинности им необходимо подтвердить себя с помощью 2FA следующим образом:

[Authorize]
[HttpPost]
[Route("tfa/verify")]
public IHttpActionResult VerifyTOTPCode(sds_TOTPCode code) {
    using (var session = MiConnectionHelper.CreateSession())
    {
        Guid loggedOnUserOid = ((ClaimsIdentity) User.Identity).GetUserOid();
        MiUser user = MiBusinessObjectHelper.Instance.GetTop1<MiUser>(new BinaryOperator(nameof(MiUser.Oid), loggedOnUserOid), 
            MiBusinessObjectHelper.Instance.GetDefaultSorting(), 
            session);

        var tfa = new TwoFactorAuth("Test");
        if (tfa.VerifyCode(user.Description, code.Code))
        {
            // TFA not verified yet
            if (!user.IsTFAVerified)
            {
                user.IsTFAVerified = true;
                session.CommitChanges();
            }
            HttpContext.Current.Session["TFAAuthenticated"] = true;

            return Ok();
        }

        return StatusCode(HttpStatusCode.Forbidden);
    }
}

Как видите, я устанавливаю HttpContext.Current.Session["TFAAuthenticated"] = true;, чтобы сохранить, если пользователь также был проверен с использованием 2FA.

Кроме того, у меня есть следующее промежуточное ПО:

namespace MiRestAPI.Middleware
{
    public class TwoFactorAuthMiddleware: OwinMiddleware
    {
        public TwoFactorAuthMiddleware(OwinMiddleware next) : base(next)
        {
        }

        public override Task Invoke(IOwinContext context)
        {
            // TODO: Check type of authentication (Windows Authentication should have TFA disabled)
            if (context.Request.User.Identity.IsAuthenticated && !context.Request.Path.Value.Contains("/auth/tfa/"))
            {
                using (var session = MiConnectionHelper.CreateSession())
                {
                    Guid loggedOnUserOid = ((ClaimsIdentity) context.Request.User.Identity).GetUserOid();
                    MiUser user = MiBusinessObjectHelper.Instance.GetTop1<MiUser>(new BinaryOperator(nameof(MiUser.Oid), loggedOnUserOid), 
                        MiBusinessObjectHelper.Instance.GetDefaultSorting(), 
                        session);

                    var httpContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);
                    bool tfaAuthenticated = httpContext.Session["TFAAuthenticated"] as bool? ?? false;

                    if (user != null && user.Is2FAEnabled && (!user.IsTFAVerified || !tfaAuthenticated))
                    {
                        context.Response.StatusCode = 428;
                        return context.Response.WriteAsync("Two Factor Authentication Required");
                    }
                }
            }

            return Next.Invoke(context);
        }
    }
}

Это промежуточное ПО должно проверять, был ли пользователь проверен с использованием 2FA, и если нет, возвращать код состояния ошибки. Проблема в том, что сеанс не сохраняется между запросами, идентифицированными одним и тем же токеном. Я предполагаю, что. NET создает новый сеанс для каждого запроса, даже если они приходят с одинаковым токеном доступа?

Если это так, каким будет решение для сохранения этого состояния между запросами?

...