У меня есть HTTP-сервер Go. Я хочу защитить свои маршруты с помощью токена 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"
}
У меня похожая проблема на другом языке. Моя ручная проверка токена работает для некоторых токенов. До меня дошло, что когда у меня есть претензия «nonce» в заголовке JWT, проверка не проходит, для других токенов, когда у меня ее нет, она работает. Не могли бы вы проверить с другим токеном, где у вас нет «одноразового номера»? (просто чтобы сузить проблему)
Вы используете неправильный тип маркера доступа Azure AD. Те, у кого есть одноразовый номер в заголовке JWT, не предназначены для проверки вашими собственными API — они предназначены для собственных API Microsoft.
Чтобы исправить это, вам нужно выставить область API, после чего вы получите токен доступа без одноразового номера в заголовке JWT. В моем сообщении в блоге есть дополнительная информация по теме.
Каждый раз, когда мы добавляем область для доступа к Microsoft graph API. Azure отправляет обратно access_token, который может быть проверен только Microsoft Graph API.
Альтернативный подход 1:
access_token
где-нибудьАльтернативный подход 2:
ПРИМЕЧАНИЕ. Не храните конфиденциальную информацию в заявках.
Комментарий владельца токенов 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