reactjs之发送到我的服务器时,“使用Google登录” JWT无效

arxive 阅读:95 2025-06-02 22:19:02 评论:0

设置:React前端和Golang后端。
我的React前端成功从Google获得了 token :

<GoogleLogin 
   clientId="<client-id>.apps.googleusercontent.com" 
   onSuccess={response => responseGoogle(response)} 
> 
</GoogleLogin> 
我有一个突变,可以发送我需要的信息:
initiateTestMutation({ 
 variables: { 
    idToken: response.getAuthResponse().id_token, 
    email: response.profileObj.email, 
    givenName: response.profileObj.givenName, 
    familyName: response.profileObj.familyName, 
 } 
} 
然后,它发送一个我可以用jwt.io解码的 token ,但它显示“无效签名”。它包含我的正确信息,但同样无效。
在服务器端,我也尝试对其进行验证,但失败了。
// This is the token as a string 
unencodedToken := *input.IDToken 
fmt.Println(unencodedToken) 
token, err := jwt.Parse(unencodedToken, func(token *jwt.Token) (interface{}, error){ 
    return []byte("What goes here?"), nil 
}) 
if err != nil { 
    fmt.Println("Could not decode the token") 
    fmt.Println(err) 
} 
if token.Valid { 
    fmt.Println("Valid token") 
} else if ve, ok := err.(*jwt.ValidationError); ok { 
    if ve.Errors&jwt.ValidationErrorMalformed != 0 { 
        fmt.Println("That's not even a token") 
    } else if ve.Errors&(jwt.ValidationErrorExpired|jwt.ValidationErrorNotValidYet) != 0 { 
        // Token is either expired or not active yet 
        fmt.Println("Expired token") 
    } else { 
        fmt.Println("Couldn't handle this token:", err) 
    } 
} else { 
    fmt.Println("Couldn't handle this token:", err) 
} 
其他资讯:
  • 全部在本地完成。 app.localhost是请求JWT的域,它被添加为批准的来源
  • 请您参考如下方法:

    接近:https://stackoverflow.com/a/61718113/12563520
    我们的 friend here写了如何正确验证JWT。

     
    token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { 
        token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { 
        if _, ok := token.Method.(*jwt.SigningMethodRS256); !ok { 
            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 := keySet.LookupKeyID(kid); 
        if len(keys) == 0 { 
             return nil, fmt.Errorf("key %v not found", kid) 
        } 
        // keys[0].Materialize() doesn't exist anymore 
        var raw interface{} 
        return raw, keys[0].Raw(&raw) 
    }) 
    
    这是我的完整实现,以满足Google从此处提供的说明: https://developers.google.com/identity/sign-in/web/backend-auth
    我可能需要验证的次数比我需要的要多,因此,如果有人要编辑或评论,我会进行更改。
    // Get the Key 
        unencodedToken := *input.IDToken 
        fetchedToken, err := jwk.FetchHTTP("https://www.googleapis.com/oauth2/v3/certs") 
     
        // Parse the token with standard claims 
        token, err := jwt.ParseWithClaims(unencodedToken, &jwt.StandardClaims{}, func(token *jwt.Token) (interface{}, error) { 
            if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { 
                return nil, gqlerror.Errorf("Unexpected token signing method", token) 
            } 
            kid, ok := token.Header["kid"].(string) 
            if !ok { 
                fmt.Println("Could not find Key ID") 
                return nil, gqlerror.Errorf("Could not find key ID in token:", token) 
            } 
            keys := fetchedToken.LookupKeyID(kid) 
            if len(keys) == 0 { 
                fmt.Println("Could not find key in the signature") 
                return nil, gqlerror.Errorf("Could not find key in the signature: ", token) 
            } 
            var empty interface{} 
            return empty, keys[0].Raw(&empty) 
        }) 
        if err != nil { 
            fmt.Println("Could not decode the token") 
            fmt.Println(err) 
            return nil, gqlerror.Errorf("Could not decode the token: ", token) 
        } 
        // Check if the token is valid 
        if token.Valid { 
            fmt.Println("Valid token") 
        } else if ve, ok := err.(*jwt.ValidationError); ok { 
            if ve.Errors&jwt.ValidationErrorMalformed != 0 { 
                fmt.Println("That's not even a token") 
                return nil, gqlerror.Errorf("Invalid Token") 
            } else if ve.Errors&(jwt.ValidationErrorExpired|jwt.ValidationErrorNotValidYet) != 0 { 
                // Token is either expired or not active yet 
                fmt.Println("Expired token") 
                return nil, gqlerror.Errorf("Expired Token:", token) 
            } else { 
                fmt.Println("Couldn't handle this token", token, err) 
                return nil, gqlerror.Errorf(err.Error()) 
            } 
        } else { 
            fmt.Println("Couldn't handle this token", token, err) 
            return nil, gqlerror.Errorf(err.Error()) 
        } 
        // Check if the claims are valid 
        err = token.Claims.Valid() 
        if err != nil { 
            fmt.Println("Failed validity check", err) 
            return nil, gqlerror.Errorf("Failed validity check on token", token, err.Error()) 
        } 
        // Check the custom claims 
        if claims, ok := token.Claims.(*jwt.StandardClaims); ok && token.Valid { 
            audienceVerified := claims.VerifyAudience("773117128619-kfrd500nf8bfaq7anl7ee1ae7ucg5kp5.apps.googleusercontent.com", true) 
            if !audienceVerified { 
                // TODO Handle failure 
                fmt.Println("Audience unverified") 
                return nil, gqlerror.Errorf("Audience unverified on token", token) 
            } 
        } 
     
        if claims, ok := token.Claims.(*jwt.StandardClaims); ok && token.Valid { 
            netloc := claims.VerifyIssuer("accounts.google.com", true) 
            httpVersion := claims.VerifyIssuer("accounts.google.com", true) 
            if !netloc && !httpVersion { 
                // TODO Handle failure 
                fmt.Println("Can't verify issuer") 
                return nil, gqlerror.Errorf("Can't verify issuer on token", token) 
            } 
        } 
    


    标签:React
    声明

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    关注我们

    一个IT知识分享的公众号