Search code examples
azureazure-active-directoryexchangewebservicesadalazure-ad-msal

Get access token to EWS and User.Read.All


I try to get an access token to the scopes: 'https://outlook.office.com/EWS.AccessAsUser.All', 'User.Read.All'.

  1. If I use the following URL to get authorization code: https://login.microsoftonline.com/common/oauth2/v2.0/authorize?scope=https%3A%2F%2Foutlook.office.com%2FEWS.AccessAsUser.All+User.Read.All&client_id=AAA...ZZZ&redirect_uri=http%3A%2F%2Flocalhost%3A9999&response_type=code an access token response is:
{
'scope': 'https://outlook.office.com/EWS.AccessAsUser.All https://outlook.office.com/User.Read https://outlook.office.com/User.Read.All', 
'ext_expires_in': 3599, 
'expires_in': 3599, 
'token_type': 'Bearer', 
'access_token': '123...zzz'
}

Please note the scope in the response. This access token works in EWS requests without errors. But requests to MS Graph API return:

{
    "error": {
        "code": "InvalidAuthenticationToken",
        "innerError": {
            "date": "2020-02-15T19:45:50",
            "request-id": "4542b743-05e1-4555-b612-e0419c3b624b"
        },
        "message": "Access token validation failure. Invalid audience."
    }
}
  1. If I use the following URL to get authorization code: https://login.microsoftonline.com/common/oauth2/v2.0/authorize?redirect_uri=http%3A%2F%2Flocalhost%3A9999&client_id=AAA...ZZZ&scope=User.Read.All+https%3A%2F%2Foutlook.office.com%2FEWS.AccessAsUser.All&response_type=code an access token response is:
{
'scope': 'EWS.AccessAsUser.All User.Read User.Read.All profile openid email', 
'ext_expires_in': 3599, 
'access_token': '0123...zzz',
'token_type': 'Bearer',
 'expires_in': 3599
}

Again, please note the scope in the response. This access token works in MS Graph requests without errors. But EWS requests return the error:

Error: Microsoft.Exchange.WebServices.Data.ServiceRequestException: The request failed. The remote server returned an error: (401) Unauthorized. ---> System.Net.WebException: The remote server returned an error: (401) Unauthorized.
   at System.Net.HttpWebRequest.GetResponse()
  1. MSAL doesn't work in this case too.
var pcaOptions = new PublicClientApplicationOptions
{
  ClientId = _appId,
  TenantId = _tenantId
};
var pca = PublicClientApplicationBuilder.CreateWithApplicationOptions(pcaOptions).Build();
var ewsScopes = new string[] { "User.Read.All", "https://outlook.office.com/EWS.AccessAsUser.All" };
var authResult = await pca.AcquireTokenInteractive(ewsScopes).ExecuteAsync();
foreach (var s in authResult.Scopes)
{
    Console.WriteLine($"Scope: {s}");
}

If https://outlook.office.com/EWS.AccessAsUser.All is in the scope list, an access token works in EWS requests. A request to MS Graph returns the error:

Error: Status Code: Unauthorized
Microsoft.Graph.ServiceException: Code: InvalidAuthenticationToken
Message: Access token validation failure. Invalid audience.

Solution

  • According to the information you provided, you want to request access token to call Microsoft Graph and Outlook Rest API and you use one request to request the access token for the two API. But we cannot do that. Because All the Microsoft Provided authentication flow does not allow multiple Resource/Scope while you would request for token. In other words, one request just can request the access token for Microsoft graph or Outlook Rest API. For more details, please refer to Accessing Multiple resources in a single authorization request