Gmail API how to authenticate to access own data using PHP? - google-oauth

I simply want to access my own gmail account and retrieve the 10 newest messages. I'm having a very hard time authenticating so that I can even attempt this.
I followed the instructions here: https://developers.google.com/gmail/api/quickstart/php
All appears to work, but now what? The documentation is tough to follow. The API calls work using API Explorer but how should I access the oAuth token in PHP?
Google provides the following exaple function:
function listMessages($service, $userId) {
$pageToken = NULL;
$messages = array();
$opt_param = array();
do {
try {
if ($pageToken) {
$opt_param['pageToken'] = $pageToken;
}
$messagesResponse = $service->users_messages->listUsersMessages($userId, $opt_param);
if ($messagesResponse->getMessages()) {
$messages = array_merge($messages, $messagesResponse->getMessages());
$pageToken = $messagesResponse->getNextPageToken();
}
} catch (Exception $e) {
print 'An error occurred: ' . $e->getMessage();
}
} while ($pageToken);
foreach ($messages as $message) {
print 'Message with ID: ' . $message->getId() . '<br/>';
}
return $messages;
}
How do I get the $service? I assume that refers to the keys stored in client_secrets.json but I'm unsure how to access.
I know this is a somewhat basic question (so basic that Google doesn't explain it) but I'm sure I'm not the only one to struggle with this.
Thanks!

You're in a common catch-22 - we've all been there.
You want to use Google API xxx (gmail in your case), so you read the docs about the the Gmail API. They make a passing reference to OAuth, along with a link, but there is a fire-hose of information there, so you skim read it and then go back to the Gmail docs hoping for a bit of sample code to copy/paste.
Unfortunately, you're probably going to have to go back to the OAuth docs and invest a few hours reading the. You'll know when you've understood it because you will be able to explain to yourself the difference between Authentication and Authorization. The main difficulty is that most of the sample code and explanations relate to the use case where your application has many users, each wishing to securely access their own email using your app. The use case where a single user wants to access his own email is an edge case and thus not well explained. this post might help How do I authorise an app (web or installed) without user intervention? (canonical ?). I wrote it for GDrive, but it will probably work for Gmail also.

Related

How can I use integrate Google sign in with my existing users?

I'm pretty sure someone must have asked this question before but I haven't been able to find anything to help me figure this out.
I currently have a set of users in my database and have my own sign in authentication mechanism for them. I am now required to add on Google sign in for my users but I don't know how I can map users who sign in with Google to their existing accounts.
Your help will be much appreciated.
Thank You
It is possible to do that,if they are using gmail you can access the user object, but from the client side. Unfortunately you may have to ask them to link.
So what you need to do behind the scenes is to check if their regoistered emaill address is a gmail. Then ask them to link. Follow the tutorial on firabase to learn how to link multiple auth providers here
firebase.auth().currentUser.linkAndRetrieveDataWithCredential(credential).
then(function(usercred) {
var user = usercred.user;
console.log("Account linking success", user);
},
function(error) {
console.log("Account linking error", error);
});

How can a webhook identify USER_IDs?

I'm developing a webhook, and I want it to be able to #mention specific users. The simple message format specifies using the format of <users/123456789012345> to #mention a specific users. Since this is not a bot, it is not processing an incoming message and cannot pull the from the sender field, as suggested in the note on the developer site linked above.
How can I get the USER_ID of a user on my domain?
I am in the same boat as you. Trying to use a Webhook to mention a user.
If you inspect the HTML on https://chat.google.com, using web/dev tools, you can actually see user ID under tag data-member-id="user/bot/123456789012345"
Using the above I tried to form a webhook that mentioned the user (in my case another bot).
Unfortunately it didn't work. Passing in the string <users/123456789012345> please test came through to chat as a string literal.
It's strange because the html links and markup DO get interpreted. As mentioned here. Edit: so does <users/all>.
I'm leaving this here since your question asks for how to elicit the ID. While it may not be pretty, or much automatable, it helped me get the user ID at least.
Edit 2: It works, just not to mention my other bot for some reason. But using this method I was able to mention a human user :)
I use this for find the USER_ID but if you have another way let me know
Right click on the user and select inspect
Search for data-member-id this is your USER_ID
A webhook will not be able to pull the USER_ID of a user. As a workaround for this, you can create a service account and a bot that has access to the room and use the REST API spaces.members.list() and spaces.members.get() method.
Note: The bot will need to be added to the room.
Okay, so in order to get the UserID without having to do all of the things that you're trying to do here you need to use the Admin SDK API in google app script. Basically what you'll want to do is use your google app script as an intermediary for what you're trying to do. So you'll post something to google app script via their web exec functions on a deployed app and then have that app communicate to the google chat API via something like this:
var googlewebhookurl = 'https://chat.googleapis.com/v1/spaces/ASDFLKAJHEPQIHEWFQOEWNQWEFOINQ';
var options = {
'method': 'post',
'contentType': 'application/json',
'payload' : JSON.stringify({ text: "<users/000000000001> I see you!" })
}
UrlFetchApp.fetch(googlewebhookurl, options);
To start, you'll need to add the Admin SDK API to the services in your google app script services area. So click the plus next to "Services" and then select the Admin SDK API and click add to add it to the services, it winds up showing up in the list as "AdminDirectory" once it has been added to the services.
This is an image showing what it looks like once you've added it to the services.
Here is a link to the documentation for the Admin SDK API getting user information: https://developers.google.com/apps-script/advanced/admin-sdk-directory#get_user
You should be able to copy and paste that example function to get the information you're looking for regarding the user. I'm pasting the example code below in case something happens to this link:
/**
* Get a user by their email address and logs all of their data as a JSON string.
*/
function getUser() {
var userEmail = 'liz#example.com';
var user = AdminDirectory.Users.get(userEmail);
Logger.log('User data:\n %s', JSON.stringify(user, null, 2));
}
In order to get the user id, take the user variable that comes back and access user.id and voila! You have the ID you're looking for. From there just plaster it into a text message in google chat and you should be in business. I haven't gotten it to work with cards at all yet. I'm not seeing any documentation saying that it's supported in cards at all. For more information regarding chat messages and cards take a look at these:
https://developers.google.com/chat/api/guides/message-formats/basic
https://developers.google.com/chat/api/guides/message-formats/cards

