Issue
I'm trying to build an app to integrate with the Microsoft Graph API.
I have an admin account in Azure, and have set up a new app through the portal.
I've downloaded and installed the PHP SDK, and have managed to set everything up so that I can get a user successfully.
I can sign into the app and grant permissions to use my information (the permission I'm requesting is Directory.ReadWrite.All, but even just requesting User.ReadWrite.All is not working for me), however, my issue seems to be that I cannot access other users.
The following only returns my own user:
$graph = new Graph();
$graph->setAccessToken('/* SOMETOKEN */');
$users = $graph->createRequest('GET', '/users')
->setReturnType(User::class)
->execute();
POSTing a new user returns me a 404 error:
$newUser = new User();
$newUser->setAccountEnabled(true);
$newUser->setGivenName('first_name');
$newUser->setSurname('last_name');
$newUser->setUserPrincipalName('some.email#address.com');
$password = new PasswordProfile();
$password->setPassword('some_password');
$newUser->setPasswordProfile($password);
$user = $graph->createRequest('POST', '/users')
->attachBody($newUser)
->execute();
Returns:
{
"error": {
"code": "",
"message": "No HTTP resource was found that matches the request URI 'https://outlook.office365.com:444/profile/v1.0/users('CID:a8ef4446a149de4d')/profile?api-version=AGSV1-internal'.",
"innerError": {
"date": "/* timestamp */",
"request-id": "/* an id */",
"client-request-id": "/* an id */"
}
}
}
Even trying to use Microsoft's Graph Explorer is getting these same errors.
Am I right in thinking this could be an account setup issue?
Update
Here is the error message the Graph Explorer is returning
{
"error": {
"code": "",
"message": "No HTTP resource was found that matches the request URI 'https://outlook.office365.com:444/profile/v1.0/users('CID:a8ef4446a149de4d')/profile?api-version=AGSV1-internal'.",
"innerError": {
"date": "2020-11-30T16:51:41",
"request-id": "743030b4-8835-4a9f-9e3e-d35919a1c289",
"client-request-id": "c40cd440-d873-ba38-dce7-8669bc561e64"
}
}
}
I have resolved this.
Issue
The issue was in the permission request.
My app was set up to allow personal accounts as well as work/school ones.
Logging in with a personal account, my user was not able to grant the *.ReadWrite or *.All permissions.
While I was getting a token back from the auth request, it only had the User.Read permission.
Steps needed to get access to all users working
Change the app in Azure to only accept work/school accounts
When my app tries to authenticate, I needed to log in with a work/school account
Granting the permissions for User.Read.All should now work
Hitting the /users endpoint should return all users
To get write working, I needed to register for a Partner Center MPN ID and associate that with my app in Azure.
Related
Hello fellow developers,
I am working with a friend on a Search Console Application. We are using Laravel and google/apiclient package.
I did implement the login with google with authenticating with OAuth2, and all workes fine.
The main issue here is that when i query search console i was able to get some websites data, but for some reasons for other websites i get this error.
Google\Service\Exception: {
"error": {
"code": 403,
"message": "User does not have sufficient permission for site 'https://example-site.com'. See also: https://support.google.com/webmasters/answer/2451999.",
"errors": [
{
"message": "User does not have sufficient permission for site 'https://examplesite.com'. See also: https://support.google.com/webmasters/answer/2451999.",
"domain": "global",
"reason": "forbidden"
}
]
}
}
https://example-site.com i used my real website.
Here are the steps that i did:
I created a project in google cloud api, activate the google search console api, i have project permission as owner, i got the credentials in json format.
In Laravel i implemented the apis (Controller and Api Routes) for google authentications(code exchange), refresh token , etc.
I also set the scope like this.
$client->setScopes(
[
\Google\Service\Oauth2::USERINFO_PROFILE,
\Google\Service\Oauth2::USERINFO_EMAIL,
\Google\Service\Oauth2::OPENID,
\Google\Service\SearchConsole::WEBMASTERS
]
);
This is the method that i used to query Analitics
public function getSearchConsoleData(Request $request)
{
$client = GoogleController::getUserClient();
$service = new \Google\Service\Webmasters($client);
$request = new \Google\Service\Webmasters\SearchAnalyticsQueryRequest;
$request->setStartRow(0);
$request->setStartDate('2022-11-01');
$request->setEndDate('2022-11-15');
$request->setSearchType('web');
$request->setDimensions(array('query','country','device','country','device',));
$query_search = $service->searchanalytics->query("https://website-that-i-own.com", $request);
$rows = $query_search->getRows();
return $rows;
}
All the site are verified, i did check in Search Console Site.
I also searched online, looked at documentation from google search console api, google api issue forum.
All the site are verified, i did check in Search Console Site.
I also searched online, looked at documentation from google search console api, google api issue forum.
Please let me know what i missed here.
Thank you so much for you help in advance.
I am developing an application which integrates with Google Ads and syncing Ad/Campaign etc. data into my servers. I am getting authorization related error when I try to request some data from Google Ads API. Here is the steps I have done by now:
Applied to Google in terms of validating an OAuth application and scopes (Done, we got verification from Google and can ask for AdWords scope)
Applied to Google Ads for getting a developer token and got it. (Basic Access)
We are able to connect test accounts and successfully getting the response. But when we try it with real accounts we get the error below.
The code is also from the original Google Ads API example. I have tried with tons of different accounts but none of them seems to be working. When I try to obtain those data with same parameters from AdWords API instead of Google Ads API, it works. But Google AdWords PHP SDK is no longer maintained so I have to keep trying with Google Ads API. I share my code below:
{
$this->customerId = $customerId;
$this->clientId = $clientId;
$this->clientSecret = $clientSecret;
$this->accessToken = $accessToken;
$oAuth2Credential = (new OAuth2TokenBuilder())
->withClientId($this->clientId)
->withClientSecret($this->clientSecret)
->withRefreshToken($this->accessToken)
->build();
$this->googleAdsClient = (new GoogleAdsClientBuilder())
->withOAuth2Credential($oAuth2Credential)
->withDeveloperToken(env("GOOGLE_DEVELOPER_TOKEN"))
->withLoginCustomerId((int) $this->customerId)
->build();
}
public function getCampaigns(): array
{
try {
$campaigns = [];
$services = $this->googleAdsClient->getGoogleAdsServiceClient();
$results = $services->search($this->customerId, $this->campaignQuery(), ['pageSize' => self::PAGE_SIZE]);
foreach ($results->iterateAllElements() as $row) {
$campaigns[] = (new Campaign())->transform($row);
}
return $campaigns;
} catch (GoogleAdsException $googleAdsException) {
// TODO add error log
return [];
}
}```
The error:
```Google\ApiCore\ApiException: {
"message": "The caller does not have permission",
"code": 7,
"status": "PERMISSION_DENIED",
"details": [
{
"#type": 0,
"data": "type.googleapis.com\/google.ads.googleads.v6.errors.GoogleAdsFailure"
},
{
"#type": 0,
"data": [
{
"errorCode": {
"authorizationError": "DEVELOPER_TOKEN_PROHIBITED"
},
"message": "Developer token is not allowed with project '691752477594'."
}
]
}
]}```
Are you using the same cloud console project credentials for the login on your site as you are for the API calls?
The very first call to the Google Ads API permanently associates a developer token to a cloud project. If this is different to the one you're using on your site, you may have to switch them.
some developer token is already associated with project that you are trying with,
to resolve this You have to create one more App project in console and re configure your secrate key, and client id with new project that you have created dont forget to use the latest developer token i.e (your current developer token) and make a first API call, then your developer token will get paired forever, once it get bound it will never be changed later on.
As said before you need to create a new google cloud project, this is related with how Google organises users through their products.
If you are a company that is advertising through Google Ads, Google wants you to organise all your campaigns under a single master user account. That master user account should have a single developer token which you use within the Google Cloud Project associated to the same company.
For Google you should not have multiple master user accounts for the same company and therefore multiple developer tokens.
Of course there are edge cases that do not fit this rule, like advertising agencies however there is not a large incentive for Google to change this.
You can follow this thread for updates, but I do not expect things to change any time soon, https://groups.google.com/g/adwords-api/c/O8_y2xt0nGo
Im doing and application with PHP, which use Microsoft Graph API. Actually i couldnt found any documentation for php, so im follow microsoft tutorial.
So first i tried to do the microsoft page example for post method:
POST https://graph.microsoft.com/beta/app/onlineMeetings
Content-Type: application/json
Content-Length: 1553
{
"meetingType": "meetNow",
"participants": {
"organizer": {
"identity": {
"user": {
"id": <id user azuread teenant>
}
}
}
},
"subject": "subject-value"
}
actually it doesnt work on microsoft graph explorer. I already gave all permissions and ir returns the following:
Failure - Status Code 403, 440ms Looks like you may not have the permissions for this call.
{
"error": {
"code": "Forbidden",
"message": "",
"innerError": {
"request-id": "fd8cdedd-99f1-4bca-9de6-29a77f834bba",
"date": "2019-04-25T18:06:43"
}
}
}
I though explorer dont work with onlinemeetings and calls, so i stopped to use it, and i tried on a php app.
Then i tried this:
// Create a Graph client
// Set graph version
// Get user info
$graph = new Graph();
$graph->setAccessToken($accessToken);
$graph->setApiVersion("beta");
$createTeamsUrl = '/app/onlineMeetings';
$events = $graph->createRequest('POST', $createTeamsUrl)
->attachBody($body)
->execute();
accessToken is the returned token from oauth v2.0, and it works.
I already gave to my azure ad aaplication all permissions for test purpuoses (including delegated and app such as OnlineMeetings.ReadWrite.All), but this returns the same error.
I did some others request, like this:
//works
$graph = new Graph();
$graph->setAccessToken($accessToken->getToken());
$user = $graph->createRequest('GET', '/me')
->setReturnType(Model\User::class)
->execute();
and this works.
I also downloaded c# sample, and it works, so i think its not permissions
https://github.com/microsoftgraph/microsoft-graph-comms-samples/
If anyone knows if this is supported or not, could be useful.
Thanks.
If you are using common as tenant to get the access token, first thing you have to do is use your tenant id instead of common word, as explained here. This worked for me.
Getting same 403 forbidden error on creating online meeting
also added "OnlineMeetings.ReadWrite.All" permission in the scope
I created a service account credential in Google and tried to change the thumbnail of a video I own (it's uploaded in my verified channel). The account is, by the way, a managed account (indeed, it's a company email). The code below apparently logs in using the credentials in the JSON file downloaded from the Google API backend. IMAGE_MIME is image/jpeg, CHUNK_SIZE_BYTES is 1 * 1024 * 1024.
putenv("GOOGLE_APPLICATION_CREDENTIALS=" . CLIENT_ACCOUNT_FILE);
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->setScopes(['https://www.googleapis.com/auth/youtube', 'https://www.googleapis.com/auth/youtube.upload']);
$client->setDefer(true);
$youtube = new Google_Service_YouTube($client);
try {
$set_request = $youtube->thumbnails->set($video_id);
$media = new Google_Http_MediaFileUpload(
$client,
$set_request,
IMAGE_MIME,
null,
true,
CHUNK_SIZE_BYTES
);
$media->setFileSize(filesize($image_path));
$status = false;
$handle = fopen($image_path, "rb");
while (!$status && !feof($handle)) {
$chunk = fread($handle, CHUNK_SIZE_BYTES);
$status = $media->nextChunk($chunk);
}
fclose($handle);
} catch (Exception $e) {
echo "ERROR -> " . $e->getMessage();
}
$client->setDefer(false);
Sadly, it throws an exception. Running getMessage(), it pops out this JSON:
{
"error": {
"errors": [
{
"domain": "youtube.thumbnail",
"reason": "forbidden",
"message": "The thumbnail cant be set for the specified video. The request might not be properly authorized.",
"locationType": "parameter",
"location": "videoId"
}
],
"code": 403,
"message": "The thumbnail cant be set for the specified video. The request might not be properly authorized."
}
}
I directly access the video ID, the channel is mine (and there's only one channel), it doesn't throw a login exception (it did until I made it work), and the image file exists. Has anyone had this issue before?
Edit
I decided to log into my personal account and follow the same process of verification, API activation, service account JSON download and script running. The error is absolutely the same, even when everything in there should be working now for a non-domain account, after Jay's answer.
I tried, just because, to use the company credentials with my personal video and try this. Same error. It's like I'm missing something on the whole process. I also checked the value of getenv and it's correct, and not setting it would pop a "Could not load the default credentials.", so in the end it's grabbing the proper credentials, although not giving access to them them somehow.
Service accounts are not members of managed G Suite domains (company accounts) and do not automatically have rights to any data that the service account creator user account has. See the note on Google's domain wide delegation setup:
Note: Although you can use service accounts in applications that run from a G Suite domain, service accounts are not members of your G Suite account and aren’t subject to domain policies set by G Suite administrators. For example, a policy set in the G Suite admin console to restrict the ability of G Suite end users to share documents outside of the domain would not apply to service accounts.
Options for you would be:
Actually perform domain wide delegation as described above and act as your G Suite user, not the service account.
Share edit access of the Youtube video with the service account email address.
I am far from the programming and PHP, but got the challenge to get the Fb share count for the website :)
I'm trying to get the proper App Access Token and send the request to Fb
according to this article.
The request should be like this:
https://graph.facebook.com/?ids=http://www.myurl.com/my-page&access_token=myappid|myappsecret
And I getting this error.
{
"error": {
"message": "Invalid OAuth access token signature.",
"type": "OAuthException",
"code": 190,
"fbtrace_id": "FfZKAkCyad1"
}
}
I am going to use it in PHP roughly like this:
function facebook_count($url)
{
$results = #file_get_contents('http://graph.facebook.com/' . $url .'&access_token=myappid|myappsecret');
if ($results) {
$like_array = json_decode($results, true);
if (!empty($like_array['shares']))
return ($like_array['shares']);
}
return 0;
}
My guess, I checked wrong Permissions (scopes) for my App token. Did not found an answer in FB dev page. Checked this for now:
user_likes, read_insights, read_audience_network_insights, public_profile
What Scope do I need to check, if I need only the shares count by the link?
Or in what else could be the problem?
You need to use an App Access Token... So the actual permissions (referring to User Access Tokens!) are irrelevant.
So, hopefully you are replacing myappid|myappsecret with your actual App Id and App Secret. If ynot, there's your error. Furthermore, I think in the file_get_contents call then ?id= part in the URL is missing.