Notice: Due to size constraints and loading performance considerations, scripts referenced in blog posts are not attached directly. To request access, please complete the following form: Script Request Form Note: A Google account is required to access the form.
Disclaimer: I do not accept responsibility for any issues arising from scripts being run without adequate understanding. It is the user's responsibility to review and assess any code before execution. More information

Breaking Azure Authentication: Be careful what you inspect (with HTTPS Inspection)

Microsoft is crystal clear on the advice: do not inspect authentication URLs. When you ignore this advice, you're setting yourself up for a world of authentication pain - not realising this pain is caused by this inspection.

After dealing with many "mysterious" Azure authentication failures that turned out to be caused by TLS inspection, I decided to build a PowerShell script that would definitively prove when inspection is happening and automatically notify the right people when it's detected, the example below shows a "pass"


What this does not apply to?

If you are calling *.login.microsoft.com then this inspection exclusion does not apply to this URL as this is required for Tenant Restrictions which can be found in in the article here if you disable inspection on this URL you cannot effectively enforce Tenant Restriction, you will know if you have this feature enabled as the block for unauthorised access looks like this:

However, the rest of this article applies to what happens when you block the other 2x URLs required to not be inspected.

The Problem: When Security Measures Become Security Risks

TLS inspection on Microsoft authentication endpoints causes a cascade of authentication issues:

  • Windows Hello for Business authentication failures
  • Azure Primary Refresh Token (PRT) problems
  • Certificate-based authentication errors
  • Content Security Policy violations in the Entra portal
  • Device registration and enrollment issues
  • Conditional Access policy evaluation problems

The irony? Your security team's attempt to "secure" traffic actually makes authentication less secure and significantly less reliable.


What Really Happens When You Ignore Microsoft's Advice

Let me paint you a picture of what actually occurs when you decide to inspect these authentication URLs, because the consequences go far beyond simple "login issues."

The Azure PRT Nightmare

The Azure Primary Refresh Token (PRT) is the backbone of modern Windows authentication to Azure resources. When you intercept the TLS traffic to authentication endpoints, you're fundamentally breaking the cryptographic trust chain that the PRT relies on. Here's what happens:

PRT Acquisition Fails: When a device tries to obtain its initial PRT during Azure AD join or hybrid join, the certificate validation fails because your proxy is presenting a corporate certificate instead of the legitimate Microsoft certificate.

Token Refresh Breaks: Even if a device somehow gets a PRT initially, subsequent refresh attempts fail because the token refresh process expects consistent certificate chains. Your proxy breaks this consistency.

Silent Authentication Stops Working: Applications that rely on PRT for silent authentication (like Office 365, Teams, or any Azure-integrated app) start prompting for credentials repeatedly because they can't validate the authentication responses.


The Single Sign-On Cascade Failure

Once the PRT is compromised, you get a domino effect of SSO failures:

Entra Resources Become Inaccessible: Users start seeing the dreaded "sign-in required" prompts for resources they should seamlessly access. The Azure portal, Microsoft 365 admin centers, and custom applications integrated with Entra all begin failing.

Certificate-Based Authentication Issues: If you're using certificate-based authentication (smart cards, Windows Hello for Business certificates), the entire mechanism breaks down because the certificate validation process can't trust the intercepted connections.

Conditional Access Issues: Conditional Access policies that rely on device trust or certificate-based authentication start treating compliant devices as non-compliant, blocking access or forcing unnecessary MFA prompts.


The User Experience Disaster

From the user's perspective, what was once seamless becomes a nightmare:

  • Constant Login Prompts: Applications that should "just work" start asking for credentials multiple times per day
  • "Something Went Wrong" Errors: Users see generic error messages in Entra-connected applications without any clear explanation
  • Intermittent Access: Sometimes authentication works (when cached tokens are still valid), sometimes it doesn't, creating an unpredictable and frustrating experience
  • MFA Overload: Conditional Access policies trigger unnecessary MFA requests because device trust can't be established

Automated Detection and Alerting

I created a PowerShell script that checks the certificates presented by critical Microsoft authentication URLs and determines whether they're legitimate public CA certificates or corporate proxy certificates. Here's how it works.

Step 1: Certificate Retrieval

The script first attempts to retrieve certificates from the key Microsoft authentication endpoints:

# Define the URLs to check
$UrlsToCheck = @(
    'https://enterpriseregistration.windows.net',
    'https://adfs.bythepowerofgreyskull.com', 
    'https://device.login.microsoftonline.com'
)

function Get-CertificateFromUrl {
    param([string]$Url)
    
    Write-Host "Checking $Url..." -ForegroundColor Yellow
    
    # First try the HTTP method
    $cert = Get-CertificateViaHttp -Url $Url
    if ($cert) {
        return $cert
    }
    
    # If HTTP method fails, try direct TLS connection
    Write-Host "  HTTP method failed, trying direct TLS connection..." -ForegroundColor Gray
    return Get-CertificateViaTls -Url $Url
}

