Connect EWS API with Modern Authentication using PowerShell

Exchange Web Services (EWS) was launched with support for Basic Authentication. Over the last few years, Microsoft pushing us to stop using basic authentication and recommend using Modern Authentication (OAuth 2.0). Here will explore how to get EWS Access Token with Modern authentication and use the token to connect EWS API.

We have used the EWS API 2.2 DLL in the below script, install the EWS Managed API 2.2 and ensure the DLL file (Microsoft.Exchange.WebServices.dll) is available in the correct location. You can download the EWS API 2.2 setup from this GitHub link.

Summary

Connect EWS API using Basic Authentication

The following script uses the basic authentication to connect the Exchange Online mailbox using Exchange Web Services (EWS).

#Import EWS API dll
Import-Module "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"

#Provide the mailbox id (email address) to connect
$MailboxName ="[email protected]"
 
#Provide the mailbox user credentials
$PSCredential = Get-Credential
 
$Service = [Microsoft.Exchange.WebServices.Data.ExchangeService]::new()
#Use Basic Authentication
$Service.Credentials = New-Object System.Net.NetworkCredential($PSCredential.UserName.ToString(),$PSCredential.GetNetworkCredential().password.ToString())

#Check EWS connection
$Service.Url = "https://outlook.office365.com/EWS/Exchange.asmx"
$Service.AutodiscoverUrl($MailboxName,{$true})
# EWS connection is Success if no error returned.

Connect EWS API using Modern Authentication

To access a mailbox with EWS API using modern authentication, we should have already registered an Azure AD app and configured the Delegated permission | EWS.AccessAsUser.All, and then we should acquire an OAuth Access Token with this application.

Once you have acquired the required access token, set the token to the Credentials property of the $Service object to consume the EWS API with modern authentication.

Import-Module 'C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll'

#Provide the mailbox id (email address) to connect
$MailboxName ="[email protected]"

#Get Access Token with the scope "https://outlook.office.com/EWS.AccessAsUser.All"
$EWSAccessToken="eyJ0eXAi...." #Refer to the below section: "Get EWS Access Token..."

$Service = [Microsoft.Exchange.WebServices.Data.ExchangeService]::new()

#Use Modern Authentication
$Service.Credentials = [Microsoft.Exchange.WebServices.Data.OAuthCredentials]$EWSAccessToken

#Check EWS connection
$Service.Url = "https://outlook.office365.com/EWS/Exchange.asmx"
$Service.AutodiscoverUrl($MailboxName,{$true})
#EWS connection is Success if no error returned.

Get EWS Access Token and Connect Mailbox using the OAuth Token

The following commands get Access Token for the Delegated permissions. You should have already created an Azure AD app and configured the Delegated permission “EWS.AccessAsUser.All“.  You can refer to this post for more details: How to Register and Configure Azure AD application.

We can use the MSAL.PS library to acquire tokens from the Microsoft identity platform. Run the following command in PowerShell to install this module.

Install-Module -Name MSAL.PS

Run the following commands to get EWS Access Token with your Azure AD app.

#Provide your Office 365 Tenant Id or Tenant Domain Name
$TenantId = "contoso.onmicrosoft.com"
   
#Used the Microsoft Graph PowerShell app id. You can create and use your own Azure AD App id if needed.
$AppClientId="14d82eec-204b-4c2f-b7e8-296a70dab67e" 

$MsalParams = @{
    ClientId = $AppClientId
    TenantId = $TenantId    
    Scopes   = "https://outlook.office.com/EWS.AccessAsUser.All"    
}

$MsalResponse = Get-MsalToken @MsalParams
$EWSAccessToken  = $MsalResponse.AccessToken

Now you have successfully acquired the EWS OAuth Access token with Modern authentication. You can use this token to access your Exchange Online mailbox using the Exchange Web Services (EWS API).

Import-Module 'C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll'

#Provide the mailbox id (email address) to connect
$MailboxName ="[email protected]"

$Service = [Microsoft.Exchange.WebServices.Data.ExchangeService]::new()

