我有一个Go HTTP服务器.我想使用Azure JWT令牌保护我的路由.我能够生成令牌,但我无法验证它.

我是这样做的:

package main

import (
    "context"
    "errors"
    "fmt"

    "github.com/dgrijalva/jwt-go"
    "github.com/lestrrat-go/jwx/jwa"
    "github.com/lestrrat-go/jwx/jwk"
    njwt "github.com/lestrrat-go/jwx/jwt"
)

const token = "<access-token>"

const jwksURL = `https://login.microsoftonline.com/common/discovery/keys`

func main() {
    set, _ := jwk.Fetch(context.TODO(), jwksURL)
    // verified that set has required kid 
    verify2(token, set)
    token, err := verify(token, set)
    // token, err := jwt.Parse(token, getKey)
    if err != nil {
        panic(err)
    }
    claims := token.Claims.(jwt.MapClaims)
    for key, value := range claims {
        fmt.Printf("%s\t%v\n", key, value)
    }
}

func verify2(token string, keyset jwk.Set) {
    btoken := []byte(token)
    parsedToken, err := njwt.Parse(
        btoken, //token is a []byte
        njwt.WithKeySet(keyset),
        njwt.WithValidate(true),
    )
    fmt.Printf("%v %v", parsedToken, err)
}

func verify(tokenString string, keySet jwk.Set) (*jwt.Token, error) {
    tkn, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
        if token.Method.Alg() != jwa.RS256.String() {
            return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
        }
        kid, ok := token.Header["kid"].(string)
        if !ok {
            return nil, errors.New("kid header not found")
        }
        keys, ok := keySet.LookupKeyID(kid)
        if !ok {
            return nil, fmt.Errorf("key %v not found", kid)
        }
        var raw interface{}
        err := keys.Raw(&raw)
        return raw, err
    })
    return tkn, err
}

verify2(..)等于<nil> failed to match any of the keys,然后 verify(..)等于crypto/rsa: verification error

我的JWT标题:

{
  "typ": "JWT",
  "nonce": "...",
  "alg": "RS256",
  "x5t": "-KI3Q9nNR7bRofxmeZoXqbHZGew",
  "kid": "-KI3Q9nNR7bRofxmeZoXqbHZGew"
}

推荐答案

您使用的Azure AD访问令牌类型错误.那些在JWT头中带有现时值的API不是为您自己的API而设计的-它们是为Microsoft自己的API而设计的.

您需要公开一个API作用域来修复这个问题,之后您将获得一个访问令牌,该令牌在JWT标头中没有现时值.我的blog post有一些进一步的相关信息.

Go相关问答推荐

无法在Macos上使用Azure Speech golang SDK

如何使用Promela建模语言对Golang RWLock进行建模

即使HTTP服务器正在使用GO和Protobuf、SQL Server启动,请求也不返回结果

在整个SQL事务中将使用上下文作为默认设置吗?

go grpc:无法导入github.com/golang/protobuf/proto(没有所需的模块提供包github.com/gorang/protobuf-proto)

Go 中的sync.Cond 与 Wait 方法

在 go 中,将接收器 struct 从值更改为指针是否向后兼容?

Golang chromedp Dockerfile

如何为ANTLR4目标Go调试监听器

为什么 `append(x[:0:0], x...)` 将切片复制到 Go 中的新后备数组中?

Wire google Inject with multi return from provider 函数

速率限制特定端点

使用 Golang 在字符串中循环重复数据

为什么此代码在运行命令 error="exec: not started" 时出现错误?

如何使用 math/big 对 bigInt 进行取模?

函数调用中的类型参数panic

在 Go 中将指针传递给函数的正确方法是什么,以便我可以读取和/或修改指针表示的值?

Go 赋值涉及到自定义类型的指针

在 go (1.18) 的泛型上实现多态的最佳方法是什么?

将函数的值作为输入参数返回给另一个