Googleからアクセストークンを取得したい。 Google APIによると アクセストークンを取得し、コードおよびその他のパラメーターをトークン生成ページに送信すると、応答は次のようなJSONオブジェクトになります。
{
"access_token" : "ya29.AHES6ZTtm7SuokEB-RGtbBty9IIlNiP9-eNMMQKtXdMP3sfjL1Fc",
"token_type" : "Bearer",
"expires_in" : 3600,
"refresh_token" : "1/HKSmLFXzqP0leUihZp2xUt3-5wkU7Gmu2Os_eBnzw74"
}
ただし、更新トークンを受け取っていません。私の場合の応答は次のとおりです。
{
"access_token" : "ya29.sddsdsdsdsds_h9v_nF0IR7XcwDK8XFB2EbvtxmgvB-4oZ8oU",
"token_type" : "Bearer",
"expires_in" : 3600
}
refresh_token
は、ユーザーからの最初の承認時にのみ提供されます。 OAuth2統合のテスト中に行う種類などの後続の承認は、refresh_token
を再度返しません。 :)
refresh_token
を返します。または、クエリパラメーターPrompt=consent
をOAuthリダイレクトに追加できます(Googleの Webサーバーアプリケーション用のOAuth 2. ページを参照)。
これにより、ユーザーにアプリケーションを再度承認するよう求められ、常にrefresh_token
が返されます。
リフレッシュトークンを取得するには、approval_Prompt=force
とaccess_type="offline"
の両方を追加する必要があります。Googleが提供するJavaクライアントを使用している場合、次のようになります。
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT, JSON_FACTORY, getClientSecrets(), scopes)
.build();
AuthorizationCodeRequestUrl authorizationUrl =
flow.newAuthorizationUrl().setRedirectUri(callBackUrl)
.setApprovalPrompt("force")
.setAccessType("offline");
私は長い夜を捜しました、そして、これはトリックをしています:
Admin-sdkから変更されたuser-example.php
$client->setAccessType('offline');
$client->setApprovalPrompt('force');
$authUrl = $client->createAuthUrl();
echo "<a class='login' href='" . $authUrl . "'>Connect Me!</a>";
次に、リダイレクトURLでコードを取得し、コードで認証してリフレッシュトークンを取得します
$client()->authenticate($_GET['code']);
echo $client()->getRefreshToken();
今すぐ保存する必要があります;)
アクセスキーがタイムアウトしたら
$client->refreshToken($theRefreshTokenYouHadStored);
これにより混乱が生じたので、難しい方法を学ぶために私が来たものを共有すると思いました。
access_type=offline
およびapproval_Prompt=force
パラメーターを使用してアクセスを要求すると、accessトークンとrefreshトークンの両方を受け取る必要があります。 accessトークンは、受け取った後すぐに期限切れになり、更新する必要があります。
新しいaccessトークンを取得する要求を正しく行い、新しいaccessトークンを含む応答を受け取りました。また、新しいrefreshトークンを取得しなかったという事実にも混乱しました。ただし、これは、同じrefreshトークンを何度も使用できるためです。
他の答えのいくつかは、何らかの理由で新しいrefreshトークンを取得したいと考えており、ユーザーを再承認することを示唆していると思いますが、実際には、 refreshトークンはユーザーによって取り消されるまで機能します。
Rich Suttonの答えaccess_type=offline
の追加がフロントエンドクライアントの認証要求で行われたことに気付いた後、ようやく機能しましたコード、notそのコードをaccess_tokenに交換するバックエンド要求。私は彼の答えにコメントを追加しました Googleのこのリンク トークンの更新の詳細について。
追伸Satellizerを使用している場合は、 AngularJSの$ authProvider.googleにそのオプションを追加する方法はこちら です。
これを設定すると、更新トークンが毎回送信されます。
$client->setApprovalPrompt('force');
以下に例を示します(php):
$client = new Google_Client();
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setRedirectUri($redirect_uri);
$client->addScope("email");
$client->addScope("profile");
$client->setAccessType('offline');
$client->setApprovalPrompt('force');
1。 'refresh_token'を取得するには?
Solution:authURLを生成するときは、access_type = 'offline'オプションを使用する必要があります。 source: WebサーバーアプリケーションにOAuth 2.0を使用
2。しかし、「access_type = offline」を使用しても、「refresh_token」は取得されませんか?
解決策:最初のリクエストでのみ取得できることに注意してください。前回の有効期限が切れた後に新しいaccess_tokenを取得する際のコード、およびこの値を上書きしないようにしてください。
Google Auth Docから:(この値= access_type)
この値は、アプリケーションがトークンの認証コードを初めて交換するときに、更新トークンとアクセストークンを返すようにGoogle認証サーバーに指示します。
再度「refresh_token」が必要な場合は、 Rich Sutton's answer に記載されている手順に従って、アプリへのアクセスを削除する必要があります。
refresh_token
を取得するには、OAuthリクエストURLにaccess_type=offline
を含める必要があります。ユーザーが初めて認証されると、nil以外のrefresh_token
と期限切れのaccess_token
が返されます。
既に認証トークンを持っているアカウントをユーザーが再認証する可能性がある場合(上記の@SsjCostyの言及のように)、トークンがどのアカウントのアカウントであるかについてGoogleから情報を取得する必要があります。それには、スコープにprofile
を追加します。 OAuth2 Ruby gemを使用すると、最終的なリクエストは次のようになります。
client = OAuth2::Client.new(
ENV["GOOGLE_CLIENT_ID"],
ENV["GOOGLE_CLIENT_SECRET"],
authorize_url: "https://accounts.google.com/o/oauth2/auth",
token_url: "https://accounts.google.com/o/oauth2/token"
)
# Configure authorization url
client.authorize_url(
scope: "https://www.googleapis.com/auth/analytics.readonly profile",
redirect_uri: callback_url,
access_type: "offline",
Prompt: "select_account"
)
スコープには2つのスペース区切りのエントリがあり、1つはGoogleアナリティクスへの読み取り専用アクセス用で、もう1つはprofile
であり、これはOpenID Connect標準です。
これにより、Googleはid_token
応答でget_token
という追加の属性を提供します。 id_tokenから情報を取得するには、Googleドキュメントで このページをチェックアウト します。これを検証して「デコード」するGoogle提供のライブラリがいくつかあります(Ruby google-id-token gem を使用しました)。解析されると、sub
パラメーターは実質的に一意のGoogleアカウントIDになります。
注目に値するのは、スコープをchangeすると、元のスコープで既に認証されているユーザーの更新トークンを再度取得することです。これは、たとえば、既に多数のユーザーがいて、すべてのユーザーがGoogleでアプリを認証しないようにしたくない場合に便利です。
ああ、最後の注意点:needPrompt=select_account
は必要ありませんが、ユーザーがもっと多くで認証したい状況がある場合に便利です1つのGoogleアカウント(つまり、サインイン/認証にこれを使用していない)。
私にとっては、Googleが提供するCalendarSampleServlet
を試していました。 1時間後にaccess_keyがタイムアウトし、401ページへのリダイレクトがあります。上記のすべてのオプションを試しましたが、機能しませんでした。最後に 'AbstractAuthorizationCodeServlet'のソースコードを確認すると、資格情報が存在する場合はリダイレクトが無効になることがわかりましたが、理想的にはrefresh token!=null
を確認する必要があります。以下のコードをCalendarSampleServlet
に追加しましたが、その後機能しました。何時間ものフラストレーションの後の大きな安心ああ、助かった。
if (credential.getRefreshToken() == null) {
AuthorizationCodeRequestUrl authorizationUrl = authFlow.newAuthorizationUrl();
authorizationUrl.setRedirectUri(getRedirectUri(req));
onAuthorization(req, resp, authorizationUrl);
credential = null;
}
#!/usr/bin/env Perl
use strict;
use warnings;
use 5.010_000;
use utf8;
binmode STDOUT, ":encoding(utf8)";
use Text::CSV_XS;
use FindBin;
use lib $FindBin::Bin . '/../lib';
use Net::Google::Spreadsheets::V4;
use Net::Google::DataAPI::Auth::OAuth2;
use lib 'lib';
use Term::Prompt;
use Net::Google::DataAPI::Auth::OAuth2;
use Net::Google::Spreadsheets;
use Data::Printer ;
my $oauth2 = Net::Google::DataAPI::Auth::OAuth2->new(
client_id => $ENV{CLIENT_ID},
client_secret => $ENV{CLIENT_SECRET},
scope => ['https://www.googleapis.com/auth/spreadsheets'],
);
my $url = $oauth2->authorize_url();
# system("open '$url'");
print "go to the following url with your browser \n" ;
print "$url\n" ;
my $code = Prompt('x', 'paste code: ', '', '');
my $objToken = $oauth2->get_access_token($code);
my $refresh_token = $objToken->refresh_token() ;
print "my refresh token is : \n" ;
# debug p($refresh_token ) ;
p ( $objToken ) ;
my $gs = Net::Google::Spreadsheets::V4->new(
client_id => $ENV{CLIENT_ID}
, client_secret => $ENV{CLIENT_SECRET}
, refresh_token => $refresh_token
, spreadsheet_id => '1hGNULaWpYwtnMDDPPkZT73zLGDUgv5blwJtK7hAiVIU'
);
my($content, $res);
my $title = 'My foobar sheet';
my $sheet = $gs->get_sheet(title => $title);
# create a sheet if does not exit
unless ($sheet) {
($content, $res) = $gs->request(
POST => ':batchUpdate',
{
requests => [
{
addSheet => {
properties => {
title => $title,
index => 0,
},
},
},
],
},
);
$sheet = $content->{replies}[0]{addSheet};
}
my $sheet_prop = $sheet->{properties};
# clear all cells
$gs->clear_sheet(sheet_id => $sheet_prop->{sheetId});
# import data
my @requests = ();
my $idx = 0;
my @rows = (
[qw(name age favorite)], # header
[qw(tarou 31 curry)],
[qw(jirou 18 gyoza)],
[qw(saburou 27 ramen)],
);
for my $row (@rows) {
Push @requests, {
pasteData => {
coordinate => {
sheetId => $sheet_prop->{sheetId},
rowIndex => $idx++,
columnIndex => 0,
},
data => $gs->to_csv(@$row),
type => 'PASTE_NORMAL',
delimiter => ',',
},
};
}
# format a header row
Push @requests, {
repeatCell => {
range => {
sheetId => $sheet_prop->{sheetId},
startRowIndex => 0,
endRowIndex => 1,
},
cell => {
userEnteredFormat => {
backgroundColor => {
red => 0.0,
green => 0.0,
blue => 0.0,
},
horizontalAlignment => 'CENTER',
textFormat => {
foregroundColor => {
red => 1.0,
green => 1.0,
blue => 1.0
},
bold => \1,
},
},
},
fields => 'userEnteredFormat(backgroundColor,textFormat,horizontalAlignment)',
},
};
($content, $res) = $gs->request(
POST => ':batchUpdate',
{
requests => \@requests,
},
);
exit;
#Google Sheets API, v4
# Scopes
# https://www.googleapis.com/auth/drive View and manage the files in your Google D# # i# rive
# https://www.googleapis.com/auth/drive.file View and manage Google Drive files and folders that you have opened or created with this app
# https://www.googleapis.com/auth/drive.readonly View the files in your Google Drive
# https://www.googleapis.com/auth/spreadsheets View and manage your spreadsheets in Google Drive
# https://www.googleapis.com/auth/spreadsheets.readonly View your Google Spreadsheets
私の解決策は少し奇妙でした。インターネットで見つけたすべての解決策を試しましたが、何もしませんでした。驚いたことにこれは機能しました。credentials.jsonを削除し、更新し、アカウントでアプリを再度認証します。新しいcredentials.jsonファイルには更新トークンが含まれます。このファイルをどこかにバックアップします。その後、トークンの更新エラーが再び発生するまでアプリを使用し続けます。エラーメッセージのみが表示されたcrendetials.jsonファイルを削除し(これは私の場合はこのようになっています)、古い資格情報ファイルをフォルダーに貼り付けます。完了です! iveがこれを行ってから1週間が経過し、問題はありませんでした。
現在、Googleは私のリクエストでこれらのパラメータを拒否しました(access_type、Prompt)... :(そして「Revoke Access」ボタンはまったくありません。refresh_tokenlolを取り戻すためにイライラしています
更新:私はここで答えを見つけました:Dリクエストでリフレッシュトークンを取得できます https://developers.google.com/identity/protocols/OAuth2WebServer
curl -H "Content-type:application/x-www-form-urlencoded"\ https://accounts.google.com/o/oauth2/revoke?token= {token}
トークンは、アクセストークンまたは更新トークンにすることができます。トークンがアクセストークンであり、対応する更新トークンがある場合、更新トークンも取り消されます。
失効が正常に処理された場合、応答のステータスコードは200です。エラー状態の場合、エラーコードと共にステータスコード400が返されます。
オフラインアクセスおよびPrompt:consentを使用するとうまくいきました。
auth2 = gapi.auth2.init({
client_id: '{cliend_id}'
});
auth2.grantOfflineAccess({Prompt:'consent'}).then(signInCallback);
認証のたびに新しいrefresh_tokenを取得するには、ダッシュボードで作成されるOAuth 2.0資格情報のタイプが「その他」である必要があります。また、前述のように、authURLを生成するときにaccess_type = 'offline'オプションを使用する必要があります。
「Webアプリケーション」タイプの資格情報を使用する場合、Prompt/approval_Prompt変数の組み合わせは機能しません。最初の要求でのみrefresh_tokenを取得できます。