Exchange Online - Other ways of Testing IMAP OAuth2 Client Credential Flow
Hi All,
I write this Blog Article in Addition to the Exchange Online POP and IMAP OAUTH 2.0 Client Credentials Flow
I tried out other ways of testing
First we need to get the Access Token
###############################################################################
# Get Access Token with MSAL
###############################################################################
Import-Module MSAL.PS
$AppID = "3bf0cf36-87bf-47a9-927b-0ef9df7cf146"
$TenantID = "icewolfch.onmicrosoft.com"
$ClientSecret = ConvertTo-SecureString "YourClientSecret" -AsPlainText -Force
$Scope = "https://outlook.office.com/.default"
Clear-MsalTokenCache
$Token = Get-MSALToken -ClientId $AppID -ClientSecret $ClientSecret -TenantId $TenantID -Scope $Scope
$AccessToken = $Token.AccessToken
# Get Access Token with MSAL
###############################################################################
Import-Module MSAL.PS
$AppID = "3bf0cf36-87bf-47a9-927b-0ef9df7cf146"
$TenantID = "icewolfch.onmicrosoft.com"
$ClientSecret = ConvertTo-SecureString "YourClientSecret" -AsPlainText -Force
$Scope = "https://outlook.office.com/.default"
Clear-MsalTokenCache
$Token = Get-MSALToken -ClientId $AppID -ClientSecret $ClientSecret -TenantId $TenantID -Scope $Scope
$AccessToken = $Token.AccessToken
You can decode your Access Token with https://jwt.ms/
Make sure you se the Roles POP.AccessAsApp or IMAP.AccessAsApp
Or use the JWTDetails Module and the command
Get-JWTDetails -token $AccessToken
It is explained that you need to use Base64 Encoding with Username and Accesstoken to Authenticate
Authenticate an IMAP, POP or SMTP connection using OAuth
https://docs.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth#use-client-credentials-grant-flow-to-authenticate-imap-and-pop-connections
https://docs.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth#use-client-credentials-grant-flow-to-authenticate-imap-and-pop-connections
So we need to build the Login in this Format
"user=test@contoso.onmicrosoft.com^Aauth=Bearer EwBAAl3BAAUFFpUAo7J3Ve0bjLBWZWCclRC3EoAA^A^A"
###############################################################################
# Build Login
###############################################################################
$UserName = "m.muster@icewolf.ch"
$Text = "user=" + $UserName + "$([char]0x01)auth=Bearer " + $accessToken + "$([char]0x01)$([char]0x01)"
$Bytes = [System.Text.Encoding]::ASCII.GetBytes($Text)
$EncodedText =[Convert]::ToBase64String($Bytes)
# Build Login
###############################################################################
$UserName = "m.muster@icewolf.ch"
$Text = "user=" + $UserName + "$([char]0x01)auth=Bearer " + $accessToken + "$([char]0x01)$([char]0x01)"
$Bytes = [System.Text.Encoding]::ASCII.GetBytes($Text)
$EncodedText =[Convert]::ToBase64String($Bytes)
If you have Git installed on your Computer you can test now with OpenSSL
cd C:\Program Files\Git\usr\bin
openssl.exe s_client -connect outlook.office365.com:993 -crlf -quiet
C: C01 CAPABILITY
S: * CAPABILITY … AUTH=XOAUTH2
S: C01 OK Completed
C: C02 AUTHENTICATE XOAUTH2 dXNlcj1zb21ldXNlckBleGFtcGxlLmNvbQFhdXRoPUJlYXJlciB5YTI5LnZGOWRmdDRxbVRjMk52YjNSbGNrQmhkSFJoZG1semRHRXVZMjl0Q2cBAQ==
S: C02 OK AUTHENTICATE completed.
C: C03 LIST "" *
S: C03 OK LIST completed
C: C04 Logout
S: C04 OK LOGOUT completed
openssl.exe s_client -connect outlook.office365.com:993 -crlf -quiet
C: C01 CAPABILITY
S: * CAPABILITY … AUTH=XOAUTH2
S: C01 OK Completed
C: C02 AUTHENTICATE XOAUTH2 dXNlcj1zb21ldXNlckBleGFtcGxlLmNvbQFhdXRoPUJlYXJlciB5YTI5LnZGOWRmdDRxbVRjMk52YjNSbGNrQmhkSFJoZG1semRHRXVZMjl0Q2cBAQ==
S: C02 OK AUTHENTICATE completed.
C: C03 LIST "" *
S: C03 OK LIST completed
C: C04 Logout
S: C04 OK LOGOUT completed
Okay that worked. Now the whole thing with PowerShell
###############################################################################
# connecting to Office 365 IMAP Service
###############################################################################
Write-Host "Connect to Office 365 IMAP Service." -ForegroundColor DarkGreen
$ComputerName = "Outlook.office365.com"
$Port = "993"
try {
$TCPConnection = New-Object System.Net.Sockets.Tcpclient($($ComputerName), $Port)
$TCPStream = $TCPConnection.GetStream()
try {
$SSLStream = New-Object System.Net.Security.SslStream($TCPStream)
$SSLStream.ReadTimeout = 5000
$SSLStream.WriteTimeout = 5000
$CheckCertRevocationStatus = $true
$SSLStream.AuthenticateAsClient($ComputerName,$null,[System.Security.Authentication.SslProtocols]::Tls12,$CheckCertRevocationStatus)
}
catch {
Write-Host "Ran into an exception while negotating SSL connection. Exiting." -ForegroundColor Red
$_.Exception.Message
break
}
}
catch {
Write-Host "Ran into an exception while opening TCP connection. Exiting." -ForegroundColor Red
$_.Exception.Message
break
}
# continue if connection was successfully established
$SSLstreamReader = new-object System.IO.StreamReader($sslStream)
$SSLstreamWriter = new-object System.IO.StreamWriter($sslStream)
$SSLstreamWriter.AutoFlush = $true
$SSLstreamReader.ReadLine()
###############################################################################
# Send "C01 CAPABILITY"
###############################################################################
Write-Host "C01 CAPABILITY" -ForegroundColor "Cyan"
$Text = "C01 CAPABILITY"
$SSLstreamWriter.WriteLine($Text)
$ResponseStr = $SSLstreamReader.ReadLine()
Write-Host "$ResponseStr" -ForegroundColor "Cyan"
#Wait for "C01 OK CAPABILITY completed"
$ResponseStr = $SSLstreamReader.ReadLine()
Write-Host "$ResponseStr" -ForegroundColor "Cyan"
# connecting to Office 365 IMAP Service
###############################################################################
Write-Host "Connect to Office 365 IMAP Service." -ForegroundColor DarkGreen
$ComputerName = "Outlook.office365.com"
$Port = "993"
try {
$TCPConnection = New-Object System.Net.Sockets.Tcpclient($($ComputerName), $Port)
$TCPStream = $TCPConnection.GetStream()
try {
$SSLStream = New-Object System.Net.Security.SslStream($TCPStream)
$SSLStream.ReadTimeout = 5000
$SSLStream.WriteTimeout = 5000
$CheckCertRevocationStatus = $true
$SSLStream.AuthenticateAsClient($ComputerName,$null,[System.Security.Authentication.SslProtocols]::Tls12,$CheckCertRevocationStatus)
}
catch {
Write-Host "Ran into an exception while negotating SSL connection. Exiting." -ForegroundColor Red
$_.Exception.Message
break
}
}
catch {
Write-Host "Ran into an exception while opening TCP connection. Exiting." -ForegroundColor Red
$_.Exception.Message
break
}
# continue if connection was successfully established
$SSLstreamReader = new-object System.IO.StreamReader($sslStream)
$SSLstreamWriter = new-object System.IO.StreamWriter($sslStream)
$SSLstreamWriter.AutoFlush = $true
$SSLstreamReader.ReadLine()
###############################################################################
# Send "C01 CAPABILITY"
###############################################################################
Write-Host "C01 CAPABILITY" -ForegroundColor "Cyan"
$Text = "C01 CAPABILITY"
$SSLstreamWriter.WriteLine($Text)
$ResponseStr = $SSLstreamReader.ReadLine()
Write-Host "$ResponseStr" -ForegroundColor "Cyan"
#Wait for "C01 OK CAPABILITY completed"
$ResponseStr = $SSLstreamReader.ReadLine()
Write-Host "$ResponseStr" -ForegroundColor "Cyan"
###############################################################################
# Build Login
###############################################################################
$UserName = "m.muster@icewolf.ch"
#$Text = "user=test@contoso.onmicrosoft.com^Aauth=Bearer EwBAAl3BAAUFFpUAo7J3Ve0bjLBWZWCclRC3EoAA^A^A"
$Text = "user=" + $UserName + "$([char]0x01)auth=Bearer " + $accessToken + "$([char]0x01)$([char]0x01)"
$Bytes = [System.Text.Encoding]::ASCII.GetBytes($Text)
$EncodedText =[Convert]::ToBase64String($Bytes)
$Login = "C02 AUTHENTICATE XOAUTH2 $EncodedText"
#$Login
#$Login | clip
###############################################################################
# Authenticate with XOAUTH2
###############################################################################
Write-Host "Authenticate using XOAuth2" -ForegroundColor "Cyan"
$SSLstreamWriter.WriteLine($Login)
$ResponseStr = $SSLstreamReader.ReadLine()
Write-Host "$ResponseStr" -ForegroundColor "Cyan"
###############################################################################
# List
###############################################################################
$Text = 'C03 LIST "" *'
$SSLstreamWriter.WriteLine($Text)
while ($ResponseStr -notmatch "LIST completed")
{
$ResponseStr = $SSLstreamReader.ReadLine()
Write-Host "$ResponseStr" -ForegroundColor "Cyan"
}
###############################################################################
# Close
###############################################################################
Write-Host "C04 LOGOUT" -ForegroundColor "Cyan"
$Text = 'C04 LOGOUT'
$SSLstreamWriter.WriteLine($Text)
$ResponseStr = $SSLstreamReader.ReadLine()
Write-Host "$ResponseStr" -ForegroundColor "Cyan"
###############################################################################
# Cleanup
###############################################################################
$SSLstreamWriter.Close()
$SSLstreamReader.Close()
$SSLStream.Close()
# Build Login
###############################################################################
$UserName = "m.muster@icewolf.ch"
#$Text = "user=test@contoso.onmicrosoft.com^Aauth=Bearer EwBAAl3BAAUFFpUAo7J3Ve0bjLBWZWCclRC3EoAA^A^A"
$Text = "user=" + $UserName + "$([char]0x01)auth=Bearer " + $accessToken + "$([char]0x01)$([char]0x01)"
$Bytes = [System.Text.Encoding]::ASCII.GetBytes($Text)
$EncodedText =[Convert]::ToBase64String($Bytes)
$Login = "C02 AUTHENTICATE XOAUTH2 $EncodedText"
#$Login
#$Login | clip
###############################################################################
# Authenticate with XOAUTH2
###############################################################################
Write-Host "Authenticate using XOAuth2" -ForegroundColor "Cyan"
$SSLstreamWriter.WriteLine($Login)
$ResponseStr = $SSLstreamReader.ReadLine()
Write-Host "$ResponseStr" -ForegroundColor "Cyan"
###############################################################################
# List
###############################################################################
$Text = 'C03 LIST "" *'
$SSLstreamWriter.WriteLine($Text)
while ($ResponseStr -notmatch "LIST completed")
{
$ResponseStr = $SSLstreamReader.ReadLine()
Write-Host "$ResponseStr" -ForegroundColor "Cyan"
}
###############################################################################
# Close
###############################################################################
Write-Host "C04 LOGOUT" -ForegroundColor "Cyan"
$Text = 'C04 LOGOUT'
$SSLstreamWriter.WriteLine($Text)
$ResponseStr = $SSLstreamReader.ReadLine()
Write-Host "$ResponseStr" -ForegroundColor "Cyan"
###############################################################################
# Cleanup
###############################################################################
$SSLstreamWriter.Close()
$SSLstreamReader.Close()
$SSLStream.Close()
That's it. Hope this helps with further testing on IMAP OAUTH2 Login.
The Code used here is also in my GitHub Repo
Regards
Andres Bohren