Web API 2 OWIN Bearer Token 的 cookie 目的是什么?

36

我试图理解MVC 5中Single Page App模板中的OWIN Bearer Token身份验证过程。请纠正我,如果我错了的话,对于OAuth密码客户端认证流程,Bearer Token身份验证的工作方式是通过检查http授权请求头来查找Bearer访问令牌代码,以查看请求是否经过身份验证,它不依赖于cookie来检查特定请求是否经过身份验证。

根据这篇文章:

使用Web API样例进行OWIN Bearer Token身份验证

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
    using (IdentityManager identityManager = _identityManagerFactory.CreateStoreManager())
    {
        if (!await identityManager.Passwords.CheckPasswordAsync(context.UserName, context.Password))
        {
            context.SetError("invalid_grant", "The user name or password is incorrect.");
            return;
        }

        string userId = await identityManager.Logins.GetUserIdForLocalLoginAsync(context.UserName);
        IEnumerable<Claim> claims = await GetClaimsAsync(identityManager, userId);
        ClaimsIdentity oAuthIdentity = CreateIdentity(identityManager, claims,
            context.Options.AuthenticationType);
        ClaimsIdentity cookiesIdentity = CreateIdentity(identityManager, claims,
            _cookieOptions.AuthenticationType);
        AuthenticationProperties properties = await CreatePropertiesAsync(identityManager, userId);
        AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
        context.Validated(ticket);
        context.Request.Context.Authentication.SignIn(cookiesIdentity);
    }
}

GrantReourceOwnerCredentials函数不仅通过这行代码创建票据: context.Validated(ticket);,而且还组合了一个cookie身份并将其设置为cookie,使用这行代码: context.Request.Context.Authentication.SignIn(cookiesIdentity);

所以我的问题是,这个函数中的cookie确切目的是什么?AuthenticationTicket不应该足以用于认证吗?


你所提到的帖子链接已经更改,现在它是https://blogs.msdn.microsoft.com/webdev/2013/09/20/understanding-security-features-in-the-spa-template-for-vs2013-rc/。 - Himalaya Garg
3个回答

37
在SPA模板中,实际上启用了两种独立的身份验证机制- cookie身份验证和令牌身份验证,这样可以对MVC和Web API控制器操作进行身份验证,但需要一些额外的设置。 如果你查看WebApiConfig.Register方法,你会看到这行代码:
    config.SuppressDefaultHostAuthentication();

这告诉Web API忽略cookie身份验证,避免了一系列问题,这些问题在你在问题中提到的链接中有所解释:

"... SPA模板启用应用程序cookie中间件作为主动模式,以便启用其他场景,如MVC身份验证。因此,如果请求具有会话cookie但没有承载令牌,则Web API仍将进行身份验证。这可能不是您想要的,因为您将容易受到API的CSRF攻击。另一个负面影响是,如果请求未经授权,两个中间件组件都将对其应用挑战。 cookie中间件将修改401响应为302以重定向到登录页面那也不适合Web API请求."

现在通过调用config.SuppressDefaultHostAuthentication(), Web API调用需要授权的请求将忽略自动发送的cookie,并寻找以"Bearer"开头的Authorization标头。MVC控制器将继续使用cookie身份验证,并且对令牌身份验证机制毫不知情,因为它并不非常适合网页身份验证。


2
此外,CookieAuthenticationOptions 中有一个名为 CookieHttpOnly 的字段。如果将其设置为 true,则浏览器不会在 JavaScript 生成的 API 请求中发送 cookie,从而节省了带宽,并避免了调试时的潜在混淆。 - ThisGuy
“MVC控制器将继续使用cookie身份验证”是什么意思?通过这行代码config.SuppressDefaultHostAuthentication(),我能够在MVC应用程序中使用cookie身份验证和在移动应用程序中使用Bearer Token身份验证吗? - mmarques
@mmarques 我认为你自己回答了这个问题。MVC将使用cookie身份验证,而Web API将使用如上配置的令牌身份验证。 - joelmdev
1
@ThisGuy 默认值本来就是true,不过感谢你提到它。 - GFoley83
@joelmdev,为什么你认为令牌身份验证机制不太适合Web? - Pepito Fernandez
1
@Tony 因为你需要在每个请求中手动添加承载令牌头。一个简单的锚点标签无法带你到已认证的页面。域名的Cookie会自动随请求一起发送。 - joelmdev

3
存在cookie让我感到困惑,因为在承载令牌的身份验证场景中,它显然是不必要的... 在这篇文章中,作者剖析了个人账户模板,并对cookie发表了以下看法:

该方法还设置了应用程序cookie。我认为没有充分的理由。

我猜模板的作者想展示不同类型的身份验证逻辑示例,在这种情况下,他们想展示如何将身份验证信息存储在承载令牌身份验证JSON有效负载和标准身份验证cookie中。
事实上,JSON身份验证有效负载被设置为包括一个额外的(不必要的)未加密属性(用户ID),似乎支持了这一理论:
var properties = CreateProperties(user.UserName);
var ticket = new AuthenticationTicket(oAuthIdentity, properties);

看起来模板的作者想提供一些有用的示例,而不仅仅是实现持票证身份验证所需的最少要求。这也在上面链接的帖子中提到了。


3
这位作者(http://stackoverflow.com/users/672453/leastprivilege)恰好对这个主题有一点了解。他是Thinktecture.IdentityServer的作者,并且撰写了这篇有关基于声明的身份验证的微软论文(http://msdn.microsoft.com/en-us/library/ff423674.aspx)。 - EBarr

-1

Cookie有一个重要作用。它的值包含了承载令牌,可以被客户端JavaScript在您的页面上提取。这意味着如果用户按下F5或刷新页面,Cookie通常会持续存在。当页面重新加载时,您的客户端JavaScript可以从Cookie中获取承载令牌。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接