是否可以使用开放 ID 连接 ID 令牌对 API 进行身份验证

Posted

技术标签:

【中文标题】是否可以使用开放 ID 连接 ID 令牌对 API 进行身份验证【英文标题】:Can an open id connect id token be used to authenticate to an api 【发布时间】:2022-01-06 13:39:39 【问题描述】:

我正在构建一个 mern 应用程序。

使用 express 构建的后端公开了一个 api,用户可以创建数据并访问他们创建的数据。

我希望允许用户使用 google 登录并获得授权来创建和访问我控制的这个 api 上的资源(而不是在 google apis 上)。

我经常看到 oauth 2 / open id connect 文章,其中指出 Id 令牌供客户端使用,而资源服务器提供的访问令牌应用于访问 api。 例如https://auth0.com/blog/why-should-use-accesstokens-to-secure-an-api/

这样做的原因是,如果在 api 上使用,id 令牌上的 aud 属性将不正确。

我意识到有些消息来源说:如果 spa 和 api 由同一服务器提供并且具有相同的客户端 ID 和受众,我可以使用和 id 令牌对 api 进行身份验证,但我希望了解我能做什么当不是这种情况时怎么办?

我觉得使用 oauth2 进行授权对我的应用来说太过分了,而且我找不到任何有关如何使用 open id connect 对我的 api 进行身份验证的信息。

当您使用 google 登录到 Auth0 授权服务器时,肯定只是从 google 请求一个开放 id 连接 id 令牌?

我想知道使用授权码授予流程在 api 服务器上接收 id 令牌是否允许我通过我的 api 对用户进行身份验证?

在这种情况下,就 open id connect 而言,api 服务器是否是客户端,因此 aud 值是否正确?

我可以使用节点 googleapis 库生成一个 url 来访问 google oauth 服务器,如下所示:

const  google  = require("googleapis");

const oauth2Client = new google.auth.OAuth2(
    'clientid','clientsecret',
    "http://localhost:3000/oauthcallback",//this is where the react app is served from
);

const calendar = google.calendar( version: "v3", auth: oauth2Client );


const scopes = ["openid"];

const url = oauth2Client.generateAuthUrl(
  // 'online' (default) or 'offline' (gets refresh_token)
  access_type: "offline",
  // If you only need one scope you can pass it as a string
  scope: scopes,
);

async function getUrl(req, res) 
  console.log(url)
  res.status(200).json(
    url,
  );

并使用以下流程。

【问题讨论】:

这取决于实际的身份验证。假设使用 jwt(通常是这种情况),但使用对称密钥进行签名。这对于身份验证是完全安全的。但是客户端可能会自行伪造令牌来查询服务器上的资源。这会打开一个安全漏洞。 【参考方案1】:

您不应该使用 ID-Token 访问任何 API。首先,ID-token 的生命周期非常短,通常为 5 分钟。

您应该始终使用访问令牌来访问 API,并且您可以使用刷新令牌获取新的访问令牌。您只能获得一次 ID-token,并使用它来创建本地用户和本地 cookie 会话。

如果您使用的是 SPA 应用程序,您还应该考虑使用 BFF 模式,以避免在 SPA-Application 中使用任何令牌 见The BFF Pattern (Backend for Frontend): An Introduction

我同意其中一位评论者的观点,即您应该遵循关注点分离的原则,并将授权服务器作为单独的服务。否则当它不起作用时它将成为调试和故障排除的引脚。

【讨论】:

我不希望使用 id 令牌作为访问令牌,我希望使用 id 令牌(已由 google 直接传递到 api 服务器)来验证 api。然后我想向客户端发送一个 jwt(不是 id 令牌,而是我在我的 api 服务器上创建的一个,就像使用用户名和密码登录时一样)用于访问 api。你说我可以使用 id 令牌来创建本地用户和本地 cookie 会话。您是指由 3rd 方 id 提供者提供给服务器或客户端的 id 令牌吗? 身份验证后您作为用户收到的 ID-token 用于识别用户,通常您基于此创建本地会话。您不能使用 ID 令牌对 API 进行身份验证。因此,当您向 Google 进行身份验证时,您应该得到两个令牌,即 ID 和访问令牌。 我想澄清一点:我想让用户访问我控制的 api。当您提到从 google 获取访问令牌时,我想知道您是否认为我正在尝试访问 google api。您还提到创建本地会话,它是否隐含在用户经过身份验证的会话中,因为会话标识请求来自谁? 我假设您使用 Google 来验证您的用户?当用户进行身份验证时,您应该取回一个 id 和访问令牌。根据您配置 Google 的方式,我假设您可以将 API 添加到 Google,以便可以使用访问令牌访问 API?如果没有,您需要在您的 API 和 google 之间添加其他人,例如 auth0.com,以便他们可以让用户通过 Google 登录,然后颁发您的 API 可以接受的访问令牌。 您在这里考虑的是让您的 API 也成为授权服务器。从技术上讲,它是可行的,它会像你描述的那样工作,但我不鼓励你走这条路。最好有明确的关注点分离 - 让 AS 问题令牌和 API 使用它们。如果您不想使用 auth0,您可以设置自己的服务器,例如使用 Keycloak,使用 Spring Security 构建,或使用我们的免费社区版 Curity Identity Server

以上是关于是否可以使用开放 ID 连接 ID 令牌对 API 进行身份验证的主要内容,如果未能解决你的问题,请参考以下文章

是否可以使用 Chrome App Indentity Api 获取 Id 令牌?

是否应该在浏览器中验证 OpenID 连接 ID 令牌?

解释 Open ID 连接中的离线令牌验证与在线令牌验证?优势、局限和权衡

Id 令牌与访问令牌

我是否可以使用客户端登录中的Firebase ID令牌来使用Java SDK对Java桌面应用程序进行身份验证?

使用客户端 ID 使用基于 AAD 令牌的身份验证公开 API