Request/obtain 用于访问 API (Auth0) 的访问令牌

Request/obtain Access Token for accessing API (Auth0)

我正在学习如何在我们的 Next.js 应用程序中使用 Auth0。使用 nexjs-auth0 SDK。我已成功通过 Auth0 进行身份验证并收到 ID 令牌和访问令牌(用于 Auth0 管理 api)。这似乎是事物的默认配置。我们有一个 API 的设置,它也将使用 Auth0 身份验证。在阅读文档数小时后,我无法弄清楚的是如何让 access_token 用于 API。

我一直在读到您没有为 API 使用 ID 令牌(个人资料信息),而是使用访问令牌。此外,当您 authenticate the user(login) 时,它会读取以获取访问令牌。我还没弄明白。

我已经在 Auth0 中定义了应用程序和 API 端点。 有一个用户设置并分配了一个角色。 这个角色有几个范围我通过它。

我能否在同一个登录调用中同时获得 api 的 ID 令牌和访问令牌,还是在用户登录后请求 API 访问令牌?我假设 API 访问令牌将是承载 jwt 类型令牌。

经历了很多痛苦之后,question-asking 发现您需要在请求中包含 API 的听众。对于Next.js-Auth0 SDK,我们这个问题的作用域,这个可以在Auth0初始化的时候完成。

文件中lib/auth0.js:

import { initAuth0 } from '@auth0/nextjs-auth0'

export default initAuth0({
  clientId: process.env.AUTH0_CLIENT_ID,
  clientSecret: process.env.AUTH0_CLIENT_SECRET,
  scope: process.env.AUTH0_SCOPE,
  audience: 'http://api.example.com/v1',
  domain: process.env.AUTH0_DOMAIN,
  redirectUri: process.env.REDIRECT_URI,
  postLogoutRedirectUri: process.env.POST_LOGOUT_REDIRECT_URI,
  session: {
    cookieSecret: process.env.SESSION_COOKIE_SECRET,
    cookieLifetime: process.env.SESSION_COOKIE_LIFETIME,
  },
})

我将受众参数添加到该文件 (audience: 'http://api.example.com/v1',),从 Auth0 仪表板将其设置为 API Identifier

这是另一个混​​淆点,因为当您在 Auth0 中设置自定义 API 时,它同时具有 IdIdentifier。您可以通过标题在顶部找到标识符。据我所知,标识符一直是端点的 uri。

添加 audience 参数后,当用户登录时,收到的 accessToken 现在是一个 JWT 承载令牌,可以与我的 API 一起使用。它只包含所需的安全位,不包含配置文件位。

要向 accessToken 添加权限,请在 Auth0 仪表板中针对 API 进行以下更改:

  • 启用 RBAC - true/on
  • 在访问令牌中添加权限 - true/on

现在是 2021 年,Auth0 已将 nextjs-auth0 库退出测试版。示例设置此时没有提到 initAuth0(),但是如果您在 Next API 路由中调用 getAccessToken(),您仍然会得到一个如下所示的短标记:vVuzVl6e0O-ydWeJXtvweASvhnWoav7w.这是因为Auth0 uses the audience parameter要判断是提供不透明令牌还是JWT。

要获取 JWT 不记名令牌以放入 Authorization header,您只需 add the audience and scope as parametershandleAuth() 中的 pages/api/auth/[...auth0].js 调用:

// pages/api/auth/[...auth0].js
import { handleAuth, handleLogin } from '@auth0/nextjs-auth0';

export default handleAuth({
  async login(req, res) {
    try {
      await handleLogin(req, res, {
        authorizationParams: {
          audience: 'https://api.example.com/products', // or AUTH0_AUDIENCE
          // Add the `offline_access` scope to also get a Refresh Token
          scope: 'openid profile email read:products' // or AUTH0_SCOPE
        }
      });
    } catch (error) {
      res.status(error.status || 400).end(error.message);
    }
  }
});

然后从您的 API 路由中对 getAccessToken() 的调用将 return 一个 JWT,您可以使用它来调用您的 API:

// pages/api/widget/[id].js
import { getAccessToken, withApiAuthRequired } from '@auth0/nextjs-auth0';

export default withApiAuthRequired(async function widget(req, res) {
  try {
    const { accessToken } = await getAccessToken(req, res);
    const { id } = req.query

    const response = await fetch(`https://MY_API_DOMAIN/widget/${id}`, {
        headers: {
            Authorization: `Bearer ${accessToken}`
        }
    })
    const widget = await response.json()

    res.status(200).json(widget)
  } catch(error) {
    console.error(error)
    res.status(error.status || 500).end(error.message)
  }
});

由于 已经回答了原因,我还将为那些使用更默认的 nextjs 设置的人添加另一个解决方案,您只需按照管理页面上的教程并使用 handleAuth() 在你的 api/auth/[...auth0].js.

AUTH0_AUDIENCE=<YOUR AUDIENCE> 添加到您的 .env.local 文件,并且不要忘记将其添加到环境变量中的 Vercel 仪表板。

您可以在管理仪表板中查找 Auth0 API 的受众 -> Applications -> APIs

或者,您可以将默认受众附加到该租户中的每个 请求。转到 Settings -> API Authorization Settings 部分 -> Default Audience。缺点是它不那么灵活。好处是,漂浮的环境变量更少。