去验证访问令牌(keycloak)

问题描述 投票:0回答:1

我正在尝试使用 GO 实现访问令牌验证。但我在网上看到的例子似乎只是用 TOKEN_SECRET 来验证它。但是我习惯了在Java spring中编程,并且不需要使用TOKEN_SECRET。我只是提供 jwk-set-uri 并检查有效性(自动 - 安全过滤器等)我知道它与 oauth 服务器通信并进行此验证。

Go 中是否没有库可以检查向 oauth 服务器发出请求时令牌是否有效?

我知道我可以通过向 oauth 服务器的用户信息端点发出请求来手动进行操作:

http://localhost:8080/auth/realms/<your_realm>/protocol/openid-connect/userinfo

(在具有密钥授权的标头中包含令牌)

但我不知道这是否完全符合标准。

正确的做法是什么?

go oauth-2.0 oauth keycloak
1个回答
0
投票

简短回答:使用 go-oidc

长答案: 首先,让我们了解 Spring Security 如何自动验证 JWT 访问令牌。按照惯例,如果您在

application.yaml
配置文件中定义 OAuth 2.0 或 OIDC 客户端属性,Spring 将自动在安全过滤器链中连接一个过滤器,从 Keycloak 中获取
jwk-set
,这是一组与私钥对应的公钥Keycloak 使用它来签署令牌。该过滤器将应用于所有受保护的路由,并且 spring 将使用公钥来检查令牌的签名是否有效,并在适用时进行额外的检查(受众、超时等...)

那么我们如何在 Go 中做到这一点呢?我们可以编写一个简单的中间件来接受

jwk-set
并使用它来验证令牌。您需要解码令牌,确认
iss
sub
声明,以确保它来自受信任的发行者并且针对目标受众,检查它是否尚未过期,然后检查
alg
声明以了解哪个使用了签名算法,从
jwk-set
中选择相应的公钥并检查签名是否有效。

func JWTMiddleware(jwkSet map[string]*rsa.PublicKey) func(http.Handler) http.Handler {
    return func(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            authHeader := r.Header.Get("Authorization")
            if authHeader == "" {
                http.Error(w, "Authorization header is required", http.StatusUnauthorized)
                return
            }

            tokenString := strings.TrimPrefix(authHeader, "Bearer ")
            token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
                if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
                    return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
                }

                alg := token.Method.Alg()
                publicKey, ok := jwkSet[alg]
                if !ok {
                    return nil, fmt.Errorf("no key found for signing method: %v", alg)
                }
                return publicKey, nil
            })
            // Other checks, ISS, Aud, Expirey etc ...

            if err != nil || !token.Valid {
                http.Error(w, "Invalid token", http.StatusUnauthorized)
                return
            }

            next.ServeHTTP(w, r)
        })
    }
}

© www.soinside.com 2019 - 2024. All rights reserved.