验证Auth0 ID令牌-我需要使用哪个秘密



我使用Auth0为用户生成JWT ID令牌。现在我想在我的go后端验证这个ID令牌。我只想要提取身份并检查它是否是由我的应用程序创建的在Auth0。

我正在使用chi路由器和jwtauth中间件。这是jwx的一个轻量级包装器。

文档说我应该做以下事情:

tokenAuth = jwtauth.New("RS256", []byte("secret"), nil)

我已经尝试了一些"保密"的东西,比如我的Auth0应用程序的客户端秘密或签名证书。但这些方法似乎都不起作用。我仔细检查了我是否使用了正确的签名算法。

结果总是token is unauthorized

r.Route("/users", func(r chi.Router) {
r.Use(jwtauth.Verifier(tokenAuth))
//r.Use(jwtauth.Authenticator)
r.Post("/info", usersService.InfoHandler)
})
在处理程序中,我尝试获取令牌:
token, _, err := jwtauth.FromContext(r.Context())
fmt.Println("token", token)
fmt.Println("error", err)

我现在已经创建了一个中间件来完成这个任务。它非常直接,我认为没有必要使用jwtauth中间件。

最好的方法似乎是使用JSON Web Key Set (JWKS)。它包含验证JWT的所有信息。
package auth0
import (
"context"
"fmt"
"github.com/lestrrat-go/jwx/jwk"
"github.com/lestrrat-go/jwx/jwt"
log "github.com/sirupsen/logrus"
"net/http"
)
var (
ErrInvalidToken = fmt.Errorf("invalid token")
ErrNoToken      = fmt.Errorf("no token found")
)
type middleware struct {
keySet   jwk.Set
audience string
issuer   string
}
type AuthUser struct {
ID    string `json:"id"`
Email string `json:"email"`
}
type userKeyType string
const userKey = userKeyType("user")
type Middleware interface {
AuthenticateUser(next http.Handler) http.Handler
}
var _ Middleware = &middleware{}
func NewMiddleware(issuer string, audience string) (middleware, error) {
// TODO implement auto rotation/refresh
keySet, err := jwk.Fetch(context.Background(), fmt.Sprintf("%s.well-known/jwks.json", issuer))
if err != nil {
return middleware{}, err
}
return middleware{
keySet:   keySet,
audience: audience,
issuer:   issuer,
}, nil
}
func (m *middleware) AuthenticateUser(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authHeader := r.Header.Get("Authorization")
if authHeader == "" {
log.Debug("no authorization header found")
http.Error(w, ErrNoToken.Error(), http.StatusForbidden)
return
}
bearerToken := authHeader[7:]
if bearerToken == "" {
log.Error("no bearer token found")
http.Error(w, ErrNoToken.Error(), http.StatusForbidden)
return
}
token, err := jwt.Parse([]byte(bearerToken), jwt.WithKeySet(m.keySet))
if err != nil {
log.Error("error parsing token")
http.Error(w, ErrInvalidToken.Error(), http.StatusForbidden)
return
}
if err := jwt.Validate(token,
jwt.WithAudience(m.audience),
jwt.WithIssuer(m.issuer)); err != nil {
log.Error("error validating token")
http.Error(w, ErrInvalidToken.Error(), http.StatusForbidden)
return
}
emailValue, ok := token.Get("email")
if !ok {
log.Error("error no email found")
http.Error(w, ErrInvalidToken.Error(), http.StatusForbidden)
return
}
email, ok := emailValue.(string)
if !ok {
log.Error("error email not a string")
http.Error(w, ErrInvalidToken.Error(), http.StatusForbidden)
return
}
if token.Subject() == "" && email == "" {
log.Error("error no subject or email found")
http.Error(w, ErrInvalidToken.Error(), http.StatusForbidden)
return
}
ctx := context.WithValue(r.Context(), userKey, AuthUser{
ID:    token.Subject(),
Email: email,
})
next.ServeHTTP(w, r.WithContext(ctx))
})
}
func GetUserFromContext(ctx context.Context) (AuthUser, error) {
user, ok := ctx.Value(userKey).(AuthUser)
if !ok {
return AuthUser{}, fmt.Errorf("could not get user from context")
}
return user, nil
}

最新更新