The script uses two methods to retrieve certificates - first via HTTP requests (which leverages PowerShell's built-in proxy handling), and if that fails, it falls back to direct TLS connections through any configured proxy.

Step 2: Legitimate CA Validation

Once I have the certificates, the script checks whether they're issued by known legitimate public certificate authorities:

# Known legitimate Microsoft certificate authorities
$LegitimateIssuers = @(
    'DigiCert',
    'Microsoft',
    'Baltimore CyberTrust Root',
    'Cybertrust',
    'VeriSign',
    'GlobalSign',
    'Entrust',
    'GeoTrust',
    'Thawte',
    'Comodo',
    'Let''s Encrypt',
    'Amazon',
    'Google Trust Services'
)

function Test-CertificateIssuer {
    param(
        [string]$Url,
        [System.Security.Cryptography.X509Certificates.X509Certificate2]$Certificate
    )
    
    $issuer = $Certificate.Issuer
    $subject = $Certificate.Subject
    
    # Check if issued by a known legitimate CA
    $isLegitimate = $false
    foreach ($legitCA in $LegitimateIssuers) {
        if ($issuer -like "*$legitCA*") {
            $isLegitimate = $true
            break
        }
    }
    
    # Return structured data for analysis
    return [PSCustomObject]@{
        Url = $Url
        Subject = $subject
        Issuer = $issuer
        IsLegitimate = $isLegitimate
        Thumbprint = $Certificate.Thumbprint
        NotAfter = $Certificate.NotAfter
        SerialNumber = $Certificate.SerialNumber
    }
}

This function creates a structured analysis of each certificate, flagging any that don't match known public CAs. If your corporate proxy is intercepting these connections, the certificates will be issued by your internal CA instead of a legitimate public authority.

Step 3: CSV Report Generation

All findings get exported to a timestamped CSV file for documentation and further analysis:

# Export results to CSV for further analysis
$csvPath = "Microsoft_Auth_Certificate_Check_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"
$results | Export-Csv -Path $csvPath -NoTypeInformation
Write-Host ""
Write-Host "Detailed results exported to: $csvPath" -ForegroundColor Gray

This creates a permanent record of the certificate analysis, which is invaluable when you need to prove to skeptical security teams that inspection is actually happening.

Step 4: Automated Email Notifications

When TLS inspection is detected, it automatically sends a detailed email notification to the security and network teams:

function Send-InspectionDetectedEmail {
    param(
        [string]$CsvPath,
        [array]$Results
    )
    
    try {
        $computerName = $env:COMPUTERNAME
        $userName = $env:USERNAME
        $timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
        $proxyConfig = Get-ProxyConfiguration
        
        # Build HTML email body with critical alert formatting
        $htmlBody = @"
<!DOCTYPE html>
<html>
<head>
    <style>
        .header { background-color: #d73502; color: white; padding: 15px; }
        .alert { background-color: #f8d7da; border: 1px solid #f5c6cb; 
                 color: #721c24; padding: 15px; border-radius: 4px; margin: 15px 0; }
        .suspicious { background-color: #f8d7da; color: #721c24; font-weight: bold; }
        .legitimate { background-color: #d4edda; color: #155724; font-weight: bold; }
    </style>
</head>
<body>
    <div class="header">
        <h2>Problem with PRT (Primary Token) and HTTPS Inspection Detected</h2>
    </div>
    
    <div class="alert">
        <strong>CRITICAL ISSUE DETECTED:</strong> TLS inspection has been detected on Microsoft authentication endpoints. This requires immediate attention.
    </div>
"@
        
        # Add certificate analysis table and recommendations
        # ... (full HTML email body construction)
        
        $mailMessage = New-Object System.Net.Mail.MailMessage
        $mailMessage.Subject = "URGENT: TLS Inspection Detected on Microsoft Authentication URLs - $computerName"
        $mailMessage.IsBodyHtml = $true
        $mailMessage.Priority = [System.Net.Mail.MailPriority]::High
        
        # Attach the CSV report
        if (Test-Path $CsvPath) {
            $attachment = New-Object System.Net.Mail.Attachment($CsvPath)
            $mailMessage.Attachments.Add($attachment)
        }
        
        $smtpClient.Send($mailMessage)
        Write-Host "Email notification sent successfully" -ForegroundColor Green
    }
    catch {
        Write-Warning "Failed to send email notification: $($_.Exception.Message)"
    }
}

Visual Notification

If we include login.microsoftonline.com as a check URL we can get then see the error message you get when the script detects inspection (however this URL will no impact your einvorinment)


However if you get an alert like this, then that will cause issues as outlined in this article as this will be intercepting the Azure authentication process.

Conclusion

Microsoft's guidance is clear: don't inspect authentication URLs. My script provides the evidence you need to prove when this guidance is being ignored and the automated notifications to ensure the right people know about it immediately.

Previous Post Next Post

نموذج الاتصال