PROBLEM SOLVED
Finally, I get the refresh_token, by revoking from google account(aka remove the apps access through account).
Everything goes normal again, and I don't need to solve the problem as the title 'Get Google access token not through the browser'.
But why I success this time? Because this time I use curl
but not thephpleague/oauth2-client
way to request auth. I think there must missing some parms when I request auth via thephpleague/oauth2-client
.
Here is a curl
way that I get the refresh_token EVERYTIME after I revoke/remove the apps access from account.
<?
//Reference to dbjpanda/google-api.php(https://gist.github.com/dbjpanda/0ba3d73832b25d720398e8f1dce1359b)
$client_id = 'xxx.apps.googleusercontent.com';
$client_secret = 'xxxx';
$redirect_uri = 'https://example.com/get_token.php';
$end_point = 'https://accounts.google.com/o/oauth2/v2/auth';
$token_file="my-token.json";
$authUrl = $end_point.'?'.http_build_query([
'client_id' => $client_id,
'redirect_uri' => $redirect_uri,
'scope' => 'https://mail.google.com/',
'access_type' => 'offline',
'include_granted_scopes' => 'true',
'response_type' => 'code',
]);
echo '<a href = "'.$authUrl.'">Authorize</a></br>';
if ( !file_exists($token_file) ){
if ( isset($_GET['code'])){
$code = $_GET['code'];
}else{
return;
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"https://accounts.google.com/o/oauth2/token");
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/x-www-form-urlencoded']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
'code' => $code,
'client_id' => $client_id,
'client_secret' => $client_secret,
'redirect_uri' => $redirect_uri,
'grant_type' => 'authorization_code',
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close ($ch);
file_put_contents($token_file, $response);
}else{
//and then to use the refresh_token to get a new access_token
}
UPDATED THE QUESTION
In short, how to get google OAuth access token automatically not through the browser(that is header('Location: ')
)?
I cannot get the refresh token any more, because I exceed the access limit while developing, and I've tried many ways and still cannot get the refresh token.
ORIGINAL QUESTION
I've successfully set up get_token.php
to get Google OAuth2 only for my website(example.com) for PHPMailer, and I can get access token via browser(by select my google account to log in to access).
Because I have exceed the limit of refresh token via development, so I've tried to use another google account to create api for my website(example.com), revoke from google account, delete OAuth and create another one(so there is a new clientId); but none of them work, and I think that I will never get a refresh token again.
Because my website is running and keep sending emails, so every hour I have to manually access the access token by link to https://example.com/get_token.php through the browser, so the PHPMailer can use the access token to work.
Is there a way to get refresh token again, or automatically link to get_token.php
to access the access token?ex: use command line, so the cronJob will do it on every hour.
My get_token.php
is very similar to the example shows on the document of thephpleague/oauth2-client
but I don't get the refresh_token
<?
require 'vendor/autoload.php';
session_start();
$token_file="my-token.json";
$provider = new \League\OAuth2\Client\Provider\Google([
'clientId' => 'xxx.apps.googleusercontent.com',
'clientSecret' => 'password',
'redirectUri' => 'https://example.com/get_token.php',
'scopes' => ['https://mail.google.com/'],
'access_type' => 'offline'
]);
if (!isset($_GET['code'])) {
$authorizationUrl = $provider->getAuthorizationUrl();
$_SESSION['oauth2state'] = $provider->getState();
header('Location: ' . $authorizationUrl);
exit;
} elseif (empty($_GET['state']) || (isset($_SESSION['oauth2state']) && $_GET['state'] !== $_SESSION['oauth2state'])) {
if (isset($_SESSION['oauth2state'])) {
unset($_SESSION['oauth2state']);
}
exit('Invalid state');
} else {
try {
$accessToken = $provider->getAccessToken('authorization_code', [
'code' => $_GET['code']
]);
$token=json_decode(file_get_contents($token_file));
$token->access_token=$accessToken->getToken();
if(!empty($accessToken->getRefreshToken())){
$token->refresh_token=$accessToken->getRefreshToken();
}
file_put_contents($token_file, json_encode($token));
} catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
exit($e->getMessage());
}
}
Here is my Mail.php
$token_file="my-token.json";
$mail = new PHPMailer();
try {
$mail->IsSMTP();
$mail->SMTPAuth = true;
$mail->SMTPSecure = "tls";
$mail->Host = "smtp.gmail.com";
$mail->Port = 587;
$mail->AddAddress($_GET['to']);
$oauth_token=file_get_contents($token_file);
$refresh_token= json_decode($oauth_token)->refresh_token;
$mail->AuthType ="XOAUTH2";
$mail->oauthUserEmail = 'auto-mail@example.com';
$mail->oauthClientId = "xxx.apps.googleusercontent.com";
$mail->oauthClientSecret = "password";
$mail->oauthRefreshToken = $refresh_token;
$mail->CharSet = 'utf-8';
$mail->SMTPDebug = 2;
$mail->Encoding = "base64";
return $mail->Send();
} catch (Exception $e) {
return false;
}