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
导入
import { Hono } from 'hono'
import { jwk } from 'hono/jwk'
import { verifyWithJwks } from 'hono/jwt'用法
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')
})获取载荷:
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 }
})匿名访问:
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 页面或其他服务器端环境:
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 的请求。
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。
optional cookie: string
设置后,会以该值为键从 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。