GenerateO365RefreshToken.ps1

<#PSScriptInfo
 
.VERSION 1.1
 
.GUID 9d8dac7e-cee0-4b96-973b-b62f98464d3f
 
.AUTHOR Samraj
 
.COMPANYNAME
 
.COPYRIGHT
 
.TAGS
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
 
.PRIVATEDATA
 
#>


<#
 
.DESCRIPTION
 Exterro eDiscovery platform connect with O365 with the help of refresh token to support modern authentication.
 
#>
 

#-- This script is used for Exterro's eDiscovery Platform.
#-- @author: Samraj K
#-- Code snippets are referred from PS gallery projects.

$ErrorActionPreference = "Stop"
$WelknownClientId = "1b730954-1685-4b74-9bfd-dac224a7b894"
$PSEndPointUrl = "https://ps.compliance.protection.outlook.com"
$O365LoginUrl = "https://login.microsoftonline.com"
[bool]  $Global:autoClosed=$false;
Function Show-LoginWindow
{
    param(
        [System.Uri]$Url
    )
    Add-Type -AssemblyName System.Web
    Add-Type -AssemblyName System.Windows.Forms
 
    $form = New-Object -TypeName System.Windows.Forms.Form -Property @{Width=500;Height=650}
    $web  = New-Object -TypeName System.Windows.Forms.WebBrowser -Property @{Width=400;Height=600;Url=($url ) }
    $DocComp  = {
        $Global:uri = $web.Url.AbsoluteUri
        if ($Global:Uri -match "error=[^&]*|code=[^&]*") {$Global:autoClosed=$true; $form.Close() }
    }
    $web.ScriptErrorsSuppressed = $true
    $web.Add_DocumentCompleted($DocComp)
    $form.Text="Exterro Token Generation"

    $Icon = [system.drawing.icon]::ExtractAssociatedIcon($PSHOME + "\powershell.exe")
    $form.Icon=$Icon
   # $form.CompanyName="Exterro Inc"
    $form.Controls.Add($web)
    $form.Add_Shown({$form.Activate()})
    $form.ShowDialog() | Out-Null
    $queryOutput = [System.Web.HttpUtility]::ParseQueryString($web.Url.Query)
    
    if($Global:autoClosed){
    $output = @{}
    foreach($key in $queryOutput.Keys){
        $output["$key"] = $queryOutput[$key]
    }
    return $output 
    }else{
    $FileLocation="tempFile.html"
    if (Test-Path $FileLocation) 
    {
      Remove-Item $FileLocation
    }
    $web.DocumentText | Out-File -FilePath $FileLocation -NoClobber
    

  $output=  GetStringBetweenTwoStrings -firstString "code=" -secondString "\\u0026session_state=" -importPath $FileLocation
  
  Remove-Item �path $FileLocation
  return $output 
  }
    
}

function GetStringBetweenTwoStrings($firstString, $secondString, $importPath){

    #Get content from file
    $file = Get-Content $importPath

    #Regex pattern to compare two strings
    $pattern = "$firstString(.*?)$secondString"

    #Perform the opperation
    $result = [regex]::Match($file,$pattern).Groups[1].Value

    #Return result
    return $result

}

function Display {
    param(
        [String]$codes
    )
    [void][Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')

    $title = 'Refresh Token'
    $msg   = 'Please copy the refresh token from the window.'

    $text = [Microsoft.VisualBasic.Interaction]::InputBox($msg, $title, $codes)

}

function Get-ExterroPSO365RefreshToken {
    
    Unblock-File -Path $MyInvocation.ScriptName;

    #--- Get the options section
        Show-Menu �Title 'My Menu'
         $selection = Read-Host "Please make a selection ( Default : Microsoft global environment)"
         switch ($selection)
         {
             '1' {
                 $PSEndPointUrl = "https://ps.compliance.protection.outlook.com"
                 $O365LoginUrl = "https://login.microsoftonline.com"
                 'You chose option #1 - Microsoft global environment'
             } '2' {
                $PSEndPointUrl = "https://ps.compliance.protection.office365.us"
                 $O365LoginUrl = "https://login.microsoftonline.us"
                 'You chose option #2 - Microsoft Cloud for US Government (GCC High)'
             } '3' {
                $PSEndPointUrl = "https://l5.ps.compliance.protection.office365.us"
                 $O365LoginUrl = "https://login.microsoftonline.us"
                 'You chose option #3 - Microsoft Cloud for US Government (DoD)'
             } '4' {
             $PSEndPointUrl = "https://ps.compliance.protection.outlook.de"
                 $O365LoginUrl = "https://login.microsoftonline.de"
                 'You chose option #4 - Microsoft Cloud Germany'
             } '5' {
             $PSEndPointUrl = "https://ps.protection.outlook.cn"
                 $O365LoginUrl = "https://login.partner.microsoftonline.cn"
                 'You chose option #5 - Azure and Microsoft 365 operated by 21Vianet in China'
             }  'q' {
                 return
             } default {
                 $PSEndPointUrl = "https://ps.compliance.protection.outlook.com"
                 $O365LoginUrl = "https://login.microsoftonline.com"
                 'Default value - Microsoft global environment'
             } 
         }
    
    #--- End of option section

    $refreshToken = ""
    $responseCode=""
        
        $codeData = Show-LoginWindow -Url "$O365LoginUrl/common/oauth2/authorize?resource=$PSEndPointUrl&client_id=$WelknownClientId&response_type=code&redirect_uri=urn:ietf:wg:oauth:2.0:oob&prompt=login" + ";"
       if($Global:autoClosed){
        If ($codeData["error"]) {
            "An error occurred accessing $PSEndPointUrl : " + $codeData["error"]
            return
        } ElseIf ($codeData["code"]) {
            $responseCode = $codeData["code"] ;
        } Else {
            "No code obtained from the endpoint url." ;
            return
        }
        }else{
            $responseCode = $codeData;
        }

        #Fetch the access token
        if ($responseCode) {
        $postParams = @{grant_type='authorization_code';code=$responseCode;client_id=$WelknownClientId;redirect_uri='urn:ietf:wg:oauth:2.0:oob'}
        $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
        $headers.Add("Content-Type", 'application/x-www-form-urlencoded')
        $response=Invoke-RestMethod -Uri "$O365LoginUrl/common/oauth2/token" -Method POST -Body $postParams -Headers $headers

        #Set-Clipboard -Value $response.refresh_token
        #$response | Out-File -FilePath "AccessToken.txt"
        Display $response.refresh_token;
        }else{
        Write-Host "Powershell window might be closed abruptly."
        }
}

function Show-Menu
{
    param (
        [string]$Title = 'M365 Environment Details'
    )
    Clear-Host
    Write-Host "================ $Title ================"
    
    Write-Host "1: Press '1' for Microsoft global environment."
    Write-Host "2: Press '2' for Microsoft Cloud for US Government(GCC High)."
    Write-Host "2: Press '3' for Microsoft Cloud for US Government(DoD)."
    Write-Host "3: Press '4' for Microsoft Cloud Germany."
    Write-Host "4: Press '5' for Azure and Microsoft 365 operated by 21Vianet in China."
    Write-Host "Q: Press 'Q' to quit."
}

Get-ExterroPSO365RefreshToken