1

ストレージ API の API リクエスト (GET バケット) を作成しています。必須パラメーターの 1 つは「Authorization」ヘッダーです。

API へのアクセスにサービス アカウントを使用していることに注意してください。

ドキュメントhttps://developers.google.com/accounts/docs/OAuth2ServiceAccountに従って「Authorization」ヘッダーのアクセス トークンを取得し、承認済みのリクエストを REST API に送信できるようにしました。問題は、常に「invalid_grant」エラーが発生することです。

次のコードを使用して確認してください。

<?php
error_reporting(E_ERROR);

const CLIENT_ID = 'XXXXXXXXXXXX.apps.googleusercontent.com';
const SERVICE_ACCOUNT = 'XXXXXXXXXXXX@developer.gserviceaccount.com';
const KEY_FILE = 'XXX.p12';

function get_oauth_access_token()
{
    $header[alg] = 'RS256';
    $header[typ] = 'JWT';

    $header = urlencode(base64_encode(utf8_encode(json_encode($header))));

    $assertion_time = time();

    $claim[iss] = CLIENT_ID; //also tried SERVICE_ACCOUNT here, no improvement
    $claim[scope] = 'https://www.googleapis.com/auth/devstorage.read_only';
    $claim[aud] = 'https://accounts.google.com/o/oauth2/token';
    $claim[exp] = $assertion_time + 3600;
    $claim[iat] = $assertion_time;

    $claim = urlencode(base64_encode(utf8_encode(json_encode($claim))));

    $data = $header . '.' . $claim;

    $p12 = file_get_contents(KEY_FILE);
    $cert = array();
    openssl_pkcs12_read($p12, $cert, 'notasecret');
    $priv_key_id = openssl_get_privatekey($cert[pkey]);

    openssl_sign($data, $signature, $priv_key_id, 'sha256');

    $signature = urlencode(base64_encode($signature));

    $assertion = $data . '.' . $signature;

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'https://accounts.google.com/o/oauth2/token');
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, array('grant_type'=>'assertion', 
                                               'assertion_type'=>'http://oauth.net/grant_type/jwt/1.0/bearer', 
                                               'assertion'=>$assertion));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);


    $result = curl_exec($ch);
    $error = curl_error($ch);

    curl_close($ch);
    var_dump($result);
    var_dump($error);
}

get_oauth_access_token();

このコードに「invalid_grant」エラーの原因となる何か問題がありますか?

4

4 に答える 4

2

問題はサーバーの時間かもしれません。

Google Analytics で問題が発生しました。コードはすべて正しいのですが、サーバーの時刻が Google の時刻よりも数秒進んでいます。テストを行うために、サーバーの時間を数分遅らせることができます。

それが機能する場合は、たとえばNTPを使用して、サーバーの時計を正確に保つことができます。

于 2012-08-16T14:28:09.450 に答える
0

これは、Google CloudStorageのRESTfulHTTPインターフェースでのサービスアカウントの使用を示す簡単なPHPプログラムです。このコードをサービスアカウントでテストしましたが、正常に機能しているようです。ご不明な点がございましたら、お気軽にお問い合わせください。

<?php

require_once 'apiClient.php';

// Define constants.
const CLIENT_ID = 'YOUR_CLIENT_ID_GOES_HERE';
const SERVICE_ACCOUNT_NAME = 'YOUR_SERVICE_ACCOUNT_NAME_GOES_HERE';
const KEY_FILE = 'key.p12';
const BUCKET = 'marc-us';

// Obtain OAuth 2.0 access token for service account.
$client = new apiClient();
$key = file_get_contents(KEY_FILE);
$client->setAssertionCredentials(new apiAssertionCredentials(
  SERVICE_ACCOUNT_NAME,
  array('https://www.googleapis.com/auth/devstorage.full_control'),
  $key)
);
$client::$auth->refreshTokenWithAssertion();
$json = $client->getAccessToken();
$accessToken = json_decode($json)->access_token;

// Add access token to Authorization header of HTTP request.
$ch = curl_init('http://commondatastorage.googleapis.com/' . BUCKET);
curl_setopt($ch, CURLOPT_HTTPHEADER, 
            array('Authorization: OAuth ' . $accessToken));
$resp = curl_exec($ch);
curl_close($ch);

// Display results.
print '<h2>Response:</h2><pre>' . $resp . '</pre>';
?>
于 2012-06-15T16:06:50.837 に答える
0

私の最後の応答のコードは私にとってはうまく機能するので、環境問題に直面していると思われます. とにかく、Google PHP クライアント ライブラリの所有者に相談したところ、内部の refreshTokenWithAssertion() メソッドの呼び出しに頼らずにアクセス トークンを更新するためのより良い方法が提供されました。彼はこのテクニックを提案しました:

  $req = new apiHttpRequest(YOUR_URL);
  $val = $client->getIo()->authenticatedRequest($req);

authenticatedRequest() の呼び出しは、必要に応じてアクセス トークン (設定されている場合はアサーション資格情報を含む) を更新します。このアプローチを使用するように上記のコードを変更しましたが、問題なく動作します。古いバージョンと新しいバージョンの両方が機能するため、機能的な違いはありませんが、内部呼び出しを回避し、curl の代わりに Google PHP クライアント ライブラリを使用してリクエストを実行し、結果がはるかに短いため、新しいバージョンの方が優れていると思います。よりシンプルなコード。

<?php

require_once 'apiClient.php';

// Define constants.
const SERVICE_ACCOUNT_NAME = 'YOUR_SERVICE_ACCOUNT_NAME';
const KEY_FILE = 'key.p12';
const BUCKET = 'marc-us';

// Obtain service account credentials assertion.
$client = new apiClient();
$key = file_get_contents(KEY_FILE);
$client->setAssertionCredentials(new apiAssertionCredentials(
  SERVICE_ACCOUNT_NAME,
  array('https://www.googleapis.com/auth/devstorage.full_control'),
  $key)
);

// Create HTTP request, authorize and execute.
$req = new apiHttpRequest('http://commondatastorage.googleapis.com/' . BUCKET);
$resp = $client::getIo()->authenticatedRequest($req);

// Display results.
print '<h2>Response:</h2>' . $resp->getResponseBody();

?>
于 2012-06-16T17:43:00.773 に答える