跳到主要内容
ecdsa.com
golang-jwt/jwt (Go)Go

错误信息

token signature is invalid: signing method ES256 is invalid

也可能输出为

  • signing method ES256 is invalid
  • token signature is invalid: signing method HS256 is invalid
  • token is unverifiable: signing method (alg) is unavailable

v4 打印的是“signing method ES256 is invalid”。如果 `alg` 的值是 golang-jwt 完全不认识的(或者是没有使用专用常量的 `none`),得到的则是“token is unverifiable: signing method (alg) is unavailable”。

golang-jwt/jwt (Go) — WithValidMethods rejected the token's alg

含义

令牌的 `alg` 头部不在你通过 `jwt.WithValidMethods` 传入的列表中,因此 golang-jwt 在调用你的 Keyfunc 获取密钥之前就拒绝了它。之所以有这项检查,是因为头部由攻击者控制:决定接受哪种算法的是验证方,而不是令牌。v5 把它归入 `ErrTokenSignatureInvalid`,因此看起来像是签名有误——实际上这是算法策略导致的拒绝。

原因

修复方法

  1. 1.

    只允许颁发者实际使用的算法

    读取颁发者的 JWKS(每个密钥的 `alg`)或发现文档(`id_token_signing_alg_values_supported`),并固定使用这些值。迁移期间同时列出新旧两种算法,并按 `kid` 选择密钥。

    go
    token, err := jwt.Parse(raw, keyfunc,
    	jwt.WithValidMethods([]string{"ES256"}), // what the issuer signs with today
    	jwt.WithIssuer("https://issuer.example.com/"),
    )
  2. 2.

    在 Keyfunc 中断言签名方法的类型

    在 Keyfunc 中检查 `t.Method` 的具体类型,可以保证 ECDSA 密钥只会与 ECDSA 算法一起使用,即使以后放宽了允许列表也是如此。

    go
    keyfunc := func(t *jwt.Token) (any, error) {
    	// Belt and braces: the key type must fit the algorithm family.
    	if _, ok := t.Method.(*jwt.SigningMethodECDSA); !ok {
    		return nil, fmt.Errorf("unexpected signing method %v", t.Header["alg"])
    	}
    	return lookupKey(t.Header["kid"])
    }

相关错误

浏览完整的签名错误库