I currently use a Python Twilio application server and grant push capabilities to my tokens with the following lines of code:
#app.route('/accessToken')
def token():
account_sid = os.environ.get("ACCOUNT_SID", ACCOUNT_SID)
api_key = os.environ.get("API_KEY", API_KEY)
api_key_secret = os.environ.get("API_KEY_SECRET", API_KEY_SECRET)
push_credential_sid = os.environ.get("PUSH_CREDENTIAL_SID", PUSH_CREDENTIAL_SID)
app_sid = os.environ.get("APP_SID", APP_SID)
grant = VoiceGrant(
push_credential_sid=push_credential_sid,
outgoing_application_sid=app_sid
)
token = AccessToken(account_sid, api_key, api_key_secret, IDENTITY)
token.add_grant(grant)
return str(token)
Is there a way for me to do that with PHP? I have loaded Twilio dependencies with composer and can get a token just fine. I just don't know how to add push capabilities to the token. These lines currently generate tokens (but not with push capabilities):
<?php
include('./vendor/autoload.php');
include('./config.php');
include('./randos.php');
use Twilio\Jwt\ClientToken;
use Twilio\Jwt\Grants;
// choose a random username for the connecting user
$identity = $_GET['identity'];
$capability = new ClientToken($TWILIO_ACCOUNT_SID, $TWILIO_AUTH_TOKEN);
$capability->allowClientOutgoing($TWILIO_TWIML_APP_SID);
$capability->allowClientIncoming($identity);
$token = $capability->generateToken();
echo $token;
?>
Thanks to a tip from Zack with Twilio, I finally got this working!
include('./vendor/autoload.php');
include('./config.php');
include('./randos.php');
use Twilio\Jwt\AccessToken;
use Twilio\Jwt\Grants;
use Twilio\Jwt\Grants\VoiceGrant;
use Twilio\Rest\Client;
// choose a random username for the connecting user
$identity = randomUsername();
$token = new AccessToken($TWILIO_ACCOUNT_SID, $API_KEY, $API_KEY_SECRET, 3600, $identity);
$grant = new VoiceGrant();
$grant->setPushCredentialSid($PUSH_CREDENTIAL_SID);
$grant->setOutgoingApplicationSid($TWILIO_TWIML_APP_SID);
$token->addGrant($grant);
echo $token;
Related
i am struggling with google API. I am creating a website where I would like to read the groups of which the authenticated user is a member.
I have read everything about the subject, but many examples are very old and in the meantime things have changed.
This is the code I'm testing:
<?php
require 'lib/google-api/vendor/autoload.php';
// Creating new google client instance
$client = new Google_Client();
// Enter your Client ID
$client->setClientId('***.apps.googleusercontent.com');
// Enter your Client Secrect
$client->setClientSecret('***');
// Enter the Redirect URL
$client->setRedirectUri('***');
$client->setApplicationName("Test");
// Adding those scopes which we want to get (email & profile Information)
$client->addScope("email");
$client->addScope("profile");
$client->addScope("https://www.googleapis.com/auth/admin.directory.group.readonly");
$client->addScope("https://www.googleapis.com/auth/admin.directory.group.member.readonly");
if(isset($_GET['code'])){
$token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
if(!isset($token["error"])){
$client->setAccessToken($token['access_token']);
// getting profile information
$google_oauth = new Google_Service_Oauth2($client);
$google_account_info = $google_oauth->userinfo->get();
// Storing data into database
$email = $google_account_info->email;
$full_name = $google_account_info->name;
echo $email . "<br>";
// this is needed only if you need to perform
// domain-wide admin actions, and this must be
// an admin account on the domain; it is not
// necessary in your example but provided for others
$client->setSubject('***');
// set the authorization configuration using the 2.0 style
$client->setAuthConfig("***.json");
$adminService = new Google_Service_Directory($client);
$googleGroups = $adminService->groups->listGroups(array('domain'=>'mydomain.com'));
$groups = $googleGroups->getGroups();
}
}
?>
I am getting the following error
Uncaught Google_Service_Exception: {
"error": "unauthorized_client",
"error_description": "Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested."
}
I have already done a Google Workspace Domain-Wide Delegation of Authority (https://developers.google.com/admin-sdk/directory/v1/guides/delegation) and I created a user to impersonate with read permissions on groups and users.
Where am I doing wrong? Thank you!
After some testing I made it work...
First of all i needed to give rights to the service account, not just at the one to impersonate.
$client = new Google_Client();
// Client ID
$client->setClientId(***);
// Client Secrect
$client->setClientSecret(***);
// Redirect URL
$client->setRedirectUri('https://www.mywebsite.com');
$client->setApplicationName('App name');
// Scopes for group reading, profile and email info
$client->addScope('https://www.googleapis.com/auth/admin.directory.group.readonly');
$client->addScope('https://www.googleapis.com/auth/userinfo.email');
$client->addScope('https://www.googleapis.com/auth/userinfo.profile');
if(isset($_GET['code'])){
$token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
if(!isset($token["error"])){
$client->setAccessToken($token['access_token']);
$google_oauth = new Google_Service_Oauth2($client);
// User info
$google_account_info = $google_oauth->userinfo->get();
$email = $google_account_info->email;
// Service account info
$client->setAuthConfig('***.json');
// Who i want to impersonate
$client->setSubject('admin#website.com');
$service = new Google_Service_Directory($client);
// Search groups of the logged user
$optParams = array(
'domain' => 'mywebsite.com',
'userKey' => $email
);
$googleGroups = $service->groups->listGroups($optParams);
$groups = $googleGroups->getGroups();
That's all :)
I'm trying to set up my own php accessToken server to grant new token for different user on my ios swift app.
I've set it up already, and can get the token key, however when the videoQuickStart app uses the token key get from my server, it will not connect to room, and even if I try to use the "token.php" from here : https://github.com/TwilioDevEd/video-quickstart-php/blob/master/token.php it still not working.
It seems like my key is not validated?
Can anyone helps?
Here's my implement of server, which is almost identical to the original one.
< ? php
include('/Applications/XAMPP/xamppfiles/htdocs/dashboard/vendor/autoload.php');
use Twilio\Jwt\AccessToken;
use Twilio\Jwt\Grants\VideoGrant;
// Required for all Twilio access tokens
$TWILIO_ACCOUNT_SID = 'XXXXX';
$TWILIO_CONFIGURATION_SID = 'XXXX';
$TWILIO_API_KEY = 'XXXX';
$TWILIO_API_SECRET = 'XXXXX';
// An identifier for your app - can be anything you'd like
$identity = $_GET['name'];
// Create access token, which we will serialize and send to the client
$token = new AccessToken(
$TWILIO_ACCOUNT_SID,
$TWILIO_API_KEY,
$TWILIO_API_SECRET,
3600,
$identity
);
$grant = new VideoGrant();
$grant->setConfigurationProfileSid($TWILIO_CONFIGURATION_SID);
$token->addGrant($grant);
// render token to string
echo json_encode(array(
'identity' => $identity,
'token' => $token->toJWT(),
));
?>
It's fixed.
It turns out I misplaced TWILIO_ACCOUNT_SID and TWILIO_CONFIGURATION_SID.
Thanks guys
When using the below code to attempt to list messages received by a brand new gmail account I just set up, I get
[Google_Service_Exception] Error calling GET https://www.googleapis.com/gmail/v1/users/myGmailAccount%40gmail.com/messages: (500) Backend Error
I know the validation portion is working correctly because I'm able to make minor modifications and query the books api as shown in this example. Below is the code I'm using to attempt to query recent messages received...
const EMAIL = 'myGmailAccount#gmail.com';
private $permissions = [
'https://www.googleapis.com/auth/gmail.readonly'
];
private $serviceAccount = 'xxxxxxxxxxxxxxxxx#developer.gserviceaccount.com';
/** #var Google_Service_Gmail */
private $gmail = null;
/** #var null|string */
private static $serviceToken = null;
public function __construct()
{
$client = new Google_Client();
$client->setApplicationName($this->applicationName);
$this->gmail = new Google_Service_Gmail($client);
//authentication
if (isset(self::$serviceToken)) {
$client->setAccessToken(self::$serviceToken);
}
$credentials = new Google_Auth_AssertionCredentials(
$this->serviceAccount,
$this->permissions,
$this->getKey()
);
$client->setAssertionCredentials($credentials);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($credentials);
}
self::$serviceToken = $client->getAccessToken();
}
public function getMessages()
{
$this->gmail->users_messages->listUsersMessages(self::EMAIL);
}
I have granted API access to gmail:
The 500 makes me believe this is an internal error with the gmail API or I'm missing something the PHP client isn't validating.
This one work for me. My understanding is service account doesn't have a mailbox and it's not too sure which mailbox it should work on. So you can't use listUsersMessages() function to get all messages.
So you will need to specify which email address that the service account need to work on.
Make sure that the scope has been allowed on Web App API to
1. Add this line:
$credentials->sub = self::EMAIL;
Before:
$client->setAssertionCredentials($credentials);
2. Then Update your getMessages() to:
$this->gmail->users_messages->listUsersMessages("me");
Hope this helps!
I imagine the account has logged in to the web interface already, right? Have you tried with a separate user? How about doing something like labels list instead? Did you try using the APIs explorer site? https://developers.google.com/apis-explorer/#p/gmail/v1/
Can you provide the first 5 digits of the developer's client ID (it's not secret anyway) so I can try to track down the error?
For this to work you have to impersonate an user account (the service account doesn't have a mailbox, as lthh89vt points out).
If you try to access the mailbox directly you will get the (500) Back End error.
The full code is:
$client_email = '1234567890-a1b2c3d4e5f6g7h8i#developer.gserviceaccount.com';
$private_key = file_get_contents('MyProject.p12');
$scopes = array('https://www.googleapis.com/auth/gmail.readonly');
$user_to_impersonate = 'user#example.org';
$credentials = new Google_Auth_AssertionCredentials(
$client_email,
$scopes,
$private_key,
'notasecret', // Default P12 password
'http://oauth.net/grant_type/jwt/1.0/bearer', // Default grant type
$user_to_impersonate,
);
$client = new Google_Client();
$client->setAssertionCredentials($credentials);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion();
}
$service = new Google_Service_Gmail($client);
$results = $service->users_messages->listUsersMessages('me');
Full instructions can be found on Google APIs Client Library for PHP
I'm having a problem implementing Google Admin SDK in PHP. It always give error
Fatal error: Uncaught exception 'Google_Service_Exception' with message 'Error calling POST
https://www.googleapis.com/admin/directory/v1/users: (403) Not Authorized to access this
resource/api' in ..\google-api-php-client\src\Google\Http\REST.php on line 79
Here is my code :
<?php
session_start();
/* * **********************************************
Make an API request authenticated with a service
account.
* ********************************************** */
set_include_path("google-api-php-client/src" . PATH_SEPARATOR . get_include_path());
require_once 'Google/Client.php';
require_once 'Google/Service/Directory.php';
/* * **********************************************
ATTENTION: Fill in these values! You can get
them by creating a new Service Account in the
API console. Be sure to store the key file
somewhere you can get to it - though in real
operations you'd want to make sure it wasn't
accessible from the webserver!
The name is the email address value provided
as part of the service account (not your
address!)
Make sure the Books API is enabled on this
account as well, or the call will fail.
* ********************************************** */
$client_id = 'my_client_id'; //Client ID
$service_account_name = 'email'; //Email Address
$key_file_location = 'key.p12'; //key.p12
if ($client_id == '<YOUR_CLIENT_ID>' || !strlen($service_account_name) || !strlen($key_file_location)) {
echo missingServiceAccountDetailsWarning();
}
$client = new Google_Client();
$client->setApplicationName("appname");
$service = new Google_Service_Directory($client);
/* * **********************************************
If we have an access token, we can carry on.
Otherwise, we'll get one with the help of an
assertion credential. In other examples the list
of scopes was managed by the Client, but here
we have to list them manually. We also supply
the service account
* ********************************************** */
if (isset($_SESSION['service_token'])) {
$client->setAccessToken($_SESSION['service_token']);
}
$key = file_get_contents($key_file_location);
$cred = new Google_Auth_AssertionCredentials(
$service_account_name, array('https://www.googleapis.com/auth/admin.directory.user'), $key
);
$client->setAssertionCredentials($cred);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$_SESSION['service_token'] = $client->getAccessToken();
/* * **********************************************
We're just going to make the same call as in the
simple query as an example.
* ********************************************** */
$familyName = filter_input(INPUT_GET, 'familyname');
$givenName = filter_input(INPUT_GET, 'givenname');
$password = filter_input(INPUT_GET, 'password');
$primaryEmail = filter_input(INPUT_GET, 'email');
$user = new Google_Service_Directory_User();
$name = new Google_Service_Directory_UserName();
$name->setFamilyName($familyName);
$name->setGivenName($givenName);
$user->setName($name);
$user->setHashFunction("MD5");
$user->setPrimaryEmail($primaryEmail);
$user->setPassword(hash("md5", $password));
$result = $service->users->insert($user);
There is no documentation and I'm very confused with this error.
I had a similar problem until I set the "sub" account on the credentials object which is the email address for the administrative user that you want to perform the API action as.
So in Google Apps Admin for your domain I assume you've created a user and added them to and admin role that has API access to users right? In your code above you just need to add (with correct email address of course):
$cred->sub = "adminuser#domain.com";
Add that right before:
$client->setAssertionCredentials($cred);
I did a full example for someone else that you might be able to reference too: https://gist.github.com/fillup/9fbf5ff35b337b27762a
I had a similar problem but found a solution to this by going through this blog
http://michaelseiler.net/2014/12/16/google-admin-sdk-api-with-php/
Assuming you have done all the necessary setting up on the Admin Console (i.e. delegating domain authority), then pay particular attention to the line
`$cred = new Google_Auth_AssertionCredentials($service_account_name, array('https://www.googleapis.com/auth/admin.directory.user'), $key);`
this should be:
`$user_to_impersonate = 'adminaccount#example.com';$scopes =array('https://www.googleapis.com/auth/admin.directory.user');$cred = new Google_Auth_AssertionCredentials(
$service_account_name,
$scopes,
$key,
'notasecret', // Default P12 password
'http://oauth.net/grant_type/jwt/1.0/bearer', // Default grant type
$user_to_impersonate);`
I changed that and boom....
I think i was receiving this error when i tried to query a user.
During the creation of the JWT_CLAIM portion of the assertion, you must specify a domain admin account that your service account can impersonate... this part was poorly documented, i thought.
i dont know exactly how the google php library does it, but i didnt see anywhere in your code where you specify that account email address. if you have looked at the oauth2 documentation, in the jwt_claim secion, there is an "additional claims" subsection that says:
To obtain an access token that grants an application delegated access to a resource, include the email address of the user in the JWT claim set as the value of the sub field.
I had to include that admin email account in the creation of my assertion before i could even query the directory.users API.
i apologize if this isnt helpful, but im not using the library for php, im building my own (with php).
i am using php 5.3.3, and codeigniter 2.1.0.
what i want to do is set up a service account, so a user can add an appointment in a text entry field on my website, then have that appointment added to a shared shared google calendar.
i have a google account, and using : https://code.google.com/apis/console I created a new project called 'pqp'
on services: enabled the calendar api
on api access: i created an oath 2.0 client id… product name = pqp, application type = service account.
downloaded the key 46… -privatekey.p12. there is a screenshot of the settings:
I got an svn checkout of the google-api-php-client (28/6/2012)
In the google-api-php-client/src/config.php I changed lines:
25: 'application_name' => 'pqp',
28: 'oauth2_client_id' => '373xxx730.apps.googleusercontent.com',
57: 'ioFileCache_directory' => 'tmp/apiClient', // my apache user does not have access to the system /tmp folder. + tmp/apiClient has permissions of 777 on the server.
using this link:
http://code.google.com/p/google-api-php-client/source/browse/trunk/examples/prediction/serviceAccount.php?spec=svn445&r=395
I modified it to:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Test extends CI_Controller{
function __construct()
{
parent::__construct();
}
function index()
{
set_include_path(get_include_path() . PATH_SEPARATOR .dirname(__FILE__).'/../libraries/google-api-php-client/src');
ini_set('error_reporting',E_ALL);
ini_set('display_errors','1');
// Set your client id, service account name, and the path to your private key.
// For more information about obtaining these keys, visit:
// https://developers.google.com/console/help/#service_accounts
define('CLIENT_ID','3731xxx44730.apps.googleusercontent.com');
define('SERVICE_ACCOUNT_NAME','373xxx244730#developer.gserviceaccount.com');
// Make sure you keep your key.p12 file in a secure location, and isn't
// readable by others.
define('KEY_FILE',dirname(__FILE__).'/../../461290xxx796c0b7db9582c-privatekey.p12');
require_once "apiClient.php";
require_once "contrib/apiCalendarService.php";
$client = new apiClient();
$client->setApplicationName("pqp");
// Set your cached access token. Remember to replace $_SESSION with a
// real database or memcached.
session_start();
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
echo 'client access token is set.<br/>';
}
// Load the key in PKCS 12 format (you need to download this from the
// Google API Console when the service account was created.
$key = file_get_contents(KEY_FILE);
$creds = new apiAssertionCredentials(SERVICE_ACCOUNT_NAME,array('https://www.googleapis.com/auth/calendar'),$key);
$client->setAssertionCredentials($creds);
$client->setClientId(CLIENT_ID);
$service = new apiCalendarService($client);
echo 'client:<br/>';
var_dump($client);
echo 'service:<br/>';
var_dump($service);
// We're not done yet. Remember to update the cached access token.
// Remember to replace $_SESSION with a real database or memcached.
if ($client->getAccessToken()) {
$_SESSION['token'] = $client->getAccessToken();
echo 'token is good!, so creating an event....';
echo $this->insert_event($service,'testing summary','my location','2012-06-29T10:00:00.000+10:00','2012-06-29T10:00:00.000+10:00');
}
}
function insert_event($service,$summary,$location,$from,$to){
$event = new Event();
$event->setSummary($summary);
$event->setLocation($location);
$start = new EventDateTime();
$start->setDateTime($from);
$event->setStart($start);
$end = new EventDateTime();
$end->setDateTime($to);
$event->setEnd($end);
$attendee1 = new EventAttendee();
$attendee1->setEmail('test#example.com');
$attendees = array($attendee1);
$event->attendees = $attendees;
$createdEvent = $service->events->insert('primary', $event);
return $createdEvent->getId();
}
}
a pastie of the output is here:
the $client object is not authenticated, the getAccessToken is not set, and the event is not inserted.
i have found it difficult to work out which settings in the $config file to change because there is different nomenclature. i guess this is an artifact of how the code has progressed.
are the settings in src/config.php correct? do i need to alter any more settings?
it is my understanding that if i create the service account, download the key file, and the contents of this file with my developer id, it should return a token, and there is no need to set up a redirection uri.. is that correct? this is the functionality i want. i don't want the user to have to authorise access because the website will only ever interact with one google account.
So, the question is, how do i get this calendar api to authenticate using a google service account?
You can try this one if you not already...
EDIT: this one intresting but if you still feel like to write one yourself then try this THE mother of the oauth2. helpful
About Service Account at google-api-php-client that you use(always take the trunk's one with SVN) I can't found in that code manipulations any reference apiAssertionCredentials::generateAssertion()
definitely there is no call to auth in there
public function __construct(
$serviceAccountName,
$scopes,
$privateKey,
$privateKeyPassword = 'notasecret',
$assertionType = 'http://oauth.net/grant_type/jwt/1.0/bearer',
$prn = false) {
$this->serviceAccountName = $serviceAccountName;
$this->scopes = is_string($scopes) ? $scopes : implode(' ', $scopes);
$this->privateKey = $privateKey;
$this->privateKeyPassword = $privateKeyPassword;
$this->assertionType = $assertionType;
$this->prn = $prn;
}
and this method should be called I guess...
public function generateAssertion() {
$now = time();
$jwtParams = array(
'aud' => apiOAuth2::OAUTH2_TOKEN_URI,
'scope' => $this->scopes,
'iat' => $now,
'exp' => $now + self::MAX_TOKEN_LIFETIME_SECS,
'iss' => $this->serviceAccountName,
);
if ($this->prn !== false) {
$jwtParams['prn'] = $this->prn;
}
return $this->makeSignedJwt($jwtParams);
}
EDIT:
Pardon. In fresh ver. look's like it's Google_OAuth2::refreshTokenWithAssertion() actualy who should start the real proces