将 id_token 传递给浏览器代码是不是不安全?

Posted

技术标签:

【中文标题】将 id_token 传递给浏览器代码是不是不安全?【英文标题】:Is it insecure to pass id_token to browser code?将 id_token 传递给浏览器代码是否不安全? 【发布时间】:2018-08-12 16:35:07 【问题描述】:

我一直在深入研究 OAuth2 / OpenID Connect(OIDC),在很多方面我感觉自己更聪明,但在很多方面,我担心一个简单的错误会让我变得脆弱。我正在构建超标准的商业应用程序。所以是时候问路了:

平台:Pivotal Cloud Foundry / UAA 后端:Spring Boot 1.5.x(但现在是 2.0) 前端:React SPA OAuth2:使用openid 范围的身份验证代码授予

我收到了id_tokenaccess_tokenrefresh_token

我有一百万个问题,但让我们从基础开始:

    是否可以获取id_token 并将其发送到浏览器中的反应代码并将其存储在会话存储中?否则,UI 究竟应该如何知道有关登录者的信息?

    如果我有id_token,我还关心/userinfo 端点吗?我的猜测是否定的。

    每次 UI 调用 api 时都会传递授权码? spring 代码是否每次都会依次调用/oauth/token? Spring 代码是否应该(或是否)缓存 auth 代码和返回的令牌之间的关系?

【问题讨论】:

【参考方案1】:

SPA 的推荐流程是implicit,并且在实践中使用oidc-client-js 库是有意义的。在此流程中,access_token 直接返回给客户端,无需额外的授权代码步骤。没有发出refresh_token

在此拓扑中,令牌存储在客户端的 sessionStorage 中(默认情况下,但这是可插入的),您通过在 Authorization 标头中传递 access_token 向后端发出请求(通常)。令牌更新不是通过刷新令牌完成的,而是通过后台静默授权端点调用自动完成的。这种方法的缺点是,如果您的应用受到 XSS 攻击,那么攻击者可以立即使用您的令牌。

但是,如果您更愿意使用服务器端流程(与表单发布响应类型混合)和(仅限 https)cookie 身份验证,那么您可以。客户端代码只需要实现某种 CSRF 缓解措施,但根本不需要了解 OpenID Connect 问题。

【讨论】:

在声明but would not need to be aware of OpenID Connect concerns at all.之前,我完全关注你。你能详细说明一下吗?如果我执行身份验证代码 + openid 范围,那么我会得到 id_tokenaccess_token。我只是将 id_token 和 auth_code 一起传回 UI,我准备好了吗?对不起,如果我在这里听起来毫无头绪,但是这里有很多活动部分。这是我的 spring 代码在本地生成的:http://localhost:8888/authorization_code?code=dqkE277rAX&state=KH4G1M 使用 cookie 身份验证方法(即服务器端应用程序在验证 id_token 后发出自己的 cookie)所有 OIDC 位将在服务器端处理,客户端不需要知道任何事情除了 CSRF 缓解 - cookie 会自动传递到后端。【参考方案2】:

您只要求openid 范围,那么为什么需要访问和刷新令牌?而且由于您希望 React 应用程序使用 ID 令牌,我建议您使用隐式流程 - 将 ID 令牌直接获取到您的前端。

    您可以将令牌保留在 SessionStorage 中。 ID 令牌可能包含您需要的所有信息,因此如果 /userinfo 端点没有提供您想要的任何其他信息,您可以忽略它。 出于安全原因,验证码只能使用一次。所以拿到token之后再保留也没有意义。如果您想保持后端 API 无状态(无会话),您可以使用访问令牌。然后最好有可能在身份验证服务器上配置特定于后端的范围,或者只使用/userinfo 端点来获取有关用户的信息。或者,如果您想将前端和后端视为一个 OAuth2 客户端(相同的 ID 令牌受众),并且您在后端只需要用户身份,则可以使用 ID 令牌。

【讨论】:

所以这可能是我迷路的地方。这是我的理解。由于 XSS 问题,我希望在服务器而不是客户端上管理身份。所以我希望我的 SPA 只返回到原始服务器。所以如果是这样的话,那么我的(被误导的?)理解就是。 javascript 获取 id_token 和 auth 代码。后端接收授权码并将其换成 access_token。然后使用 access_token 调用其他后端服务。我写了一个令人惊叹的 ascii 艺术流程图,但我不能在评论中发布它:D 如果您使用 Auth 代码,那么 JavaScript 永远不会触及 auth 代码 - 浏览器会被重定向到您的后端 URL (redirect_uri 参数)。然后,如果您想向 SPA 获取令牌或某些用户信息,您需要将重定向发送到 SPA URL,例如 spa-url#id_token=base64tokenRepresentation 或使后端有状态,以便 SPA 可以从其后端会话中获取用户信息。 这对片段很有意义。从来没有想过以这种方式使用它们。澄清一点,你说JavaScript never touches the auth code。你的意思是JavaScript never touches the access_token?我看到身份验证代码返回到我的反应应用程序,但没有看到 access_token。 我的意思是授权码。身份验证代码应该由您的后端从请求参数中读取,并且在从/token 端点获取令牌后,后端应该忘记该代码并将重定向发送到您的 SPA。 灯泡!尽管我已经阅读和阅读了 2 个月,但您是第一个说“授权码是一次性使用”的人。这是我错过的一大块拼图。你是一个学者和一个绅士。

以上是关于将 id_token 传递给浏览器代码是不是不安全?的主要内容,如果未能解决你的问题,请参考以下文章

使用客户端集成将变量 Amount 传递给 Smart PayPal 按钮是不是安全?

Azure AD Daemon应用程序的应用程序权限和id_token

哪些函数 PHP 被认为不是“二进制安全的”?这些“非二进制安全”函数将字符串传递给哪些库?为啥?

将初始化向量和盐与密文一起传递是不是不安全?

将用户输入用于 Python 的正则表达式是不是安全?

自定义属性未传递到由 AWS Cognito 创建的 ID_TOKEN