Периодические циклы перенаправления во время проверки подлинности ADFS

Я использую Owin для настройки своего приложения ASP.NET MVC 5 (.NET 4.5, IIS 7/8) для аутентификации в сторонней настройке ADFS:

app.SetDefaultSignInAsAuthenticationType(WsFederationAuthenticationDefaults.AuthenticationType);

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType
});

app.UseWsFederationAuthentication(new WsFederationAuthenticationOptions
{
    Wtrealm = Settings.Auth.Wtrealm,
    MetadataAddress = Settings.Auth.MetadataAddress
});

У меня также есть собственный фильтр проверки подлинности (используется вместе с AuthorizeAttribute):

public class OwinAuthenticationAttribute : ActionFilterAttribute, IAuthenticationFilter
{
    public void OnAuthentication(AuthenticationContext filterContext)
    {
        var user = filterContext.RequestContext.HttpContext.User;

        var authenticated = user.Identity.IsAuthenticated;
        if (!authenticated)
        {
            return;
        }

        /* Redirect to profile setup if not already complete */
    }

    public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
    {
    }
}

В половине случаев это работает нормально, но иногда при первоначальном входе между приложением и входом в ADFS возникает цикл перенаправления. Похоже, что это зависит от сеанса (не происходит для всех пользователей одновременно), и как только возникает цикл перенаправления, кажется, что он продолжается до обновления пула приложений.

Когда возникает цикл перенаправления, я все еще вижу (на вкладке Chrome Network), что выглядит как действительный токен, выдаваемый ADFS.

Мне трудно выделить основную причину, но я обнаружил, что когда цикл не возникает, user.Identity имеет тип ClaimsIdentity, а IsAuthenticated - это true. Когда это действительно происходит, IsAuthenticated равно false, но user.Identity имеет тип WindowsIdentity.

Все формы аутентификации в IIS, кроме Anonymous, отключены. IIS Express нигде не используется.

Что может быть причиной этого?


person Ant P    schedule 17.02.2015    source источник


Ответы (1)


Используете ли вы данные сеанса и/или TempData? Я понимаю, это связано с файлами cookie. У меня тоже такая же проблема.

Вот дополнительная информация и подробное объяснение причины. Эту проблему можно обойти, заставив Owin использовать конвейер файлов cookie System.Web (см. здесь):

public class SystemWebCookieManager : ICookieManager
{
    public string GetRequestCookie(IOwinContext context, string key)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }

        var webContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);
        var cookie = webContext.Request.Cookies[key];
        return cookie == null ? null : cookie.Value;
    }

    public void AppendResponseCookie(IOwinContext context, string key, string value, CookieOptions options)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        if (options == null)
        {
            throw new ArgumentNullException("options");
        }

        var webContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);

        bool domainHasValue = !string.IsNullOrEmpty(options.Domain);
        bool pathHasValue = !string.IsNullOrEmpty(options.Path);
        bool expiresHasValue = options.Expires.HasValue;

        var cookie = new HttpCookie(key, value);
        if (domainHasValue)
        {
            cookie.Domain = options.Domain;
        }
        if (pathHasValue)
        {
            cookie.Path = options.Path;
        }
        if (expiresHasValue)
        {
            cookie.Expires = options.Expires.Value;
        }
        if (options.Secure)
        {
            cookie.Secure = true;
        }
        if (options.HttpOnly)
        {
            cookie.HttpOnly = true;
        }

        webContext.Response.AppendCookie(cookie);
    }

    public void DeleteCookie(IOwinContext context, string key, CookieOptions options)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        if (options == null)
        {
            throw new ArgumentNullException("options");
        }

        AppendResponseCookie(
            context,
            key,
            string.Empty,
            new CookieOptions
            {
                Path = options.Path,
                Domain = options.Domain,
                Expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),
            });
    }
}

И чтобы подключить его:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    // ...
    CookieManager = new SystemWebCookieManager()
})
person Jamie    schedule 18.02.2015
comment
Спасибо за это - вы спасли меня от головной боли. Как ни странно, мы наткнулись на ваш вопрос по этому поводу, но на него не ответили! Надеюсь, вы не возражаете, но я расширил ваш ответ, включив в него обходной путь от ошибки Katana, чтобы люди все еще могли добраться до него, если ссылка когда-либо не работает. Я собирался добавить свой собственный ответ с этой дополнительной информацией, но я думаю, что вы заслуживаете похвалы за это. - person Ant P; 19.02.2015
comment
Я забыл, что уже спрашивал об этом, мне лучше пойти и обновить его. Я также реализовал это решение и пока все хорошо. - person Jamie; 19.02.2015
comment
На случай, если это сэкономит кому-то время, CookieAuthenticationOptions.CookieManager доступен только из Microsoft.Owin.Security. .Cookies начиная с версии 3.0.0 - person Dunc; 10.05.2016
comment
Слава за это. Невероятно, что это все еще проблема сегодня. Я реализовал ваше решение, и оно работает безупречно. Мне только недавно пришлось это сделать, так как наша текущая реализация перестала работать на ровном месте. Сумасшедший! - person Joshua H; 03.05.2017