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

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

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)

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

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"

###############################################################################
# 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 IMAPPOP3_OAUTH2.ps1

Regards
Andres Bohren