Exchange Managed API and OAuth Authentication

Hallo zusammen,

In der Vergangenheit habe ich einige Scrips für Exchange Web Services (EWS) geschrieben. Da die Deaktivierung von Basic Auth immer näher rückt (auch wenn das jetzt wieder ein bisschen zurückgestellt wurde), macht es Sinn, mich mit der OAuth Authentifizierung von EWS zu beschäftigen.

Authenticate an EWS application by using OAuth
https://docs.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth

In Azure AD habe ich eine Applikation erstellt, welche keine Rechte besitzt.

Um die EWS Impersonation zu setzen, muss man das Manifest bearbeiten und zwar den Parameter "requiredResourceAccess"

Es muss folgendes dort eingefügt werden

"requiredResourceAccess": [
 {
 "resourceAppId": "00000002-0000-0ff1-ce00-000000000000",
 "resourceAccess": [
  {
   "id": "dc890d15-9560-4a4c-9b7f-a736ec74ec40",
   "type": "Role"
  }
  ]
 }
],

Das bewirkt, dass das "full_access_as_app" als Application Permission vergeben wird. Dann muss man noch den "Grant Admin Consent" durchführen.

Damit ist die Berechtigung der Applikation abgeschlossen.

Nun ein bisschen Code. Man beachte hier den Scope https://outlook.office365.com/.default

###############################################################################
# Get AccessToken
###############################################################################

#Variables
$ClientID = "9a8d72df-686a-496c-bc5e-a147d813abd1"
$ClientSecret = "MyClientSecret"
$tenantID = "icewolfch.onmicrosoft.com"
$scope = "https://outlook.office365.com/.default"
$authority = "https://login.microsoftonline.com/$tenantID/oauth2/v2.0/token"

$Body = @{
  "grant_type"    = "client_credentials";
  "client_id"     = "$ClientID";
  "client_secret" = "$ClientSecret";
  "scope"      = "$scope";
}

#Get AccessToken
$result = Invoke-RestMethod -Method POST -uri $authority -Body $body
$AccessToken = $result.access_token
$AccessToken

Or you can use MSAL to get the Token

###############################################################################
# Get AccessToken MSAL
###############################################################################
#Install-Module MSAL.PS
#Authenticate with Certificate
$AppID = "
9a8d72df-686a-496c-bc5e-a147d813abd1"
$tenantID = "icewolfch.onmicrosoft.com"
$CertificateThumbprint = "07eff3918f47995eb53b91848f69b5c0e78622fd"
$scope = "https://outlook.office365.com/.default"
$RedirectUri = "https://login.microsoftonline.com/common/oauth2/nativeclient"

$Certificate = Get-ChildItem -Path cert:\CurrentUser\my\$CertificateThumbprint
$Token = Get-MsalToken -ClientId $AppID -ClientCertificate $Certificate -TenantId $TenantID -Scope $Scope -RedirectUri $RedirectUri
$AccessToken = $Token.AccessToken
$AccessToken

Verbinden mit EWS und OAuth über die EWS Managed API

###############################################################################
#EWS OAuth Auth
###############################################################################

#Office 365 Icewolf
[string]$EWSURL = "https://outlook.office365.com/EWS/Exchange.asmx"
[string]$TargetMailbox = "postmaster@icewolf.ch"

# Load EWS Managed API DLL  and Connect to Exchange
[string]$EwsApiDll = "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"
Import-Module -Name $EwsApiDll

#Create EWS Object and connect with OAuth
$EWService = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013_SP1)
$EWService.Url = $EWSURL
$OAuthCredentials = New-Object Microsoft.Exchange.WebServices.Data.OAuthCredentials($AccessToken)
$EWService.Credentials = $OAuthCredentials

#Connect to another Mailbox
$EWService.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $TargetMailbox)

Folder auflisten lassen

###############################################################################
# List Folders
###############################################################################
$FolderView = New-Object Microsoft.Exchange.WebServices.Data.FolderView(300)
$FolderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep
$Folders = $EWService.FindFolders([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$FolderView)
$Folders | ft DisplayName, id

Die Applikation hat einen ApplicationAccessPolicy zugewiesen. Damit kann sie nur auf die Mailboxen der Mitglieder der Gruppe zugreifen und nicht auf alle Mailboxen der Exchange Online Organisation.

New-ApplicationAccessPolicy
https://docs.microsoft.com/en-us/powershell/module/exchange/new-applicationaccesspolicy?view=exchange-ps

Versuche ich nun auf eine Mailbox ausserhalb der ApplicationPolicy zuzugreifen, erhalte ich eine Fehlermeldung

[string]$TargetMailbox = "max.muster@icewolf.ch"
$EWService.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $TargetMailbox)

###############################################################################
# List Folders
###############################################################################
$FolderView = New-Object Microsoft.Exchange.WebServices.Data.FolderView(300)
$FolderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep
$Folders = $EWService.FindFolders([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$FolderView)

Grüsse
Andres Bohren