Azure JWT在Go中的验证不起作用

huangapple go评论93阅读模式
英文:

Azure JWT verification in Go is not working

问题

我有一个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)
	// 验证set是否具有所需的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(..) 返回 &lt;nil&gt; failed to match any of the keys,而
verify(..) 返回 crypto/rsa: verification error

我的JWT头部:

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

I have a Go HTTP Server. I want to protect my routes using Azure JWT Token. I am able to generate the token but I am not able to verify it.

This is how I am doing it:

package main
import (
&quot;context&quot;
&quot;errors&quot;
&quot;fmt&quot;
&quot;github.com/dgrijalva/jwt-go&quot;
&quot;github.com/lestrrat-go/jwx/jwa&quot;
&quot;github.com/lestrrat-go/jwx/jwk&quot;
njwt &quot;github.com/lestrrat-go/jwx/jwt&quot;
)
const token = &quot;&lt;access-token&gt;&quot;
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(&quot;%s\t%v\n&quot;, 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(&quot;%v %v&quot;, 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(&quot;unexpected signing method: %v&quot;, token.Header[&quot;alg&quot;])
}
kid, ok := token.Header[&quot;kid&quot;].(string)
if !ok {
return nil, errors.New(&quot;kid header not found&quot;)
}
keys, ok := keySet.LookupKeyID(kid)
if !ok {
return nil, fmt.Errorf(&quot;key %v not found&quot;, kid)
}
var raw interface{}
err := keys.Raw(&amp;raw)
return raw, err
})
return tkn, err
}

verify2(..) gives &lt;nil&gt; failed to match any of the keys and
verify(..) gives crypto/rsa: verification error

my JWT header:

{
&quot;typ&quot;: &quot;JWT&quot;,
&quot;nonce&quot;: &quot;...&quot;,
&quot;alg&quot;: &quot;RS256&quot;,
&quot;x5t&quot;: &quot;-KI3Q9nNR7bRofxmeZoXqbHZGew&quot;,
&quot;kid&quot;: &quot;-KI3Q9nNR7bRofxmeZoXqbHZGew&quot;
}

答案1

得分: 3

你正在使用错误类型的Azure AD访问令牌。带有JWT头部中的nonce的令牌不是用于验证你自己的API的,而是用于Microsoft自己的API。

你需要公开一个API范围来解决这个问题,之后你将获得一个JWT头部中没有nonce的访问令牌。我的博客文章中有一些相关的进一步信息。

英文:

You are using the wrong type of Azure AD access token. Those with a nonce in the JWT header are not designed to be validated by your own APIs - they are intended for Microsoft's own APIs.

You need to expose an API scope to fix this, after which you will get an access token without a nonce in the JWT header. My blog post has some further related info.

答案2

得分: 2

我在另一种语言中遇到了类似的问题。我的手动令牌验证对于某些令牌有效。我注意到,当JWT头部中有"nonce"声明时,验证失败,而当没有该声明时,其他令牌可以正常工作。你可以尝试使用另一个没有"nonce"的令牌来检查一下吗?这样可以缩小问题的范围。

英文:

I have similar problem in another language. My manual token verification works for some tokens. It came to my attention that when I have the "nonce" claim on the JWT header, validation fails, for other tokens when I don't have it, it works. May you please check with another token where you don't have the "nonce"? (just to narrow down the problem)

答案3

得分: 0

每当我们添加一个范围来访问Microsoft Graph API时,Azure会返回一个只能由Microsoft Graph API验证的访问令牌。

替代方法1:

  • 在后端签署自己的JWT以授权前端请求
  • access_token存储在某个地方

替代方法2:

  • 调用Graph API并使用声明签署一个JWT
  • 在前端和后端之间验证和使用JWT

**注意:**不要在声明中存储敏感信息

Microsoft的OAuth令牌所有者对此发表了评论:https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609#issuecomment-524434987

了解更多关于Azure OIDC的信息:https://xsreality.medium.com/making-azure-ad-oidc-compliant-5734b70c43ff

英文:

Anytime we add a scope to access Microsoft graph API. Azure sends back an access_token that can only be verified by Microsoft graph API.

Alternative approach 1:

  • Sign my own JWT to authorize my front-end requests in the back-end
  • Store the access_token somewhere

Alternative approach 2:

  • Make a call to graph API and sign a JWT with the claims
  • Verify and use the JWT between your FE and BE

NOTE: Do not do store sensitive information in the claims

Microsoft's OAuth tokens owner comment about this: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609#issuecomment-524434987

Learn more about Azure OIDC: https://xsreality.medium.com/making-azure-ad-oidc-compliant-5734b70c43ff

huangapple
  • 本文由 发表于 2023年4月13日 12:19:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76001593.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定