Это действительно хороший обзор этого блога: https://ingogegenwarth.wordpress.com/2018/08/02/ews-and-oauth/#more-5139
Я использовал этот блог, чтобы заставить его работать в наших скриптах PowerShell - с большим количеством проб и ошибок. В следующем примере сценария используется ClientID приложения, зарегистрированный в Azure AD. Если у вас еще нет приложения, зарегистрированного в Azure AD, вы должны сделать это в первую очередь. В Интернете доступны различные руководства по регистрации нового приложения в Azure AD. Чтобы использовать EWS с OAuth, ваше зарегистрированное приложение должно иметь правильные разрешения в Azure AD. У EWS есть два варианта:
- Использовать делегированные разрешения и запрашивать разрешение API «EWS.AccessAsUser.All» в Azure AD - Устаревшие API |Обмен |Делегированные разрешения |EWS.AccessAsUser.All (Доступ к почтовым ящикам как зарегистрированному пользователю через веб-службы Exchange). Это разрешение дает вашему зарегистрированному приложению такой же доступ к почтовым ящикам Exchange, как и вошедшему в систему пользователю. Если вы используете это разрешение, то в первый раз, когда ClientID вашего приложения используется какой-либо службой или учетной записью пользователя для доступа к Exchange Online, соответствующая учетная запись должна подтвердить ClientID посредством интерактивного всплывающего уведомления. Поэтому, прежде чем использовать этот сценарий в автоматическом режиме, вы должны в интерактивном режиме получить доступ к Exchange Online Service, используя ClientID вашего зарегистрированного приложения, и одобрить всплывающее окно авторизации. Самый простой способ сделать это - войти в почтовый ящик с помощью бесплатного приложения Microsoft «EWS Editor» и указать ClientID вашего приложения. Как только ClientID вашего приложения будет утвержден, ваш сценарий может работать полностью автоматически без какого-либо взаимодействия.
- Используйте разрешения приложения и запросите разрешение API «full_access_as_app» в Azure AD - Устаревшие API |Обмен |Делегированные разрешения |EWS.AccessAsUser.All (Доступ к почтовым ящикам как зарегистрированному пользователю через веб-службы Exchange). Это разрешение дает вашему зарегистрированному приложению полный доступ через веб-службы Exchange ко всем почтовым ящикам без зарегистрированного пользователя. Этот тип разрешений дает приложению полный доступ к любому почтовому ящику в службе Exchange Online и должен быть одобрен глобальным администратором Azure AD, предоставляющим «согласие администратора». Затем ваш сценарий будет проходить проверку подлинности в Exchange Online с использованием зарегистрированного идентификатора клиента приложения Azure AD (фактически это имя пользователя) и Client Secret (фактически пароль).
В приведенном ниже примере используется вариант 1. У меня нетпроверенный вариант 2. Какой бы вариант вы ни выбрали, вам нужно будет обработать запрос токена OAuth (пример в приведенном ниже коде) из Azure AD и регулярно проверять и обновлять токен (без примера). Я не сделал этого, так как все наши сценарии EWS просты, быстро запускают сценарии, которые завершаются до обновления токена (обычно в течение 60 минут). Если это то, что вам нужно, вам нужно будет попросить других о помощи. Надеюсь, что это поможет вам выбрать правильный путь ...
Вот пример сценария (основная часть сценария вызывает функцию Get-EWSOAuthToken):
#Variables
$UserPrincipalName = "Enter the UPN of your Service Account ID"
$Password = "Password of your Service Account ID - store this securely"
$ClientIDfromAzureAD = "Client ID of your registered application in Azure AD"
$errRecip = "Email address of recipients to notify via email if errors occur"
$script = "Name of script"
$sender = "Email address of sender - normally the server name where your script runs"
$logfile = "Path and filename to log file"
$smtpServer = "Your SMTP server"
Function Get-EWSOAuthToken
{
<#
.SYNOPSIS
Request an OAuth EWS token from Azure AD using supplied Username and Password
.DESCRIPTION
Request an OAuth EWS token from Azure AD using supplied Username and Password
.PARAMETER UserPrincipalName
The UPN of the user that will authenticate to Azure AD to request the OAuth Token
.PARAMETER Password
The Password (SecureString) of the user that will authenticate to Azure AD to request the OAuth Token
.PARAMETER ADALPath
The full path and filename on the local file system to the ADAL (Active Directory Authentication Library) DLL. This library is installed as part of various modules such as Azure AD, Exchange Online, etc.
.PARAMETER ClientId
Identifier of the client application that is requesting the token. You must register your calling application in Azure AD. This will provide you with a ClientID and RedirectURI
.PARAMETER ConnectionUri
The URI of the Exchange Online EWS endpoint. Default URI of 'https://outlook.office365.com/EWS/Exchange.asmx' is used
.PARAMETER RedirectUri
Address to return to upon receiving a response from the authority. You must register your calling application in Azure AD. This will provide you with a ClientID and RedirectURI
.EXAMPLE
$token = Get-EWSOAuthtokenFromCredential -UserPrincipalName "ABC123@mydomain.com" -Password $mySecurePassword -ClientId "123444454545454767687878787" -RedirectUri "https://dummyredirectdomain.com"
$ews = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService -ArgumentList Exchange2013_SP1 -ErrorAction Stop
$ews.UseDefaultCredentials = $False
$ews.Credentials = [Microsoft.Exchange.WebServices.Data.OAuthCredentials]$token
#>
[CmdletBinding()]
Param
(
[System.String]$UserPrincipalName,
[System.Security.SecureString]$Password,
[System.String]$ADALPath,
[System.String]$ClientId = "123444454545454767687878787",
[System.Uri]$ConnectionUri = "https://outlook.office365.com/EWS/Exchange.asmx",
[System.Uri]$RedirectUri = "https://dummyredirectdomain.com"
)
Begin
{
Write-Host "Starting Get-EWSOAuthTokenFromCredential function..." -ForegroundColor Yellow
#Determine ADAL location based on Azure AD module installation path
If([System.String]::IsNullOrEmpty($ADALPath))
{
Write-Host "Attempting to locate ADAL library..." -ForegroundColor Yellow
$ADALPath = (Get-InstalledModule -Name "AzureAD" -ErrorAction SilentlyContinue | Select-Object InstalledLocation).InstalledLocation
$ADALPath = Join-Path -Path $ADALPath -ChildPath "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
Write-Host "Located library @ '$ADALPath'" -ForegroundColor Yellow
If([System.String]::IsNullOrEmpty($ADALPath))
{
#Get List of installed modules and check Azure AD DLL is available
$tmpMods = Get-Module -ListAvailable | Where-Object {$_.Name -eq "AzureAD"}
If($tmpMods)
{
$ADALPath = Split-Path $tmpMods.Path
$ADALPath = Join-Path -Path $ADALPath -ChildPath "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
Write-Host "Located library @ '$ADALPath'" -ForegroundColor Yellow
}
Else
{
$err = "$($myinvocation.mycommand.name) requires the ADAL Library DLL files ('Microsoft.IdentityModel.Clients.ActiveDirectory.dll') that are installed as part of the 'AzureAD' module! Please install the AzureAD module from the Powershell Gallery. See: 'https://www.powershellgallery.com/packages/AzureAD' for more information"
Throw "$err"
}
}
}
#Load 'Microsoft.IdentityModel.Clients.ActiveDirectory' DLL
Try
{
Import-Module $ADALPath -DisableNameChecking -Force -ErrorAction Stop
Write-Host "Successfully imported ADAL Library" -ForegroundColor Yellow
}
Catch
{
$err = "$($myinvocation.mycommand.name): Could not load ADAL Library DLL '$ADALPath'. Error: $_"
Throw "$err"
}
}
Process
{
try
{
$resource = $connectionUri.Scheme + [System.Uri]::SchemeDelimiter + $connectionUri.Host
$azureADAuthorizationEndpointUri = "https://login.windows.net/common/oauth2/authorize/"
$AuthContext = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext($azureADAuthorizationEndpointUri) -ErrorAction Stop
$AuthCredential = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.UserPasswordCredential($UserPrincipalName, $Password) -ErrorAction Stop
Write-Host "$($myinvocation.mycommand.name): Requesting a new OAuth Token..." -ForegroundColor Yellow
$authenticationResult = ([Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContextIntegratedAuthExtensions]::AcquireTokenAsync($AuthContext, $resource, $clientId, $AuthCredential))
If ($authenticationResult.Status.ToString() -ne "Faulted") {
Write-Host "$($myinvocation.mycommand.name): Successfully retrieved OAuth Token" -ForegroundColor Yellow
}
else {
$err = "$($myinvocation.mycommand.name): Error occurred calling ADAL 'AcquireTokenAysnc' : $authenticationResult.Exception.ToString()"
Throw "$err"
}
}
catch
{
#create object
$returnValue = New-Object -TypeName PSObject
#get all properties from last error
$ErrorProperties =$Error[0] | Get-Member -MemberType Property
#add existing properties to object
foreach ($Property in $ErrorProperties)
{
if ($Property.Name -eq 'InvocationInfo')
{
$returnValue | Add-Member -Type NoteProperty -Name 'InvocationInfo' -Value $($Error[0].InvocationInfo.PositionMessage)
}
else
{
$returnValue | Add-Member -Type NoteProperty -Name $($Property.Name) -Value $($Error[0].$($Property.Name))
}
}
#return object
$returnValue
break
}
}
End
{
return $authenticationResult
}
}
###### Main script
#Ensure TLS 1.2 protocol is enabled
try {
If ([Net.ServicePointManager]::SecurityProtocol -notmatch 'Tls12') {
[Net.ServicePointManager]::SecurityProtocol += [Net.SecurityProtocolType]::Tls12
Write-Host "Enabled Tls1.2 in '[Net.ServicePointManager]::SecurityProtocol'" -ForegroundColor Yellow
}
else {
Write-Host "Tls1.2 is enabled in '[Net.ServicePointManager]::SecurityProtocol'" -ForegroundColor Yellow
}
}
Catch {
$err = "An error occurred enabling TLS1.2. Error: $_"
Write-Host "`n$err" -ForegroundColor Red
Send-MailMessage -To $errRecip -Subject "$script - Error occurred during processing" -Body $err -From $sender -Attachment $logfile -SmtpServer $smtpServer
Exit
}
#CHECK FOR EWS MANAGED API, IF PRESENT IMPORT THE HIGHEST VERSION EWS DLL, ELSE EXIT
$EWSDLL = (($(Get-ItemProperty -ErrorAction SilentlyContinue -Path Registry::$(Get-ChildItem -ErrorAction SilentlyContinue -Path 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Exchange\Web Services'|Sort-Object Name -Descending | Select-Object -First 1 -ExpandProperty Name)).'Install Directory') + "Microsoft.Exchange.WebServices.dll")
If (Test-Path $EWSDLL)
{
Try
{
Import-Module $EWSDLL -DisableNameChecking -ErrorAction Stop
}
Catch
{
$err = "An error occurred importing the Exchange Web Services DLL '$EWSDLL'. Error: $_"
Write-Host "`n$err" -ForegroundColor Red
Send-MailMessage -To $errRecip -Subject "$script - Error occurred during processing" -Body $err -From $sender -Attachment $logfile -SmtpServer $smtpServer
Exit
}
}
Else
{
$err = "This script requires the EWS Managed API 1.2 or later. Please download and install the current version of the EWS Managed API from http://go.microsoft.com/fwlink/?LinkId=255472"
Write-Host "`n$err" -ForegroundColor Red
Send-MailMessage -To $errRecip -Subject "$script - Error occurred during processing" -Body $err -From $sender -Attachment $logfile -SmtpServer $smtpServer
Exit
}
#Create EWS Object
$ews = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService -ArgumentList "Exchange2013_SP1" -ErrorAction Stop
#Authenticate EWS using OAuth
Try {
$ews.UseDefaultCredentials = $False
Write-Host "Requesting EWS OAuth Token using registered Client ID" -ForegroundColor Yellow
$OAuthResult = Get-EWSOAuthToken -UserPrincipalName $UserPrincipalName -Password $Password -ClientId "$ClientIDfromAzureAD" -ErrorAction Stop
$token = $OAuthResult.Result.AccessToken
#Check if we successfully retrieved an Oauth Token
If ([System.String]::IsNullOrEmpty($token))
{
$err = "Get-EWSOAuthtoken returned an empty Auth Token. Aborted. Latest error details:`n$_error $($OAuthResult.Exception)"
Write-Host "`n$err" -ForegroundColor Red
$OAuthResult | Format-List -Force
$OAuthResult.Result | Format-List -Force
Send-MailMessage -To $errRecip -Subject "$script - Error occurred during processing" -Body "$err" -From $sender -Attachment $logfile -SmtpServer $smtpServer
Exit
}
else
{
$OAuthchk = $true
$ews.Credentials = [Microsoft.Exchange.WebServices.Data.OAuthCredentials]$token
Write-Host "Set EWS credentials to OAuth token" -ForegroundColor Yellow
}
}
Catch
{
$err = "An error occurred creating a new EWS object. Error:`n $_"
write-host "`n$err" -ForegroundColor Red
Send-MailMessage -To $errRecip -Subject "$script - Error occurred during processing" -Body "$err" -From $sender -Attachment $logfile -SmtpServer $smtpServer
Exit
}
# Do your processing using EWS
....