OpenId Connect 问题 - 授权代码流 (OAuth 2.0)

Posted

技术标签:

【中文标题】OpenId Connect 问题 - 授权代码流 (OAuth 2.0)【英文标题】:OpenId Connect Questions -Authorization Code Flow (OAuth 2.0) 【发布时间】:2015-12-11 17:00:07 【问题描述】:

我正面临 OpenId Connect 的自定义实现。但是(总有一个but)我有些疑惑:

我了解获取acces_token和id_token的过程,除了OP向客户端提供authorization_code的步骤。如果它是通过重定向完成的(使用重定向 uri)

HTTP/1.1 302 Found
Location: https://client.example.org/cb?
code=SplxlOBeZQQYbYS6WxSbIA
&state=af0ifjsldkj
最终用户能够看到该授权码吗?它不会过期吗?想象一下我们抓住了它,我们稍后(几天后)使用它是一个安全漏洞吗?令牌端点中的状态是否应该过期?

流程继续,我们在客户端获得了Access_tokenid_token

Access_token 应该如何在 OP 端使用?它应该存储在数据库中吗?或者自行包含验证所需的信息?您会推荐什么? 在客户端,每个请求都应该发送两个令牌?

最后一个疑问,如果我们有一个Access_token,那么id_token 的存在是为了在单独的令牌中表示授权和身份验证?

额外疑惑: 我知道获取访问令牌的过程,但我怀疑 OP 一旦生成和发送,它会验证每个请求附带的 access_token

OP 如何知道访问令牌有效?据我所知,OP 应该说 access_token 是有效/无效的。应该有一些方法来检查它吧?如果令牌没有存储在 DB 中,它如何知道它代表一个有效的经过身份验证的用户? 将 access_token 存储在 cookie 中是不是一个坏主意?因为有时我们调用一些 web 服务,我们想发送 access_token 作为参数。还是有其他变通解决方案? 访问令牌应如何存储在 Client 中,例如在 ASP.NET 中,在会话中?

非常感谢大家,一旦你给我解释,我会放弃投票并标记为答案。 谢谢!

【问题讨论】:

补充的疑惑,也请回答! 【参考方案1】:

最终用户能够看到该授权码吗?

是的。虽然,即使可以看到授权码,令牌请求也需要发送客户端的秘密(浏览器看不到)

它不会过期吗?想象一下我们抓住了它,我们稍后(几天后)使用它是一个安全漏洞? Token Endpoint 中的状态是否应该过期?

规范说授权码应该过期。见https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2。

在 OP 端应该如何使用 Access_token ?它应该存储在数据库中吗?或者自己包含验证它所需的信息?你会推荐什么?

如果您希望能够撤销令牌,则应将访问令牌存储在 OP 上。如果您不这样做,令牌将采用 JWT 格式(自包含)...但如果您希望能够撤销它,无论它是否是 JWT,您都应该存储它。

在客户端,每个请求都应该发送两个令牌?

不,只是访问令牌。

最后一个疑问,如果我们有一个 Access_token,那么 id_token 的存在是为了在分离的令牌中表示授权和身份验证?

是的,它们是用于不同目的的单独令牌。访问令牌用于授权,ID 令牌是自包含的,用于与客户端通信用户已通过身份验证。

OP 如何知道访问令牌有效?据我所知,OP 应该说 access_token 是有效/无效的。应该有一些方法来检查它吧?如果令牌没有存储在 DB 中,它如何知道它代表一个有效的经过身份验证的用户?

请参阅How to validate an OAuth 2.0 access token for a resource server?,了解有关资源服务器应如何在让来自客户端的请求通过之前验证访问令牌的想法。

将 access_token 存储在 cookie 中是个坏主意吗?因为有时我们调用一些 web 服务,我们想发送 access_token 作为参数。还是有其他解决方法?

我假设您正在使用授权代码授予流程(...根据您的问题)。如果是这种情况,首先从 OP 而不是访问令牌传回授权代码的原因是,访问令牌可以隐藏在服务器端——远离浏览器本身。使用授权代码授予流程,访问令牌应远离浏览器。如果您想直接从浏览器向资源服务器发送 api 请求,请查看 oauth2 隐式流程 (https://www.rfc-editor.org/rfc/rfc6749#section-4.2)。

访问令牌应如何存储在 Client 中,例如在 ASP.NET 中,在会话中?

在 OAuth2 的 OpenID Connect 风格中,访问令牌用于离线访问(即在经过身份验证的“会话”之外)。访问令牌可以在用户会话期间使用,但最好将刷新令牌存储在数据库中,以便您的客户端应用程序可以在需要时请求新的访问令牌,只要刷新令牌有效。 .即使用户的身份验证过期。访问令牌应该是短暂的,因此将其存储在数据库中是一种选择,但不是必需的。

【讨论】:

非常感谢!我补充了一些额外的疑问,如果你能回答他们将不胜感激,然后我可以标记为你的答案。 非常感谢!你太有帮助了。想象一下这样的情况,一个 app1 获得了一个 access_token,需要在另一个 app2 webservice 上使用(在某些情况下)。我们想使用相同的 access_token 来访问 app1 以在 app2 上调用 ws,这可能吗?我们应该为此目的使用隐式流吗?因为如果没有,access_token会留在app1的会话中吗?或者将 access_tokens 存储在数据库中,可以提取一个 JWT access_token,它具有自包含的所有权限(例如在 app2 上调用 web 服务的权限?

以上是关于OpenId Connect 问题 - 授权代码流 (OAuth 2.0)的主要内容,如果未能解决你的问题,请参考以下文章

OpenID Connect Core 1.0使用授权码流验证(下)

OpenID Connect 的 OWIN 中间件 - 代码流(流类型 - AuthorizationCode)文档?

OpenID Connect 是不是支持资源所有者密码凭证授予?

ASP.NET Web API 和 OpenID Connect:如何从授权码中获取访问令牌

[认证授权] 4.OIDC(OpenId Connect)身份认证授权(核心部分)

OpenID Connect:如何在客户端凭证流中添加自定义声明数据