跳转到正文

JWK Auth 中间件 ​

JWK Auth 中间件使用 JWK(JSON Web Key)验证令牌,对请求进行身份验证。它检查 Authorization 请求头,以及配置的其他来源(如 Cookie)。它使用提供的 keys 验证令牌;指定 jwks_uri 时会从该地址获取密钥;设置 cookie 选项时,也支持从 Cookie 提取令牌。

此中间件验证的内容 ​

对于每个令牌,jwk() 会:

  • 解析并验证 JWT 头部的格式。
  • 要求头部包含 kid,并按 kid 查找匹配密钥。
  • 拒绝对称算法(HS256、HS384、HS512)。
  • 要求头部的 alg 包含在配置的 alg 允许列表中。
  • 如果匹配的 JWK 含有 alg 字段,要求它与 JWT 头部的 alg 一致。
  • 使用匹配的密钥验证令牌签名。
  • 默认验证时间相关声明:nbf、exp 和 iat。

可以通过 verification 选项配置可选的声明验证:

  • iss:提供时验证签发者。
  • aud:提供时验证受众。

如果需要在上述内容之外进行额外的令牌检查(如自定义的应用层授权规则),请在 jwk() 之后添加自己的中间件。

说明

客户端发送的 Authorization 请求头必须包含指定的身份验证方案。

示例:Bearer my.token.value 或 Basic my.token.value

导入 ​

ts
import { Hono } from 'hono'
import { jwk } from 'hono/jwk'
import { verifyWithJwks } from 'hono/jwt'

用法 ​

ts
const app = new Hono()

app.use(
  '/auth/*',
  jwk({
    jwks_uri: `https://${backendServer}/.well-known/jwks.json`,
    alg: ['RS256'],
  })
)

app.get('/auth/page', (c) => {
  return c.text('You are authorized')
})

获取载荷:

ts
const app = new Hono()

app.use(
  '/auth/*',
  jwk({
    jwks_uri: `https://${backendServer}/.well-known/jwks.json`,
    alg: ['RS256'],
  })
)

app.get('/auth/page', (c) => {
  const payload = c.get('jwtPayload')
  return c.json(payload) // eg: { "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }
})

匿名访问:

ts
const app = new Hono()

app.use(
  '/auth/*',
  jwk({
    jwks_uri: (c) =>
      `https://${c.env.authServer}/.well-known/jwks.json`,
    alg: ['RS256'],
    allow_anon: true,
  })
)

app.get('/auth/page', (c) => {
  const payload = c.get('jwtPayload')
  return c.json(payload ?? { message: 'hello anon' })
})

在中间件之外使用 verifyWithJwks ​

verifyWithJwks 工具函数可以在 Hono 中间件上下文之外验证 JWT 令牌,例如用于 SvelteKit SSR 页面或其他服务器端环境:

ts
const id_payload = await verifyWithJwks(
  id_token,
  {
    jwks_uri: 'https://your-auth-server/.well-known/jwks.json',
    allowedAlgorithms: ['RS256'],
  },
  {
    cf: { cacheEverything: true, cacheTtl: 3600 },
  }
)

配置 JWKS 获取请求选项 ​

要配置如何从 jwks_uri 获取 JWKS,请将 fetch 请求选项作为 jwk() 的第二个参数传入。

此参数为 RequestInit,仅用于获取 JWKS 的请求。

ts
const app = new Hono()

app.use(
  '/auth/*',
  jwk(
    {
      jwks_uri: `https://${backendServer}/.well-known/jwks.json`,
      alg: ['RS256'],
    },
    {
      headers: {
        Authorization: 'Bearer TOKEN',
      },
    }
  )
)

选项 ​

required alg: AsymmetricAlgorithm[] ​

允许用于令牌验证的非对称算法数组。

可用类型包括 RS256 | RS384 | RS512 | PS256 | PS384 | PS512 | ES256 | ES384 | ES512 | EdDSA。

optional keys: HonoJsonWebKey[] | (c: Context) => Promise<HonoJsonWebKey[]> ​

公钥值,或返回公钥值的函数。该函数接收 Context 对象。

optional jwks_uri: string | (c: Context) => Promise<string> ​

设置后,会尝试从此 URI 获取 JWK,预期响应为包含 keys 的 JSON,并将获取的密钥添加到提供的 keys 选项中。也可以传入回调函数,使用 Context 动态决定 JWKS URI。

optional allow_anon: boolean ​

设为 true 后,没有有效令牌的请求也可通过中间件。使用 c.get('jwtPayload') 检查请求是否已验证。默认值为 false。

设置后,会以该值为键从 cookie 请求头获取对应值,再作为令牌验证。

optional headerName: string ​

查找 JWT 令牌的请求头名称。默认值为 Authorization。

optional realm: string ​

在 401 响应返回的 WWW-Authenticate 质询头中,由 realm 参数描述的保护域。默认值为请求 URL。

optional verification: VerifyOptions ​

除签名验证之外,配置声明验证行为:

optional VerifyOptions.iss: string | RegExp ​

验证令牌时预期的签发者。未设置时,不会检查 iss 声明。

optional VerifyOptions.aud: string | string[] | RegExp ​

验证令牌时预期的受众。设置后,令牌必须包含 aud 声明,且至少一个受众值必须匹配。

optional VerifyOptions.nbf: boolean ​

nbf(生效时间)声明存在且此项设为 true 时,会验证该声明。默认值为 true。

optional VerifyOptions.iat: boolean ​

iat(签发时间)声明存在且此项设为 true 时,会验证该声明。默认值为 true。

optional VerifyOptions.exp: boolean ​

exp(过期时间)声明存在且此项设为 true 时,会验证该声明。默认值为 true。

基于 MIT 许可证发布。