php-ews
php-ews copied to clipboard
Oauth is not working with Exchange 2013
Hi @Garethp, first of all thank you for making this SOAP API to communicate with EWS, it does me a great service in making my web application which my manager would use to view employee appointments based on availability. The problem that I currently have is that when I tried to switch from API::withUsernameAndPassword
to API::withCallbackToken
, I get this error : Fatal error: Uncaught garethp\ews\API\Exception\UnauthorizedException in C:\xampp\htdocs\php-ews-fork\src\API\ExchangeWebServices.php:454
.
What I did
I tried using your code in examples/basic/authentificatingWithOauth.php and did a few tweaks :
<?php
session_start();
require_once "../../vendor/autoload.php";
use garethp\ews\API;
use garethp\ews\API\ExchangeWebServicesAuth;
use garethp\ews\API\ExchangeWebServices;
$tokenEndpoint = 'https://login.microsoftonline.com/tenant-id/oauth2/v2.0/token';
$authorizationEndpoint = 'https://login.microsoftonline.com/tenant-id/oauth2/v2.0/authorize';
$clientId = '...';
$clientSecret = '...';
$redirectUri = 'http://localhost/php-ews-fork/examples/basic/authenticatingWithOAuth.php';
$resource = 'https://mail.company.com';
//The first step is to get your authorization code. It's a one time use code that needs to be granted by the user. You
//should have your own way to get it, but just for the sake of example I'm going to show you a way to do that
if (!isset($_SESSION['token']) && !isset($_GET['code'])) {
$redirect = $authorizationEndpoint .
'?response_type=code' .
'&client_id=' . urlencode($clientId) .
'&redirect_uri=' . urlencode($redirectUri) .
'&scope=' . urlencode('EWS.AccessAsUser.All');
header("Location: {$redirect}");
exit();
}
elseif (isset($_GET['code'])) {
//Once you have your code, you can exchange it for a token. The code can only be used once, so you don't store the code.
//The token is what we'll be using for the duration of the session, so you should store between pages.
$code = $_GET['code'];
$token = ExchangeWebServicesAuth::getTokenFromAuthorizationCode(
$clientId,
$clientSecret,
$code,
$redirectUri,
$tokenEndpoint
);
$_SESSION['token'] = $token;
}
//Once you have your token you can just create your API as easily as before, but with the token instead of with a
//username and a password
$token = $_SESSION['token'];
echo $token;
$api = API::withCallbackToken('mail.company.com', $token);
$calendar = $api->getCalendar();
...
The token here is displayed correctly, however, when I call getCalendar(), I get the error.
I also, change a few things in the ExchangeWebServicesAuth.php file :
public static function getTokenFromAuthorizationCode(
$clientId,
$clientSecret,
$authorizationCode,
$redirectUri,
$tokenEndPoint = 'https://login.microsoftonline.com/common/oauth2/v2.0/token'
) {
$postOptions = array(
'http_errors' => false,
'form_params' => array(
'client_id' => $clientId, //Don't need resource nor client_secret because Client is public nor resource
'code' => $authorizationCode,
'redirect_uri' => $redirectUri,
'grant_type' => 'authorization_code'
)
);
$client = new Client();
$response = $client->request('POST', $tokenEndPoint, $postOptions);
$response = $response->getBody()->__toString();
$response = json_decode($response);
return $response->access_token;
}
Note
I did find two quick fixes for this issue :
- Changed the API call to
API::withUsernameAndPassword
but that was not quite what I was looking for - Changed the $server to an Office 365 Outlook account like this :
$api = API::withCallbackToken('outlook.office365.com', $token);
but I was looking to communicate with an old Exchange Outlook version : 2013, not the 365 one.
I did a lot of research but find nothing relevant to my problem so, if you or anyone had any clues as to what to do, anything at all, that would be a great help to me.