Google contacts API invalid scope but app does not need review - contacts api

I'm trying to use Google Contacts API to import a users gmail contacts. This works with my gmail but fails when others try to login with the following error message:
Error: invalid_scope
This app hasn't been verified to access: {invalid = [https://www.googleapis.com/auth/contacts]} Please contact the developer for assistance. Are you the developer? If this project needs these scopes, sign in to an account with access to edit your project and try again. If not, contact the developer for help.
Because of this message, I did some research and found this question which suggests that this app needs to be reviewed. I then submitted my app for verification. However, I received an e-mail saying that my app does not need verification from google.
Thank you for submitting the developer verification form. Based on the information you provided, you have access to the scopes that you are planning to use. If you add any more scopes in the future, you may have to go through verification.
The scope I am requesting is https://www.google.com/m8/feeds/.
Does this scope require approval from google?
I'm using the gapi library, below is my code:
function start() {
var auth_obj = {
clientId: currentUser.GOOGLE_APP_ID,
scope: 'https://www.google.com/m8/feeds/'
}
gapi.client.init(auth_obj).then(function() {
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
})
};
gapi.load('client:auth2', start);
function getContacts() {
var access_token = gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse().access_token
var url = "https://www.google.com/m8/feeds/contacts/default/"
url += "thin?alt=json&access_token=" + access_token
url += "&max-results=500&v=3.0"
$.get(url)
}
Yes, If your app is going to be used by random other users and it is asking for the contact scope then it needs to be reviewed and approved.
The reason you got the answer from us (it does not need a review).. if you indicated that it was for your own usage or for just a few users. In that case you (and whoever needs to approve) can join a Google group. You probably joined the Google group and thus you can approve this app (or your account is part of gsuite).
Contact me with more details about your app and I can look into the specifics.
I suggest that you respond to the review and make it very clear what data you plan to access and how you are going to use it. If Google has any doubt about your intentions with the data, they see to be less likely to approve the request.
Also, if you plan to only read their contacts, you could modify your scope to be https://www.googleapis.com/auth/contacts.readonly.

Can't figure out how to query Bing/Azure Marketplace API

How the heck do you use the Bing API (now Azure Marketplace API)? Does it only support oAuth? Can anyone show me an example of how to authenticate to it? The documentation is silent and after an hour of frustration I'm posting the question here.
Here is the end point I am trying to hit:
https://api.datamarket.azure.com/Bing/Search/v1/Composite?query=sushi&sources=web
This throws up Basic Auth; if I cancel I get an error message saying that only Basic and oAuth are supported.
However, no combination of username and password known to my account works for Basic, and I can't find an example of how to use oAuth with it. I have an account set up, I have subscribed to the free tier.
After doing more research and experiment I was able to figure it out. The examples confused me (I think theyassume a lot of context about Azure's SOAPy conventions over REST, such as case sensitivity and quoted strings). Perhaps they will confuse others so I'm posting my answer here:
function searchBing() {
var request=require('request');
var url="https://api.datamarket.azure.com/Bing/Search/v1/Web?Query='sushi'&$format=JSON";
var key="[your account key]";
request.get(url, {auth: { user: key, password: key} }, function (error, result) {
console.log(error, result.body);
})
}

Using Gdata authorization by removing hardcoded gmail credentials to get google contacts

The idea is to login through gmail and get all contacts details and also add a contact from PHP code to google contact list.
The whole flow is working well and i am getting contact list and also adding contacts with fields.
The problem is that the code has hardcoded variables where i need to set google email and password.I want to have a link to authoriZe and then get all response..
So i just need to bypass the credentials on first attempt using an API or token method and get the contact details
Please suggest if someone has gone through this issue or share examples or resourced that might help toward the solution.
Here is the code snippet...
$user = "XXX#XXX.com";
$pass = "XXX";
// Need to remove above 2 lines and combine the login on the fly API using some with further working stuff
try {
// perform login and set protocol version to 3.0
$client = Zend_Gdata_ClientLogin::getHttpClient(
$user, $pass, 'cp');
$gdata = new Zend_Gdata($client);
$gdata->setMajorProtocolVersion(3);
// perform query and get feed of all results
$query = new Zend_Gdata_Query(
'http://www.google.com/m8/feeds/contacts/default/full');
$query->maxResults = 1000;
$query->setParam('orderby', 'lastmodified');
$query->setParam('sortorder', 'descending');
$feed = $gdata->getFeed($query);
//display data in loop below....
}
Basically I want to remove the user and pwd variables and do it on the fly to get data.
Right now I am getting all contacts and also able to add a contact but the way of setting credentials is to be changed to be more secure using a token or other way..
Insead of using the username and password directly, you need to use the Google OAuth. You need to first create a project in the Google OAuth and specify correct details. Using the app created there, you can ask for permission of a user and get his contact details in the response.
How to get Google Contacts information using Google OAuth?