

Connecting to Exchange Online PowerShell via client secret
source link: https://www.michev.info/Blog/Post/2997/connecting-to-exchange-online-powershell-via-client-secret-flow
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Connecting to Exchange Online PowerShell via client secret
Microsoft just released a new version of the Exchange Online (V2) PowerShell module, which brings support for much awaited feature – seamless connectivity that satisfies MFA requirements thanks to using the certificate-based authentication flow. Now, one can argue that this isn’t “true” MFA and point to the inherit auditing issues when using this flow, but that’s true for all other apps leveraging it, and not something the Exchange team can be blamed for.
We did a thorough review/guide of the new method in our recent post over at the Quadrotech blog. Here I’ll add few more details that were left out for brevity or simply border the “unsupported” frontier and should not be used unless you really want to get your hands dirty. We start by getting the obvious thing out of the way – yes, you can actually use a client secret as well, although it is considered less secure and Microsoft chose not to support it via the module. But nothing is stopping you from generating a client secret for your app, then using it to connect via the “manual” method outlined below. But more on that later.
First, what is this “manual” method I talk about? Well, if you are familiar with the way Exchange Online Remote PowerShell implements support for modern authentication (or have seen my previous articles on the subject), you are aware that the bulk of the client-side changes are introduced to handle the token request/renewal process. Once the token is obtained, it is “proxied” via the good old basic authentication WinRM endpoint, to a slightly different URI – one that has the “BasicAuthToOAuthConversion=true” value added. The backend of course has also received some updates in order to handle this, but those are out of our hands, and thus not as interesting.
The important thing is that once you understand the process, you can bypass the built-in cmdlets and create your own “connect to Exchange Online via modern authentication” function, which might suit your needs better. Same applies to the features released in the new version of the module. Once you have configured the Azure AD application, it’s permissions and the certificate to be used for authentication, you can use any number of methods to obtain a token, for example:
Add-Type
-Path
'C:\Program Files\WindowsPowerShell\Modules\AzureAD\2.0.1.10\Microsoft.IdentityModel.Clients.ActiveDirectory.dll'
$authContext45
=
New-Object
"Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext"
-ArgumentList
"https://login.windows.net/tenant.onmicrosoft.com"
$secret
=
Get-ChildItem
cert://currentuser/my/
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
$CAC
=
[Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate]
::new(
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
,
$secret
)
where I have pointed to a certificate stored in the Personal store for the current user and also provided the client_id of the application registered in Azure AD. If everything checks out and a valid token is obtained, you are ready to establish the remote PowerShell session. One small detail you need to know first – when passing the token, you need to specify the username in the following format: “OAuthUser@tenantGUID”. Here’s how it works:
$token
=
$authenticationResult
.Result.AccessToken
$Authorization
=
"Bearer {0}"
-f
$Token
$Password
=
ConvertTo-SecureString
-AsPlainText
$Authorization
-Force
$Ctoken
=
New-Object
System.Management.Automation.PSCredential
-ArgumentList
"OAuthUser@923712ba-352a-4eda-bece-09d0684d0cfb"
,
$Password
$Session
=
New-PSSession
-ConfigurationName
Microsoft.Exchange
-ConnectionUri
https://outlook.office365.com/PowerShell-LiveId
?
BasicAuthToOAuthConversion=true
-Credential
$Ctoken
-Authentication
Basic
-AllowRedirection
-Verbose
Import-PSSession
$Session
And with that, you should have an Exchange Online Remote PowerShell session established and all the cmdlets corresponding to the admin role granted to the application’s service principal available.
A variation of the above can be used to point to a certificate file, instead of using the certificate store provider. Assuming we have a cert.pfx file, protected with a password, the following example can be used:
$authContext45
=
New-Object
"Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext"
-ArgumentList
"https://login.windows.net/tenant.onmicrosoft.com"
$certFile
=
"C:\cert.pfx"
$certFilePassword
=
"P4$$w0rd"
$secret
=
New-Object
-TypeName
System.Security.Cryptography.X509Certificates.X509Certificate
-ArgumentList
$certFile
,
$certFilePassword
$CAC
=
[Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate]
::new(
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"
,
$secret
)
Or if you don’t want to get bothered by certificates and don’t care about the increased security they provide, you can simply add a client secret to the application you registered in Azure AD and use the client credentials flow instead:
$authContext4
=
New-Object
"Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext"
-ArgumentList
"https://login.windows.net/tenant.onmicrosoft.com"
$ccred4
=
New-Object
Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential
-ArgumentList
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
,
"very_long_string"
And that’s pretty much it. Once you have a valid token, use it to establish the remote PowerShell session via the sample above. Don’t forget to add some proper error handling and most importantly, logic to detect token expiry and renew/obtain new tokens as needed!
One additional detail you might need when troubleshooting connectivity issues – the token must contain the wid claim and within it, the admin role(s) to which the service principal object corresponding to your Azure AD application has been assigned. You already know how to get the token, as for decoding it use a site such as jwt.ms or just do it directly via PowerShell as detailed in this article. Here’s how a sample valid token would look like:
///UPDATE.
I remembered one thing I forgot to add in this post – make sure you pass the “anchor” when connecting. The module cmdlet does that for you, but when you create the session yourself, you need to add “&email=SystemMailbox%7bbb558c35-97f1-4cb9-8ff7-d53741dc928c%7d%40tenantname.onmicrosoft.com” to the connection string.
So the end result should be something like this:
"https://outlook.office365.com/PowerShell-LiveId
?
BasicAuthToOAuthConversion=true&email=SystemMailbox
%
7bbb558c35-97f1-4cb9-8ff7-d53741dc928c
%
7d
%
40tenantname.onmicrosoft.com
This will fix some of the issues you get with Azure AD-related operations, such as creating a Shared mailbox. Some, but not all, as some cmdlets are simply not designed to work in the context of an app.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK