Search code examples
powershelloauthexchange-serverexchangewebservices

Convert Powershell Exchange EWS script authentication to Oauth getting error: The audience claim value is invalid for current resource


I'm trying to convert some existing Exchange Online EWS scripts to use Oauth. I'm able to request an access token, but when I try to work with a mailbox it errors with the following. I appreciate your help!

x-ms-diagnostics: 2000003;reason="The audience claim value is invalid for current resource. Audience claim is 'https://graph.microsoft.com', request url is 'https://outlook.office365.com/EWS/ Exchange.asmx' and resource type is 'Exchange'.";error_category="invalid_resource"

Here's the code:

## Request an access token

# Define AppId, secret and scope, your tenant name and endpoint URL
$AppId = 'APP-ID HERE'
$AppSecret = 'SECRET HERE'
$Scope = "https://graph.microsoft.com/.default"
$TenantName = "OurDomain.onmicrosoft.com"
$Url = "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token"

# Add System.Web for urlencode
Add-Type -AssemblyName System.Web

# Create body
$Body = @{
    client_id = $AppId
    client_secret = $AppSecret
    scope = $Scope
    grant_type = 'client_credentials'
}

# Splat the parameters for Invoke-Restmethod for cleaner code
$PostSplat = @{
    ContentType = 'application/x-www-form-urlencoded'
    Method = 'POST'

    # Create string by joining bodylist with '&'
    Body = $Body
    Uri = $Url
}

# Request the token!
$Request = Invoke-RestMethod @PostSplat

#######################

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

## Create the Exchange Service object with Oauth creds
$Service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService -ArgumentList Exchange2013_SP1
$service.Url= new-object Uri("https://outlook.office365.com/EWS/Exchange.asmx")
$Service.TraceEnabled = $true
$Service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.OAuthCredentials($Request.access_token)

#####################

$Email = "[email protected]"

# Set the WellKnownFolder
$FolderId = [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox

# Bind to WellKnownFolder Notes
$folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($Service, $folderId)

Write-Host "$($Email): $($folderName):  " -NoNewline 
$folder.archivetag.RetentionId.Guid     

Solution

  • In your script you will need to change the scope original scope from

    $Scope = "https://graph.microsoft.com/.default"
    

    to

    $Scope = "https://outlook.office365.com/.default"
    

    The rest of your code isn't using the Graph so you don't need to get an access token for something your not using. Also because your using an App Secret you would be generating an App Only token which means you won't have a refresh token anyway. The two things that is missing from your EWS code is you need to use EWS Impersonation and you should also always set the X-AnchorMailbox header eg you would have

    $service.HttpHeaders.Add("X-AnchorMailbox", "[email protected]")
    $service.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, "[email protected]")