c++ - "invalid_grant"- 通过 C++ 中的 Google 服务帐户与 googleapi 日历交互

标签 c++ curl jwt

我仍然收到来自 google 的“invalig_grant:/。我放弃了。

我正在使用 C++ 中的服务帐户与 googleapi 日历进行交互(使用 curl)。 有一个代码:

调用登录函数:

loginService(
    "XXXXXXXXXXXXXXXXXXXXXXX@developer.gserviceaccount.com",
    "XXXXXXXXXXXXXX@gmail.com",
    "key.p12"
    );

有登录功能:

int loginService(const string &client_id,const string &user_id,const string &key_path){

Json::FastWriter writer;

Json::Value header;
header["alg"] = "RS256";
header["typ"] = "JWT";
string JWT_header = writer.write(header);

Json::Value claim;
int iat_time=time(NULL);
int exp_time = iat_time+3600;
claim["iss"] = client_id;
claim["scope"] = _api_url+"auth/calendar";
claim["sub"] = user_id;
claim["aud"] = "https://accounts.google.com/o/oauth2/token";
claim["exp"] = exp_time;
claim["iat"] = iat_time;
string JWT_claimSet = writer.write(claim);

JWT_header = base64_encode(JWT_header);
JWT_claimSet = base64_encode(JWT_claimSet);

if (JWT_header.find("=")!=string::npos) JWT_header.erase(JWT_header.find("="));
if (JWT_claimSet.find("=")!=string::npos) JWT_claimSet.erase(JWT_claimSet.find("="));

string signature = JWT_header+"."+JWT_claimSet;
string JWT_signature = signWithRsaSha256(signature,key_path);

JWT_signature = base64_encode(JWT_signature);

if (JWT_signature.find("=")!=string::npos) JWT_signature.erase(JWT_signature.find("="));

string assertion = JWT_header + "." + JWT_claimSet + "." + JWT_signature;
string post_data = "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=" + assertion;

curlPost("https://accounts.google.com/o/oauth2/token", post_data);

Json::Reader reader;
Json::Value data;
bool parsingSuccessful = reader.parse(_read_data, data);

return 0;
}

有散列函数:

string signWithRsaSha256(const string &input, const string &privateKey)
{

FILE *fp;
EVP_PKEY *pkey = 0;
EVP_MD_CTX *ctx = 0;
const EVP_MD *sha256Md = 0;
unsigned char sig[256];
unsigned int s(0);
PKCS12 *p12 = 0;
X509 *cert= 0;
string out;

OpenSSL_add_all_ciphers();
OpenSSL_add_all_digests();
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();

ctx = EVP_MD_CTX_create();
EVP_MD_CTX_init(ctx);
sha256Md = EVP_sha256(); 

try {
    EVP_SignInit(ctx, sha256Md);
    EVP_SignUpdate(ctx, input.c_str(), input.size());

    ERR_load_crypto_strings();
    if (!(fp = fopen(privateKey.c_str(), "rb"))) {
        cerr << "Error opening file "<< privateKey;
    }
    p12 = d2i_PKCS12_fp(fp, NULL);
    fclose (fp);
    if (!p12) {
        cerr << "Error reading PKCS#12 file\n";
    }

    if (!PKCS12_parse(p12, "notasecret", &pkey, &cert, NULL)) {
    cerr << "Error parsing PKCS#12 file\n";
    }

    s = EVP_PKEY_size(pkey);
    EVP_SignFinal(ctx, sig, &s, pkey);

    out=(char*)sig;

}
catch (const char *s)
{
    cerr << "ERROR: RSA SHA256 hashing failed: " <<s<< endl;
}

PKCS12_free(p12);
EVP_MD_CTX_destroy(ctx);
X509_free(cert);
EVP_cleanup();

return out;
}

和发布功能:

int curlPost(const string &url, const string &post_data)
{
_curl_handle = curl_easy_init();

curl_easy_setopt(_curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(_curl_handle, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(_curl_handle, CURLOPT_USERAGENT, MY_USER_AGENT);
curl_easy_setopt(_curl_handle, CURLOPT_WRITEFUNCTION, WriteFunction);
curl_easy_setopt(_curl_handle, CURLOPT_WRITEDATA, &_read_data);
curl_easy_setopt(_curl_handle, CURLOPT_WRITEHEADER, &_read_header);
curl_easy_setopt(_curl_handle, CURLOPT_URL, url.c_str());
curl_easy_setopt(_curl_handle, CURLOPT_POST, 1);
curl_easy_setopt(_curl_handle, CURLOPT_POSTFIELDS, post_data.c_str());

_curl_result = curl_easy_perform(_curl_handle);

curl_easy_cleanup(_curl_handle);

return 0;
}

最佳答案

让 JWT 运行起来有点棘手(尤其是在 c/c++ 中)。从编码、签名 alg、json 格式或者即使您的本地系统时钟不是 NTP 时间同步的任何内容都可能导致通用 invalid_grant 但是,请查看以下内容是否 link有帮助。

(我想晚发总比不发好)

关于c++ - "invalid_grant"- 通过 C++ 中的 Google 服务帐户与 googleapi 日历交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25283955/

相关文章:

php - 通过 Youtube API 上传大视频导致内存不足

.net - 如何使用服务帐户向Google v3 api进行身份验证

java - JWT 签名验证

spring-boot - Spring 5 + WebFlux 安全性 + JWT token

c++ - cuda 共享库链接 : undefined reference to cudaRegisterLinkedBinary

c++ - Constexpr:与 nullptr 的比较 - 错误或功能?

c++ - 在代码体内定义仿函数

c++ - nvcc、gcc、clang 和 msvc "respect"在结构中使用 __restrict__ 关键字吗?

json - Keycloak:验证访问 token 并获取 keycloak ID

php - CURL 或 file_get_contents 来更新提要列表?