I have set the MS Azure API permissions of contacts.read.write but when executing the following code I get this message:
Uncaught GuzzleHttp\Exception\ClientException: Client error: POST https://graph.microsoft.com/beta/contacts resulted in a 400 Bad Request response: { "error": { "code": "Request_BadRequest", "message": "A value without a type name was found and no expecte (truncated...) in C:\Program Files\Ampps\www\weedo\weedo2\content\libraries\MicrosoftGraph\vendor\guzzlehttp\guzzle\src\Exception\RequestException.php:113
My post code:
$graph = new Graph();
$graph
->setBaseUrl("https://graph.microsoft.com/")
->setApiVersion("beta")
->setAccessToken($this->accessToken);
$data = array(
"GivenName" => "Test",
"Surname" => "account",
"EmailAddresses" => array(
array(
"Address" => "testaccount#mail.com",
"Name" => "Mail Name"
)
)
);
$user = $graph->createRequest("POST", "/contacts")
->addHeaders(array("Content-Type" => "application/json"))
->setReturnType(Model\User::class)
->attachBody($data)
->setTimeout("1000")
->execute();
I believe I followed these pages correctly, but the examples are not all given for PHP so I'm not sure where to go from here:
https://github.com/microsoftgraph/msgraph-sdk-php
https://learn.microsoft.com/en-us/graph/api/user-post-contacts?view=graph-rest-1.0&tabs=http
I also wrapped the $data parameter in a json_encode just for testing, but no luck.
Where to go? What to do?
EDIT:
So as seems i was confused with organizational contacts (which are obtained by /contacts) and personal contacts (which are obtained by /me/contacts). Now it is not (yet) supported to create organizational contacts, which i find rediculous but for some reason i'm not allowed to create contacts on application based either. any thoughts / ideas on this?
You are right, currently, there is no Microsoft Graph API for creating organizational contacts, only list and get method provided. When I tried to create a new one, I got this error:
This issue also has been confirmed by a Microsoft engineer here.
So the only 2 ways I know to add organizational contacts is on Microsoft 365 admin Center =>Users => Contacts blade to add manually:
Add my self as a org contat and I can get the new record from /contacts calling:
The second way is using the PowerShell command:New-MailContact to do this:
All of these 2 ways I have tested on my side and all works for me.
UPDATE:
If you are looking for some sample code about adding a user's personal contacts by an Azure AD application, just try code below:
use Microsoft\Graph\Graph;
use Microsoft\Graph\Http\GraphRequest;
$tenantId= '<your tenant name/ID>';
$clientId = '<azure ad app id>';
$clientSecret ='<azure ad app secret>';
$targetUser = '<target user UPN/ID>';
$guzzle = new \GuzzleHttp\Client();
$url = 'https://login.microsoftonline.com/' . $tenantId . '/oauth2/token?api-version=1.0';
$token = json_decode($guzzle->post($url, [
'form_params' => [
'client_id' => $clientId,
'client_secret' => $clientSecret,
'resource' => 'https://graph.microsoft.com/',
'grant_type' => 'client_credentials',
],
])->getBody()->getContents());
$accessToken = $token->access_token;
$data = array(
"GivenName" => "Test2",
"Surname" => "account2",
"EmailAddresses" => array(
array(
"Address" => "testaccount2#mail.com",
"Name" => "Mail Name2"
)
)
);
$graph = new Graph();
$graph->setAccessToken($accessToken);
$graph->createRequest("POST", "/users/$targetUser/contacts")
->addHeaders(array("Content-Type" => "application/json"))
->attachBody($data)
->execute();
Result:
Related
I am calling one Microsoft graph API from my PHP application, API is https://graph.microsoft.com/beta/policies/identitySecurityDefaultsEnforcementPolicy
my code is like below
$graph = new Graph();
$graph->setAccessToken(session('my_token'));
try{
$response = $graph->createRequest("GET", "/policies/identitySecurityDefaultsEnforcementPolicy")->execute();
}
catch(Exception $e){
dd($e);
}
$arr = $response->getBody();
dd($arr);
but it always catches exception and displays the below error
Client error: `GET https://graph.microsoft.com/v1.0/policies/identitySecurityDefaultsEnforcementPolicy` resulted in a `403 Forbidden` response:
{"error":{"code":"AccessDenied","message":"You cannot perform the requested operation, required scopes are missing in the token.","innerError":{"date":"2022-11-23T06:47:39","request-id":"9a4573c7-fd72-44ae-8ac6-8e4589cf1497","client-request-id":"9a4573c7-fd72-44ae-8ac6-8e4589cf1497"}}}
all the other Microsoft graph APIs are working well
I have also given permission to Policy.Read.All and granted admin consent to the Microsoft app I am using here for auth.
Update: when I open Microsoft's online token parser https://jwt.ms/ and parsed my token, I see the roles like
"roles": [
"Mail.ReadWrite",
"User.ReadWrite.All",
"SecurityEvents.Read.All",
"Mail.ReadBasic.All",
"Group.Read.All",
"MailboxSettings.Read",
"Group.ReadWrite.All",
"SecurityEvents.ReadWrite.All",
"User.Invite.All",
"Directory.Read.All",
"User.Read.All",
"Domain.Read.All",
"GroupMember.Read.All",
"Mail.Read",
"User.Export.All",
"IdentityRiskyUser.Read.All",
"Mail.Send",
"User.ManageIdentities.All",
"MailboxSettings.ReadWrite",
"Organization.Read.All",
"GroupMember.ReadWrite.All",
"IdentityRiskEvent.Read.All",
"Mail.ReadBasic",
"Reports.Read.All"
]
but not the Policy.Read.All
Update: Getting auth token code is
$guzzle = new \GuzzleHttp\Client();
$url = 'https://login.microsoftonline.com/'.env("TANANT_ID").'/oauth2/token?api-version=beta';
$token = json_decode($guzzle->post($url, [
'form_params' => [
'client_id' => env("CLIENT_ID"),
'client_secret' => env("CLIENT_SECRET"),
'resource' => 'https://graph.microsoft.com/',
'grant_type' => 'client_credentials',
],
])->getBody()->getContents());
// echo $token->access_token;
Session::put('my_token', $token->access_token);
When you're requesting the token, you need to supply a scope URL,
https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow#get-a-token
So as a basic example (this might not give the permission you need) but shows what your missing.
$guzzle = new \GuzzleHttp\Client();
$url = 'https://login.microsoftonline.com/'.env("TANANT_ID").'/oauth2/token?api-version=beta';
$token = json_decode($guzzle->post($url, [
'form_params' => [
'client_id' => env("CLIENT_ID"),
'client_secret' => env("CLIENT_SECRET"),
'resource' => 'https://graph.microsoft.com/',
'scope' => 'https://graph.microsoft.com/.default',
'grant_type' => 'client_credentials',
],
])->getBody()->getContents());
// echo $token->access_token;
Session::put('my_token', $token->access_token);
specifically notice that i have added
'scope' => 'https://graph.microsoft.com/.default', to your form params
Looks like you don't have Policy.Read.All permission , could you please cross check permission through azure portal and provide the required permission and try again.
Thanks
I have a website where my clients can view their invoices and upload design assets related to the invoice. I want to create a PHP form which uploads the files to OneDrive, instead of storing them on our web server.
I have followed the instructions in this StackOverflow answer to get started.
I have created the app in Microsoft Azure, and entered the appropriate Application (client) ID, Object ID, and Directory (tenant) ID. I am using a client secret to authorize the application, and submitting a POST request using my account's email and password to get the access token.
The relevant code for my upload form looks like this:
if (isset($_FILES['uploads'])) {
$guzzle = new \GuzzleHttp\Client();
$tenantId = 'xxxxxx';
$clientId = 'xxxxxx';
$clientSecret = 'xxxxxx';
$url = 'https://login.microsoftonline.com/' . $tenantId . '/oauth2/token';
$user_token = json_decode($guzzle->post($url, [
'form_params' => [
'client_id' => $clientId,
'client_secret' => $clientSecret,
'resource' => 'https://graph.microsoft.com/',
'grant_type' => 'password',
'username' => 'xxxxxx#companydomain.com',
'password' => 'xxxxxx'
],
])->getBody()->getContents());
$user_accessToken = $user_token->access_token;
$graph = new Graph();
$graph->setAccessToken($user_accessToken);
foreach ($_FILES['uploads']['name'] as $key => $name) {
try {
$graph->createRequest(
"PUT", "/drive/root:/Documents/".$_FILES['uploads']['name'][$key].":/content"
)->upload(
$_FILES['uploads']['tmp_name'][$key]
);
} catch (Exception $e) {
var_dump($e);
}
}
}
This code throws an exception, showing the following error message when I try to upload a :
Client error: `PUT https://graph.microsoft.com/v1.0/drive/root:/Documents/Screen%20Shot%202022-10-30%20at%204.03.44%20PM.png:/content` resulted in a `403 Forbidden` response
In the Azure API Permissions, I have granted the Files.Read.All, Files.ReadWrite.All, and User.Read permissions. However, when I check the access token in https://jwt.ms/, I just see "scp": "User.Read".
So it looks like my access token might not have the correct permissions, but I can see that I do have permissions to read and write files when I look at the API Permissions page in Azure.
How can I further debug this issue and find a solution to upload files from my server to OneDrive?
Thanks to Nikolay's comment, I added a scope parameter to form_params and that fixed it.
I also changed the grant_type to client_credentials, and removed the username/password authorization.
$user_token = json_decode($guzzle->post($url, [
'form_params' => [
'client_id' => $clientId,
'client_secret' => $clientSecret,
'resource' => 'https://graph.microsoft.com/',
'grant_type' => 'client_credentials',
'scope' => 'https://graph.microsoft.com/.default'
],
])->getBody()->getContents());
$user_accessToken = $user_token->access_token;
I try to send a message to a specific channel in teams.
It works perfectly with 'https://developer.microsoft.com/de-de/graph/graph-explorer'.
For reciving the access token i do the following. This part works, because i can retrieve user information and other things with it.
$guzzle = new \GuzzleHttp\Client(['verify' => false]);
$tenantId = '<tenant_id>';
$clientId = '<client_id>';
$clientSecret = '<client_secret>';
$url = 'https://login.microsoftonline.com/' . $tenantId . '/oauth2/token?api-version=1.0';
$token = json_decode($guzzle->post($url, [
'form_params' => [
'client_id' => $clientId,
'client_secret' => $clientSecret,
'resource' => 'https://graph.microsoft.com/',
'grant_type' => 'client_credentials',
],
'verify' => false
])->getBody()->getContents());
$accessToken = $token->access_token;
This part now is the one that produces the error
$graph = new Graph();
$graph->setAccessToken($accessToken);
$url = '/teams/<team_id>/channels/<channel_id>/messages';
$queryParams = [
'body' => [
'content' => 'foo'
]
];
$info = $graph->setApiVersion("beta")->createRequest("POST", $url)
->addHeaders(array("Content-Type" => "application/json"))
->attachBody($queryParams)
->setReturnType(BetaModel\User::class)
->execute();
echo '<pre>';
print_r($info);
This produces the following error
{
"error": {
"code": "UnknownError",
"message": "",
"innerError": {
"date": "2020-11-11T10:14:03",
"request-id": "<request_id>",
"client-request-id": "<client_request_id>"
}
}
}
The teams id and the channel id are correct, i can retrieve them by using
/users/<user_id>/joinedTeams
and
/teams/<teams_id>/channels
and as mentioned earlier, it works in the graph explorer page.
I know that i somehow need to send the message in an user context, but i can't make it work, and i can't find useful informations, so i am pleased for any. Thanks in advance!
This api call currently does not support application permissions, so you cannot use the client credential flow to obtain a token. You need to grant delegated permissions to the application, and then use the auth code flow to obtain the token. see:here.
I try to implement a php client, access a mailbox of a user with graph api. Because it's a background service, which should fetching specific mails attachment, it must run with grant type password.
So far, I got it really easy working make a login with thephpleague/oauth2-client and grant type client_credentials:
$provider = new \League\OAuth2\Client\Provider\GenericProvider([
'clientId' => '...',
'clientSecret' => '...',
'redirectUri' => 'https://login.microsoftonline.com/common/oauth2/nativeclient',
'urlAuthorize' => null,
'urlAccessToken' => 'https://login.microsoftonline.com/.../oauth2/token?api-version=1.0',
'urlResourceOwnerDetails' => 'https://graph.microsoft.com/v1.0/me',
]);
$accessToken = $provider->getAccessToken('client_credentials');
Now I try it with grant type password, but it fails:
$provider = new \League\OAuth2\Client\Provider\GenericProvider([
'clientId' => '...',
'clientSecret' => '...',
'redirectUri' => 'https://login.microsoftonline.com/common/oauth2/nativeclient',
'urlAuthorize' => null,
'urlAccessToken' => 'https://login.microsoftonline.com/.../oauth2/token?api-version=1.0',
'urlResourceOwnerDetails' => 'https://graph.microsoft.com/v1.0/me',
]);
$accessToken = $provider->getAccessToken('password', [
'username' => '...',
'password' => '...',
]);
Response I get: invalid_request. Google that error, I come to https://learn.microsoft.com/de-de/azure/active-directory/develop/v2-oauth2-auth-code-flow which tells me, I should fix my request.
Now... somehow it's hard, finding a) a ressource telling which urls are right and b) finding a tutorial, tell how I add right a app so I can get it working (maybe also a result, because the o365 layout changes fast...)
Does anyone have a idea, what the right parameters are and what I must do in the Azure Active Directory Admin Center so its working?
My goal is "only", access a users mailbox and get attachments from existing mails. I think, when I can authenticate successfully, all other things are easy (hope so).
Please refer to the official tutorial: Authenticate with the Microsoft Graph service.
To authenticate as an application you can use the Guzzle HTTP client, which comes preinstalled with this library, for example like this:
<?php
require __DIR__ . '/vendor/autoload.php';
$guzzle = new \GuzzleHttp\Client();
$tenantId = 'your_tenanet_id, e4c9ab4e-****-****-****-230ba2a757fb';
$clientId = 'your_app_id_registered_in_portal, dc175b96-****-****-****-ea03e56da5e7';
$clientSecret = 'app_key_generated_in_portal, /pGggH************************Zr732';
$url = 'https://login.microsoftonline.com/' . $tenantId . '/oauth2/token';
$user_token = json_decode($guzzle->post($url, [
'form_params' => [
'client_id' => $clientId,
'client_secret' => $clientSecret,
'resource' => 'https://graph.microsoft.com/',
'grant_type' => 'password',
'username' => 'your_user_id, jack#***.onmcirosoft.com',
'password' => 'your_password'
],
])->getBody()->getContents());
$user_accessToken = $user_token->access_token;
$graph = new Graph();
$graph->setAccessToken($user_accessToken );
$response = $graph->createRequest('Get','/me/messages')
->setReturnType(Model\Message::class)
->execute();
?>
Note that the resource should be https://graph.microsoft.com/
As there are several changes in LinkedIn People Search API as of now,please explain how to use this API for people search by company and etc...
I have read
https://developer-programs.linkedin.com/documents/people-search-api
and other document but not getting connection with search link and API key and all.As explained in document we can search some thing like this
https://api.linkedin.com/v1/people-search?keywords=Princess
but where we need to put API KEY and all. I am new to APIs so please if possible explain this.
I have also go through other blogs but they are old and not applicable.
If possible please also mention possibility and things we cann't do.
LinkedIn's People Search API has not been available to the open developer community since May, 2015.
You can apply to be a developer partner at: https://developer.linkedin.com/partner-programs/apply
If you are an official partner of LinkedIn and still have access to that API, you should follow up with your assigned Partner Engineering representative for further assistance, rather than public forums.
Use Postman to follow this tutorial:
https://developer.linkedin.com/docs/oauth2
On succes you can click to get the PHP code you need to create the request with OATH2. I have no developer account on LinkedIn so that part you have to do yourself.
The example GET request would look like this in PHP:
Step 2
<?php
$client = new http\Client;
$request = new http\Client\Request;
$request->setRequestUrl('https://www.linkedin.com/uas/oauth2/authorization');
$request->setRequestMethod('GET');
$request->setQuery(new http\QueryString(array(
'response_type' => 'code',
'client_id' => '123456789',
'redirect_uri' => 'https://www.example.com/auth/linkedin',
'state' => '987654321',
'scope' => 'r_basicprofile'
)));
$request->setHeaders(array(
'cache-control' => 'no-cache'
));
$client->enqueue($request)->send();
$response = $client->getResponse();
echo $response->getBody();
Step 3
<?php
$client = new http\Client;
$request = new http\Client\Request;
$request->setRequestUrl('https://www.linkedin.com/uas/oauth2/accessToken');
$request->setRequestMethod('POST');
$request->setQuery(new http\QueryString(array(
'grant_type' => 'authorization_code',
'code' => '987654321',
'redirect_uri' => 'https://www.myapp.com/auth/linkedin',
'client_id' => '123456789',
'client_secret' => 'shhdonottell'
)));
$request->setHeaders(array(
'postman-token' => 'bee6f5d7-a0e6-4a76-6ef8-930c95af53a6',
'cache-control' => 'no-cache',
'content-type' => 'application/x-www-form-urlencoded',
'host' => 'www.linkedin.com'
));
$client->enqueue($request)->send();
$response = $client->getResponse();
echo $response->getBody();