I am trying to send an email using Microsoft GraphAPI inside my Laravel app. I am able to successfully get an access token through this function.
public function getAccessToken() {
$tenantId = 'someID';
$scope = 'https://graph.microsoft.com/.default';
$appId = 'someAppID';
$secretId = 'secretID';
$secret = 'someSecretString';
$url = "https://login.microsoftonline.com/{$tenantId}/oauth2/v2.0/token?scope={$scope}&client_id={$secretId}";
$config = [
'grant_type' => 'client_credentials',
'client_id' => $appId,
'client_secret' => $secret,
'scope' => $scope,
];
$response = Http::asForm()->post($url, $config);
$data = $response->json();
$token = Arr::get($data, 'access_token');
return $token;
}
When I decode the received access token using jwt.io, I get this.
{
"aud": "https://graph.microsoft.com",
"iss": "https://sts.windows.net/**********************/",
"iat": 1727514977,
"nbf": 1727514977,
"exp": 1727518877,
"aio": "k2BgYGiT2uLUtyghU2/p5IaN16YKAAA=",
"app_displayname": "Mailer Oauth2",
"appid": "***************************",
"appidacr": "1",
"idp": "https://sts.windows.net/***************************/",
"idtyp": "app",
"oid": "c4addf3b-ab49-4270-bbf8-a2a4d832c560",
"rh": "0.ARMBkUlDtYDgK02i7VB0sFJDagMAAAAAAAAAwAAAAAAAAAAUAQA.",
"roles": [
"Mail.ReadWrite",
"Mail.ReadBasic.All",
"Mail.Read",
"Mail.Send",
"Mail.ReadBasic"
],
"sub": "c4addf3b-ab49-4270-bbf8-a2a4d832c560",
"tenant_region_scope": "EU",
"tid": "*************************************",
"uti": "bC3CrECPGEOLobarnNDrAA",
"ver": "1.0",
"wids": [
"0997a1d0-0d1d-4acb-b408-d5ca73121e90"
],
"xms_idrel": "10 7",
"xms_tcdt": 1727427193
}
Under the roles attribute, I can see that Mail.Send is present.
When I try to send an email using this code
$emailData = [
'message' => [
'subject' => [$this->subject],
'body' => [
'contentType' => 'HTML',
'content' => $newTemplate,
]
],
'bccRecipients' => [
[
'emailAddress' => [
'address' => $this->mails->toArray()
]
]
],
'attachments' => [
[
'@odata.type' => '#microsoft.graph.fileAttachment',
'name' => basename($srcImage),
'contentBytes' => base64_encode(file_get_contents($srcImage)),
'contentId' => 'image',
],
],
];
$response = Http::withToken($this->token)
->post("https://graph.microsoft.com/v1.0/users/{$this->email->email}/sendMail", [
'message' => $emailData['message'],
'saveToSentItems' => 'true',
]);
But I receive this error
{"error":{"code":"OrganizationFromTenantGuidNotFound","message":"The tenant for tenant guid '***************************' does not exist.","innerError":{"oAuthEventOperationId":"d630a3bf-f7b2-4373-872f-6618f21d7429","oAuthEventcV":"bXHKl4PYUfE8FIF62ShkHA.1.1","errorUrl":"https://aka.ms/autherrors#error-InvalidTenant","requestId":"e131128d-d6f1-43da-85ac-88799cac7cac","date":"2024-09-28T09:30:39"}
}}
This is a screenshot from my Azure app (App Permissions tab)
I have searched the internet and found out that I should use keyword 'common' when obtaining an access token, instead of using actual tenantID... I have tried it, but I receive error that tenantID is invalid and I can't obtain access token.
https://login.microsoftonline.com/common/oauth2/v2.0/token?scope={$scope}&client_id={$secretId}
I have selected multitenancy inside the Azure app, as you can see on the screenshot:
Honestly, I am not very experienced with Microsoft Azure... I assume the problem might be in some Azure definitions, but I have no idea where. Any help is appreciated.
The problem was in the getAccessToken()
function. I was sending a request to the wrong endpoint, and therefore the obtained access token was wrong. The correct endpoint URL is
https://login.microsoftonline.com/common/oauth2/v2.0/token
More info on this link: https://learn.microsoft.com/en-us/graph/auth-v2-user?tabs=http