配置自定义 JWT 身份验证(Okta、Auth0)

数据 API 生成器通过自定义身份验证提供程序支持第三方标识提供者。 当你的组织使用 Okta、Auth0 或其他符合 OAuth 2.0/OpenID Connect 的标识提供者时,请使用此方法。

身份验证流

使用自定义标识提供者时,客户端应用将处理用户身份验证,然后将访问令牌发送到数据 API 生成器:

使用第三方标识提供者自定义 JWT 身份验证流的插图。

阶段 发生的情况
用户身份验证 用户通过标识提供者登录(Okta、Auth0 等)
令牌获取 客户端应用从 IdP 接收访问令牌
API 调用 客户端在 Authorization 标头中将令牌发送到 DAB。
验证 DAB 验证 JWT(颁发者、受众、签名)
授权 DAB 提取角色并评估权限

先决条件

  • 您在身份提供商(如 Okta、Auth0 等)处的账户
  • 在标识提供者中注册的应用程序
  • 已安装的数据 API 生成器 CLI (安装指南
  • 具有至少一个实体的现有 dab-config.json 实体

快速参考

设置 价值
Provider Custom
验证所必需的 issaudexp有效签名
授权所必需的 roles 包含所选角色的声明
令牌标头 Authorization: Bearer <token>
角色声明类型 roles (已修复,不可配置)
角色选择标头 X-MS-API-ROLE

步骤 1:配置标识提供者

确切的步骤取决于你的提供商。 以下是所需的键值:

要收集的值

价值 在哪里找到 用于
颁发者 URL 提供程序文档或 OAuth 元数据终结点 DAB jwt.issuer (用作 JWT 授权机构)
观众 应用程序的客户端 ID 或自定义 API 标识符 DAB jwt.audience

注释

DAB 使用配置的 jwt.issuer 作为 JWT 授权。 签名密钥通过标准的 OpenID Connect 元数据(通常为 <issuer>/.well-known/openid-configuration)自动发现。

Okta 示例

  1. 登录到 Okta 管理控制台
  2. 导航到 应用程序>应用程序
  3. 创建或选择应用程序。
  4. 记下 客户端 ID (用作目标受众)。
  5. 颁发者通常是 https://<your-domain>.okta.com

Auth0 示例

  1. 登录到 Auth0 仪表板
  2. 导航到 应用程序>API
  3. 创建或选择 API。
  4. 记下 标识符(用作目标受众)。
  5. 你的颁发者是 https://<your-tenant>.auth0.com/

重要

数据 API 生成器对基于角色的 roles 授权使用固定声明类型。 无法配置此值。 如果标识提供者在不同的声明(例如 groupspermissions)中生成角色,则必须将提供程序配置为也生成 roles 声明,或使用登录后操作将值复制到 roles 声明中。

步骤 2:配置数据 API 生成器

将身份验证提供程序设置为 Custom 并配置 JWT 设置:

CLI

# Set the authentication provider
dab configure \
  --runtime.host.authentication.provider Custom

# Set the expected audience
dab configure \
  --runtime.host.authentication.jwt.audience "<your-api-identifier>"

# Set the expected issuer
dab configure \
  --runtime.host.authentication.jwt.issuer "https://<your-issuer>/"

生成的配置

{
  "runtime": {
    "host": {
      "authentication": {
        "provider": "Custom",
        "jwt": {
          "audience": "<your-api-identifier>",
          "issuer": "https://<your-issuer>/"
        }
      }
    }
  }
}

步骤 3:配置实体权限

定义标识提供者分配的角色的权限:

CLI

# Allow authenticated users to read
dab update Book \
  --permissions "authenticated:read"

# Allow users with 'admin' role full access
dab update Book \
  --permissions "admin:*"

生成的配置

{
  "entities": {
    "Book": {
      "source": "dbo.Books",
      "permissions": [
        {
          "role": "authenticated",
          "actions": ["read"]
        },
        {
          "role": "admin",
          "actions": ["*"]
        }
      ]
    }
  }
}

步骤 4:在标识提供者中配置角色

DAB 期望声明中 roles 的角色。 配置您的身份提供者以包含此声明。

Okta:将群组添加为角色

  1. 在 Okta 管理控制台中,转到 安全>API
  2. 选择授权服务器。
  3. 转到“ 声明 ”选项卡。
  4. 添加声明:
    • 名称roles
    • 包含在令牌类型中:访问令牌
    • 值类型:组
    • 筛选器:选择要包含的组

Auth0:添加角色与动作

  1. 在 Auth0 仪表板中,转到 操作>
  2. 创建一个新的操作(登录后触发)。
  3. 添加代码以包括角色:
exports.onExecutePostLogin = async (event, api) => {
  const roles = event.authorization?.roles || [];
  if (roles.length > 0) {
    api.accessToken.setCustomClaim('roles', roles);
  }
};
  1. 部署操作并且将其添加到登录流。

小窍门

有关使用 Okta 配置 JWT 声明的详细指南,请参阅 使用 Okta 的 SDK 实现高级 JWT 声明

步骤 5:测试配置

  1. 启动数据 API 生成器:

    dab start
    
  2. 从标识提供者获取令牌。 使用提供商的 SDK 或 Postman 等工具。

  3. 检查 jwt.io 处的令牌以验证:

    • 声明aud与已配置的受众匹配
    • 声明 iss 与配置的颁发者匹配
    • roles 声明包含预期值
  4. 调用 API:

    curl -X GET "http://localhost:5000/api/Book" \
      -H "Authorization: Bearer <your-token>"
    
  5. 若要使用自定义角色,请包括 X-MS-API-ROLE 标头:

    curl -X GET "http://localhost:5000/api/Book" \
      -H "Authorization: Bearer <your-token>" \
      -H "X-MS-API-ROLE: admin"
    

JWT 验证详细信息

数据 API 生成器验证 JWT 的以下方面:

检查 Description
签名 使用通过配置的 jwt.issuer 颁发机构发现的签名密钥(OpenID Connect 元数据/JWKS)进行验证
颁发者 必须完全匹配 jwt.issuer 配置
观众 必须完全匹配 jwt.audience 配置
过期日期 令牌不得过期(exp 声明)
不早于 令牌必须有效(nbf 声明(如果存在)

Troubleshooting

症状 可能的原因 解决方案
401 Unauthorized 颁发者不匹配 请检查iss声明是否完全匹配(包括结尾的斜杠)
401 Unauthorized 受众不匹配 检查aud声明是否与配置的值匹配
401 Unauthorized 令牌已过期 获取新令牌
401 Unauthorized 元数据不可用 确保 DAB 能够到达 <issuer>/.well-known/openid-configuration
403 Forbidden 角色不在令牌中 将角色添加到 IdP 配置
403 Forbidden 缺少角色声明 将 IdP 配置为包含 roles 声明
403 Forbidden 错误的声明名称 DAB 使用声明类型 roles (固定,不可配置)

重要

DAB 当前使用声明类型 roles 来进行所有角色检查。 此值是硬编码的,不能更改为groupspermissions其他声明名称。 将标识提供者配置为在名为 roles 的声明中发送角色。

常见发行者格式

Provider 颁发者格式
Okta https://<domain>.okta.comhttps://<domain>.okta.com/oauth2/default
Auth0 https://<tenant>.auth0.com/ (请注意尾部斜杠)
Azure AD B2C https://<tenant>.b2clogin.com/<tenant-id>/v2.0/
Keycloak https://<host>/realms/<realm>

完整配置示例

Okta 配置

{
  "$schema": "https://github.com/Azure/data-api-builder/releases/latest/download/dab.draft.schema.json",
  "data-source": {
    "database-type": "mssql",
    "connection-string": "@env('SQL_CONNECTION_STRING')"
  },
  "runtime": {
    "host": {
      "authentication": {
        "provider": "Custom",
        "jwt": {
          "audience": "0oa1234567890abcdef",
          "issuer": "https://dev-12345.okta.com"
        }
      }
    }
  },
  "entities": {
    "Book": {
      "source": "dbo.Books",
      "permissions": [
        {
          "role": "authenticated",
          "actions": ["read"]
        },
        {
          "role": "editor",
          "actions": ["create", "read", "update"]
        }
      ]
    }
  }
}

Auth0 配置

{
  "$schema": "https://github.com/Azure/data-api-builder/releases/latest/download/dab.draft.schema.json",
  "data-source": {
    "database-type": "mssql",
    "connection-string": "@env('SQL_CONNECTION_STRING')"
  },
  "runtime": {
    "host": {
      "authentication": {
        "provider": "Custom",
        "jwt": {
          "audience": "https://my-api.example.com",
          "issuer": "https://my-tenant.auth0.com/"
        }
      }
    }
  },
  "entities": {
    "Book": {
      "source": "dbo.Books",
      "permissions": [
        {
          "role": "authenticated",
          "actions": ["read"]
        },
        {
          "role": "admin",
          "actions": ["*"]
        }
      ]
    }
  }
}