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

时间:2014-08-13 10:35:38

标签: c++ curl jwt

我仍然收到来自谷歌的“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;
}

1 个答案:

答案 0 :(得分:-1)

让JWT进行有点棘手(特别是在c / c ++中)。从编码,签名alg,json格式或甚至本地系统时钟未达到NTP时间的任何内容都可能导致通用invalid_grant,但请查看以下link是否有帮助。

(我想最好迟到而不是迟到)