Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Oauth is not working with Exchange 2013 #250

Open
Matt504 opened this issue Jul 3, 2023 · 0 comments
Open

Oauth is not working with Exchange 2013 #250

Matt504 opened this issue Jul 3, 2023 · 0 comments

Comments

@Matt504
Copy link

Matt504 commented Jul 3, 2023

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant