Private/Connect-AzureService.ps1

# Connect-AzureService.ps1
# Installs Az modules if needed, authenticates to Azure, and populates $script:Context.
# Part of the M365-QuickAssess module -- not exported.

function Connect-AzureService
{
    Write-Log "Preparing Azure connection..."

    # -------------------------------------------------------------------
    # Module Check / Install
    # -------------------------------------------------------------------
    $requiredModules = @( "Az.Accounts", "Az.Resources" )

    foreach ( $module in $requiredModules )
    {
        if ( -not ( Get-Module -ListAvailable -Name $module ) )
        {
            Write-Log "$module not found -- installing from PSGallery..." "WARN"

            try
            {
                Install-Module $module -Scope CurrentUser -Repository PSGallery -Force -ErrorAction Stop
                Write-Log "$module installed successfully"
            }
            catch
            {
                Write-Log "Failed to install $module : $( $_.Exception.Message )" "ERROR"
                throw
            }
        }
    }

    # -------------------------------------------------------------------
    # Import Modules
    # -------------------------------------------------------------------
    try
    {
        Import-Module Az.Accounts  -ErrorAction Stop
        Import-Module Az.Resources -ErrorAction Stop
    }
    catch
    {
        Write-Log "Failed to import Az modules: $( $_.Exception.Message )" "ERROR"
        throw
    }

    Disable-AzContextAutosave -Scope Process | Out-Null

    # -------------------------------------------------------------------
    # Check for existing valid session
    # -------------------------------------------------------------------
    $azContext = Get-AzContext -ErrorAction SilentlyContinue

    if ( $azContext -and $azContext.Tenant.Id -eq $script:Context.TenantId )
    {
        Write-Log "Using existing Azure session for tenant $( $script:Context.TenantId )"
        return
    }

    # -------------------------------------------------------------------
    # Authenticate
    # -------------------------------------------------------------------
    Write-Log "Connecting to Azure (device authentication)..."

    try
    {
        Clear-AzContext -Scope Process -Force -ErrorAction SilentlyContinue
        Disconnect-AzAccount -Scope Process -ErrorAction SilentlyContinue | Out-Null

        Connect-AzAccount `
            -TenantId              $script:Context.TenantId `
            -UseDeviceAuthentication `
            -Scope                 Process `
            -SkipContextPopulation `
            -ErrorAction           Stop | Out-Null

        # Preload subscriptions without triggering the subscription picker UI
        $null = Get-AzSubscription -TenantId $script:Context.TenantId -ErrorAction Stop

        Write-Log "Connected to Azure tenant $( $script:Context.TenantId )"
    }
    catch
    {
        Write-Log "Azure authentication failed: $( $_.Exception.Message )" "ERROR"
        throw
    }
}