Google API OAuth 2.0 CURL return "Required parameter missing: grant_type"

I am trying to authenticate Google OAuth 2.0 for a web server application.

I can get the code from Google in order, but when I send it back to try to get the access token, it always gives me the error "Required parameter missing: grant_type. Error 400", even though the grant_type file exists.

Also, if I specify the length of the content as nothing but 0, it causes other errors.

Here is the code that executes this curl:

$url = 'https://accounts.google.com/o/oauth2/token'; $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FAILONERROR, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/x-www-form-urlencoded', 'Content-length: 0' )); curl_setopt($ch, CURLOPT_POSTFIELDS, array( 'code='. urlencode($code), 'client_id=' . urlencode($clientID), 'client_secret=' . urlencode($clientSecret), 'redirect_uri=http%3A%2F%2Flocalhost%2Fexperiments%2FnewGALogin.php', 'grant_type=authorization_code' )); 
+4
source share
6 answers

to try

 curl_setopt($ch, CURLOPT_POSTFIELDS, array( 'code' => $code, 'client_id' => $clientID, 'client_secret' => $clientSecret, 'redirect_uri' => 'http%3A%2F%2Flocalhost%2Fexperiments%2FnewGALogin.php', 'grant_type' => 'authorization_code' )); 

or

 curl_setopt($ch, CURLOPT_POSTFIELDS, 'code=' . urlencode($code) . '&' . 'client_id=' . urlencode($clientID) . '&' . 'client_secret=' . urlencode($clientSecret) . '&' . 'redirect_uri=http%3A%2F%2Flocalhost%2Fexperiments%2FnewGALogin.php' . '&' . 'grant_type=authorization_code' ); 
+6
source

After investigating this problem, it looks like the grant_type array format is not accepted. (Yes, the query string method works, but it is messy to build.)

Adding http_build_query () to the array works if you are interested in storing the POST fields in the array.

 curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array( 'code' => $code, 'client_id' => $clientID, 'client_secret' => $clientSecret, 'redirect_uri' => 'http%3A%2F%2Flocalhost%2Fexperiments%2FnewGALogin.php', 'grant_type' => 'authorization_code' ))); 
+1
source

I tried to use the PHP code in the original question, plus the answers provided here, and continued to receive complaints from the Google token server about the lack of “grant_type”, although it was definitely transmitted. It turns out that the problem was CURLOPT_HTTPHEADER did not like / need "Content-length: 0". Hope this full working code saves someone else the same headache ...

 // This is what Google OAUTH server sends to you $code = $_GET['code']; // These come from your client_secret.json file $clientID = "your client id.apps.googleusercontent.com"; $clientSecret = "your client secret"; $redirectURI = "your redirect URI"; $token_uri = 'https://accounts.google.com/o/oauth2/token'; $ch = curl_init($token_uri); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FAILONERROR, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/x-www-form-urlencoded' )); // Build the URLEncoded post data $postFields = http_build_query(array( 'client_secret' => $clientSecret, 'grant_type' => 'authorization_code', 'redirect_uri' => $redirectURI, 'client_id' => $clientID, 'code' => $code )); curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields); $response = curl_exec($ch); // Save response, especially the "refresh_token" $pathToAccessToken = "/your/path/to/access_token.json"; file_put_contents($pathToAccessToken, $response); 

FYI, the JSON response looks something like this:

 { "access_token" : "xxxWhateverGibberish", "token_type" : "Bearer", "expires_in" : 3600, "refresh_token" : "yyyMoreGibberish" } 

After that, I was able to successfully complete the calendar request (the API area that my initial OAuth request accessed) using the following code:

 function getClient() { $client = new Google_Client(); $client->setApplicationName(APPLICATION_NAME); $client->setScopes(SCOPES); $client->setAuthConfigFile(CLIENT_SECRET_PATH); $client->setAccessType('offline'); // Load previously authorized credentials from a file. $pathToAccessToken = "/your/path/to/access_token.json"; $accessToken = file_get_contents($pathToAccessToken); $client->setAccessToken($accessToken); // Refresh the token if it expired. if ($client->isAccessTokenExpired()) { $client->refreshToken($client->getRefreshToken()); file_put_contents($pathToAccessToken, $client->getAccessToken()); } return $client; } $client = getClient(); $service = new Google_Service_Calendar($client); // Print the next 10 events on the user calendar. $calendarId = 'primary'; $optParams = array( 'maxResults' => 10, 'orderBy' => 'startTime', 'singleEvents' => TRUE, 'timeMin' => date('c'), ); $results = $service->events->listEvents($calendarId, $optParams); if (count($results->getItems()) == 0) { print "No upcoming events found.\n"; } else { print "Upcoming events:\n"; foreach ($results->getItems() as $event) { $start = $event->start->dateTime; if (empty($start)) { $start = $event->start->date; } printf("%s (%s)\n", $event->getSummary(), $start); } } 
+1
source

Read the CURLOPT_POSTFIELDS documentation CURLOPT_POSTFIELDS :

... as an array with the field name as the key and field data as the value

You are doing something, but not this. Try:

 curl_setopt($ch, CURLOPT_POSTFIELDS, array( 'code' => $code, 'client_id' => $clientID, ... 

In this case, you do not need urlencode .

0
source

I didn’t want to believe it, but, strangely enough, I simply switched from CURLOPT_POSTFIELDS from the array to the '&' concatenated string (with the same data!), Let my OAuth server finally recognize the grant_type type.

0
source

The main problem with the original question and some answers are the different values ​​accepted in the curl_setopt call when using the CURLOPT_POSTFIELDS key.

When the input is an array, the resulting Content-Type will be multipart/form-data , which does not meet the OAuth 2.0 specification, and the server will ignore it. When the input is a query string (for example, built using http_build_query ), Content-Type: will be application/x-www-form-urlencoded , which is what the specification requires.

See the "Notes" section at: http://php.net/manual/en/function.curl-setopt.php

0
source

Source: https://habr.com/ru/post/1382090/


All Articles