Hi All,
I have an issue that I hope someone can help with; in part because I need to re-code an ASP.net (C#) web application that our staff used to use to interact with our on-premise Exchange (using PowerShell commands in code). nd now needs to interact with Exchange Online instead.
Understanding that V1 is being retired and basic authentication being disabled (and the fact we use MFA already) I have opted to use the new EXO V2 module... and thought it best to get a solution working using PowerShell script first, before attempting the same in code; which I have successfully achieved using a self-signed certificate and a thumbprint per the instructions at https://docs.microsoft.com/en-us/powershell/exchange/app-only-auth-powershell-v2
So, for example, the following redacted Powershell script works fine for me 🙂
## Import Modules
Import-Module ExchangeOnlineManagement
## Set Input Params
$tenantID = 'ourtenant.onmicrosoft.com'
$appID = 'OURAPPID-ABCD-ABCD-ABCD-57d726ccABCD'
$CertificateThumbPrint = '037814C89E93C036E9BE331E83EF53467958C1D8'
## Connect to Exchange Online (with Certificate Thumbprint)
Connect-ExchangeOnline -CertificateThumbPrint $CertificateThumbPrint -AppID $appID -Organization $tenantID
## Get Mailbox Properties
Get-EXOMailbox -UserPrincipalName 'devade@XYZ.co.uk' -Properties DeliverToMailboxAndForward, ForwardingAddress
## Disconnect
Disconnect-ExchangeOnline
However I need to do all this in C# code. Previously (on-premise) I had something like this...
// Define locals
PSSnapInException psSnapInException = new PSSnapInException();
// Create a Runspace Configuration object
RunspaceConfig = RunspaceConfiguration.Create();
// Add the Exchange PowerShell SnapIn to the Runspace
RunspaceConfig.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.SnapIn", out psSnapInException);
// Check for errors
if (psSnapInException != null) {throw new Exception(psSnapInException.Message, psSnapInException.InnerException);}
// Get the status of Mailbox Forwarding for the Current User using PowerShell script
string[] psResponse = RunScript($"Get-Mailbox '{username}' | Format-List DeliverToMailboxAndForward, ForwardingAddress;");
etc, etc, etc.
Now I need to recode this to work with EXO V2 and I am struggling.
I read that I now have to use WMManConnectionInfo to create a remote session using my certificate thumbprint so tried...
WSManConnectionInfo ci = new WSManConnectionInfo(new Uri("https://outlook.office365.com/PowerShell"),
"http://schemas.microsoft.com/powershell/Microsoft.Exchange", "037814C89E93C036E9BE331E83EF53467958C1D8");
using (Runspace runspace = RunspaceFactory.CreateRunspace(ci))
{
using (PowerShell session = PowerShell.Create())
{
runspace.Open();
session.Runspace = runspace;
// Script content would go here using Get-EXOMailbox cmdlet instead of Get-Mailbox
session.AddCommand("Exit-PSSession").Invoke();
runspace.Close();
}
}
which didn't work but gave me the following error (at the point the code creates the runspace)...
The WinRM client cannot process the request. The Enhanced Key Usage (EKU) field of the certificate is not set to "Client Authentication". Retry the request with a certificate that has the correct EKU
Note;
I also tried the following URI in the code above as I didn't understand how my C# code knows about our tenant and app (i.e. the params $tenantid and $appid in my working PowerShell statement Connect-ExchangeOnline -CertificateThumbPrint $CertificateThumbPrint -AppID $appID -Organization $tenantID)...
WSManConnectionInfo ci = new WSManConnectionInfo(new Uri("https://outlook.office365.com/PowerShell?DelegatedOrg=ourtenant.onmicrosoft.com&BasicAuthToOAuthConversion=true"),
"http://schemas.microsoft.com/powershell/Microsoft.Exchange", "037814C89E93C036E9BE331E83EF53467958C1D8");
... but I get the same error 😞
Having searched the Internet high and lo I cannot find any examples of how to connect to Exchange Online using C# code in order to interact and manipulate Exchange using PowerShell cmdlets using EXO V2 and MFA. Perhaps I am completely barking up the wrong tree in what I am trying to achieve here. Can anyone help me with my issue / point me to a working solution / explain to me what I am doing wrong (even if it requires a whole new approach)? Have I confused my use of certificates?
Any assistance would be very much appreciated.
Thanks, Ade.