#Use Modern Authentication
$Service.Credentials = [Microsoft.Exchange.WebServices.Data.OAuthCredentials]$EWSAccessToken

#Check EWS connection
$Service.Url = "https://outlook.office365.com/EWS/Exchange.asmx"
$Service.AutodiscoverUrl($MailboxName,{$true})
#EWS connection is Success if no error returned.
Advertisement

11 thoughts on “Connect EWS API with Modern Authentication using PowerShell”

  1. Hi,

    Thanks for usefull post! Unfortunatly i’m bouncing against an error when I try the following command:
    $Service.Credentials = [Microsoft.Exchange.WebServices.Data.OAuthCredentials]$EWSAccessToken

    The error states says: “Unable to find type [Microsoft.Exchange.WebServices.Data.OAuthCredentials].”

    Does this has to do something with the dll I imported? I’m using the EWS 2.2.

    Kind regards,

    Reply
  2. Hi
    I’m getting
    Exception calling “FindFolders” with “2” argument(s): “ExchangeImpersonation SOAP header must be present for this type of OAuth token.”

    On $FoldersResult = $Service.FindFolders([Microsoft.Exchange.Webservices.Data.WellKnownFolderName]::Inbox, $Folderview)

    Reply
  3. Hi,

    I’m receiving the following error for the AutoDiscoverUrl:

    $Service.AutodiscoverUrl($MailboxName,{$true})
    Exception calling “AutodiscoverUrl” with “2” argument(s): “The Autodiscover service couldn’t be located.”
    At line:1 char:1
    + $Service.AutodiscoverUrl($MailboxName,{$true})
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : AutodiscoverLocalException

    I have EWS 2.2 installed and pointed to the Microsoft.Exchange.WebServices.dll. Am I missing something else?

    Thanks

    Reply
    • 1. Ensure that you have provided the correct email address.
      2. Ensure that you have provided the correct user credentials
      3. If you tried modern authentication, then just check with the basic authentication and vice-versa to ensure the credentials are correct.

      Reply
  4. Hi. I am trying to use a Secret ID with the $MsalParams object and I get a token (which doesn’t look any different each time I run the get token portion of the code), and when I do the AudoDiscoverUrl() I get this error:
    Exception calling “AutodiscoverUrl” with “2” argument(s): “The expected XML node type was XmlDeclaration, but the actual type is Element.”
    If I remove the Secret ID parameter, it works, but I have to manually enter username and password each time the login prompt appears (after 60 mins of default expiration).
    I am trying to automate all this so I can pull email attachments from an AD mailbox.
    Thanks

    Reply
  5. If I use this code do I need to change the Scope parameter value because I use EWS instead Graph API? Just to make sure I will get EWS Token.

    #Provide your Office 365 Tenant Domain Name or Tenant Id
    $TenantId = “contoso.onmicrosoft.com”
    #$TenantId = “xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”

    #Provide Application (client) Id of your app
    $AppClientId=”xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”

    #Provide Application client secret key
    $ClientSecret =”xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”

    $RequestBody = @{client_id=$AppClientId;client_secret=$ClientSecret;grant_type=”client_credentials”;scope=”https://graph.microsoft.com/.default”;}
    $OAuthResponse = Invoke-RestMethod -Method Post -Uri https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token -Body $RequestBody
    $AccessToken = $OAuthResponse.access_token

    Then after I will this code you provide:

    Import-Module ‘C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll’

    #Provide the mailbox id (email address) to connect
    $MailboxName =”[email protected]

    $Service = [Microsoft.Exchange.WebServices.Data.ExchangeService]::new()

    #Use Modern Authentication
    $Service.Credentials = [Microsoft.Exchange.WebServices.Data.OAuthCredentials]$AccessToken

    #Check EWS connection
    $Service.Url = “https://outlook.office365.com/EWS/Exchange.asmx”
    $Service.AutodiscoverUrl($MailboxName,{$true})
    #EWS connection is Success if no error returned.

    Reply

Leave a Comment