Web API 2,OWIN 身份验证,SignOut 不注销

Posted

技术标签:

【中文标题】Web API 2,OWIN 身份验证,SignOut 不注销【英文标题】:Web API 2, OWIN Authentication, SignOut doesn't logout 【发布时间】:2014-08-24 12:04:53 【问题描述】:

我正在做一些研究,以期使用 Bearer 令牌作为身份验证机制(即 AngularJS UI,在 Web API [2] 项目中通过 OWIN 进行身份验证)。

我的登录工作正常,角色信息和一切都很好,但我无法获取用于注销的令牌。

我的启动配置是这样的:

OAuthOptions = new OAuthAuthorizationServerOptions() 
    TokenEndpointPath = new PathString("/Token"),
    Provider = new ApplicationOAuthProvider(PublicClientId),
    AccessTokenExpireTimeSpan = SESSION_TIMEOUT,
    AllowInsecureHttp = true
;

而我的注销操作就是这样:

public HttpResponseMessage Logout() 
    var authentication = HttpContext.Current.GetOwinContext().Authentication;
    authentication.SignOut(DefaultAuthenticationTypes.ExternalBearer);

    return new HttpResponseMessage(HttpStatusCode.OK);

为简洁起见,我已将所有身份验证内容省略,但为了确认我在设置令牌时使用的是 ExternalBearer

在我的 UI 中,我将令牌存储在本地存储中(此处不涉及 cookie,这是一个经过深思熟虑的设计决定)。所以我的 UI 上有一个 logout 按钮,Logout 操作被点击并且代码运行良好。

但是,如果我随后在 API 上执行需要授权的操作,请求仍会通过(即,即使用户应该已注销,用户仍会通过身份验证。

要么我遗漏了一些非常明显的东西(不会是第一次;-),要么这里发生了一些更基本的事情 - 最后我正在 ping @leastprivilege,因为我知道这是他们的领域。

我们将不胜感激地收到任何帮助或见解。


我唯一能想到的是令牌在服务器/API 端是无状态的,因此不能过期或注销。

如果是这样的话,我想我可以:

a) 添加一个刷新令牌,该令牌创建一个在过去过期的新令牌 - 这甚至可以工作吗? - 实际上取消它,它会发出一个新令牌......旧令牌仍然有效

b) 将不记名令牌存储在数据库中并每次检查,在注销时删除令牌(自然加盐、散列等)。然而,这只是让我们回到拥有一个有状态的服务器。

c) 当有人明确注销时,我可以(并且将会)从本地存储中删除该令牌,但是如果 一个坏人 可以拦截该令牌,则该令牌在技术上仍然有效。当然,以上所有内容都会超过 SSL,这应该会抑制 坏人/坏人

d) 也许这就是为什么很多人将 Bearer 令牌存储在 cookie 中(作为一种存储机制)的原因,因此一旦您注销,至少 cookie 将在下次刷新时被删除。

抱歉,以上内容有点脑残,只是想抢先提问

【问题讨论】:

如果您通过以下建议解决了问题,请添加您的代码。对于您在哪里添加唯一 ID 并启用 IncludeJwtId,我真的有点困惑 【参考方案1】:

只要我知道不记名令牌存在于客户端,所以我认为您不需要服务器端“注销”功能。只需从客户端本地存储中删除令牌即可将您注销。

【讨论】:

是的,我们将这样做(参见 C),但事实是 Bearer 令牌仍然有效。如果有人可以在删除之前拦截它,他们仍然可以冒充用户。 没问题。我很感谢你努力阅读它:-) 在不记名令牌上设置较短的过期时间(如30分钟)并在刷新令牌上实施数据库验证策略?【参考方案2】:

由于 OAuth 不是身份验证协议,因此没有注销的概念。删除客户端上的访问令牌 - 这就是您所能做的。

如果您想在服务器端使令牌无效,请为其添加一个唯一 id 并在您的服务中跟踪 - 您需要手动构建类似的东西。

【讨论】:

我认为这证实了我的想法。谢谢。 令牌需要这样做。在 IdentityServer 例如每个客户端都有一个标志IncludeJwtId 那么认证的目的是什么。SignOut(DefaultAuthenticationTypes.ExternalBearer); @leastprivilege 我正在使用 Oauth 连接到 Quickbooks Online。它有自己的身份验证服务器和身份验证客户端。连接并验证令牌后,我正在使用登录方法设置 owin athentication cookie。它设置了 User.Identity 并授权我的控制器,这些控制器不允许完美的匿名访问。但是当 QBO 会话到期时,它会在调用 api 时抛出 401。在这里,我发现了这个异常并要求退出。但是 mvc User.Identity 仍然有效。在这种情况下该怎么做,因为在我的情况下删除访问令牌不起作用。【参考方案3】:

这个问题已经存在了很长时间(并且也得到了回答),但我只是想表达一下自己的想法。

我会做与您的 (C) 选项类似的操作,但在不记名访问令牌上使用较短的到期时间,例如 10 或 20 分钟,这样当您注销并删除客户端上的令牌时,尽管从技术上讲令牌仍然有效,坏人将只有剩余的到期时间来玩你的有效令牌。

在实践中,我会将它与长寿命刷新令牌一起使用,以便在它过期并希望继续与 API 资源交互时获得新的不记名令牌,而无需再次进行身份验证。

【讨论】:

@Duncan 我想我不小心标记了答案。我已删除我的评论。很抱歉,感谢您的纠正。【参考方案4】:

我在这里有一个很好的解决方案:http://www.nakov.com/blog/2014/12/22/webapi-owin-identity-custom-login-service/。它是基于 OWIN 和标准 ASP.NET Identity (Microsoft.AspNet.Identity.EntityFramework) 的 Web API OAuth 不记名令牌授权的自定义用户会话实现。它可以像大多数人所期望的那样工作:

Web API 会话在 30 分钟不活动后终止。 每次授权 HTTP 请求时,会话的生命周期都会延长 30 分钟。 注销工作正常:注销后持有者 access_token 变为无效(已被撤销)。

GitHub 上提供了完整的工作源代码:https://github.com/SoftUni/SPA-with-AngularJS/tree/master/Ads-REST-Services

【讨论】:

非常好的博文。谢谢你的来信。

以上是关于Web API 2,OWIN 身份验证,SignOut 不注销的主要内容,如果未能解决你的问题,请参考以下文章

具有混合身份验证 JWT 和 SAML 的 ASP.NET Web API 2.2 OWIN

身份验证/授权 MVC 5 和 Web API - Katana/Owin

Web API 2 OWIN Bearer Token cookie的用途?

OWIN 托管的 web api:使用 windows 身份验证并允许匿名访问

实施 Identity 2.1 + OWIN OAuth JWT 不记名令牌时如何从 Web API 控制器端点进行身份验证

具有 OWIN 自主机和 Windows 身份验证的 Web Api