How to use Azure Manage Identity to send out email using Graph API ?

EnterpriseArchitect 6,301 Reputation points
2025-12-12T05:07:33.1866667+00:00

I have created the Automation account with managed Identity called 'SecretExpiryNotifier', so I don't have to hard-code the Entra ID Application secrets password in the PowerShell runbook as described in the article https://wiseservices.co.uk/post/a3a10db6-02b5-4162-9773-cc3e2c618a47

But how can I update the code to avoid hard-coding the password or client secrets?

 

# Azure AD App Registration details
$ClientId = "931c0f90-0e10-4dc7-8fe3-2b634172729f"
$TenantId = "c96b5c7c-436d-4252-9e63-429e959aeecc"
$clientSecret = "ABCD1234-5678-90AB-CDEF-1234567890AB"

# Notification details
$notificationEmails = @("******@wiseservices.co.uk", "******@wiseservices.co.uk")  # List of recipients
$senderEmail = "******@wiseservices.co.uk"  # Sender's email (must be allowed by App Access Policy)
$expirationThresholdDays = 30
$today = Get-Date
$emailSubject = "App Registration Client Secret Expiration Alert"

# Step 1: Get an access token
$tokenUri = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
$body = @{
    client_id     = $clientId
    scope         = "https://graph.microsoft.com/.default"
    client_secret = $clientSecret
    grant_type    = "client_credentials"
}
$response = Invoke-RestMethod -Method Post -Uri $tokenUri -Body $body
$token = $response.access_token
if (-not $token) {
    Write-Output "Failed to retrieve access token. Check your Azure AD credentials."
    exit 1
}
Write-Output $token

# Use Microsoft Graph API to list app registrations
$uri = "https://graph.microsoft.com/v1.0/applications"
$headers = @{
    Authorization = "Bearer $token"
}
$appRegistrations = Invoke-RestMethod -Uri $uri -Headers $headers

# Initialize the email body
$emailBody = "The following App Registration client secrets are about to expire:`n`n"
# Microsoft Graph API for app registrations (already retrieved as $appRegistrations)
foreach ($app in $appRegistrations.value) {
    # Get the app's password credentials using Graph API
    $passwordUri = "https://graph.microsoft.com/v1.0/applications/$($app.id)/passwordCredentials"
    $passwordCredentials = Invoke-RestMethod -Uri $passwordUri -Headers $headers
    foreach ($secret in $passwordCredentials.value) {
        Write-Output "Inspecting secret details: $($secret | ConvertTo-Json -Depth 10)"
        $endDate = [datetime]$secret.endDateTime
        $daysRemaining = ($endDate - $today).Days
        # Check if the expiration is within the threshold
        if ($daysRemaining -le $expirationThresholdDays) {
            # Append the expiring secret details to the email body
            $emailBody += "App: $($app.displayName) - Expiration Date: $($secret.endDateTime) - Days Remaining: $($daysRemaining)`n"
        }
    }
}
# Check if we have any secrets that are expiring
if ($emailBody -ne "The following App Registration client secrets are about to expire:`n`n") {
    # Prepare recipients
    $recipients = @()
    foreach ($email in $notificationEmails) {
        $recipients += @{ EmailAddress = @{ Address = $email } }
    }
    # Prepare the email message
    $emailMessage = @{
        Message         = @{
            Subject      = $emailSubject
            Body         = @{
                ContentType = "Text"
                Content     = $emailBody
            }
            ToRecipients = $recipients
        }
        SaveToSentItems = "false"
    }
    # Send the email using Microsoft Graph API
    $sendEmailUri = "https://graph.microsoft.com/v1.0/users/$senderEmail/sendMail"
    Invoke-RestMethod -Uri $sendEmailUri -Method POST -Headers @{ Authorization = "Bearer $token" } -Body ($emailMessage | ConvertTo-Json -Depth 10) -ContentType "application/json"
    Write-Output "Notification email sent."
} else {
    Write-Output "No expiring client secrets found."
}
Write-Output "Script execution complete."

Because I cannot grant the Manage Identity called 'SecretExpiryNotifier' with the Application.Read.All, Directory.Read.All, and Mail.Send permissions in Microsoft Graph, using admin consent applied

Microsoft Security | Microsoft Entra | Microsoft Entra ID
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Q&A Assist
    2025-12-12T05:07:44.1533333+00:00
    AI generated content. This question contains an answer created with AI from Q&A Assist. Learn more

    To use Azure Managed Identity to send emails using the Microsoft Graph API without hard-coding the client secret, you can modify your PowerShell script to authenticate using the Managed Identity instead of using client credentials. Here’s how you can update your code:

    1. Remove Client Secret and Client ID: Since you are using Managed Identity, you do not need to specify the ClientId and clientSecret.
    2. Get Access Token Using Managed Identity: You can obtain an access token for Microsoft Graph using the Managed Identity directly. Here’s how you can do that:
    # Get an access token using Managed Identity
    $tokenUri = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://graph.microsoft.com/"
    $response = Invoke-RestMethod -Method Get -Uri $tokenUri -Headers @{ Metadata = "true" }
    $token = $response.access_token
    if (-not $token) {
        Write-Output "Failed to retrieve access token. Check your Managed Identity configuration."
        exit 1
    }
    Write-Output $token
    
    1. Update Email Sending Logic: The rest of your email sending logic can remain largely the same, but you will use the $token obtained from the Managed Identity for authorization.

    Here’s the updated portion of your script:

    # Send the email using Microsoft Graph API
    $sendEmailUri = "https://graph.microsoft.com/v1.0/users/$senderEmail/sendMail"
    Invoke-RestMethod -Uri $sendEmailUri -Method POST -Headers @{ Authorization = "Bearer $token" } -Body ($emailMessage | ConvertTo-Json -Depth 10) -ContentType "application/json"
    Write-Output "Notification email sent."
    
    1. Assign Required Permissions: Ensure that the Managed Identity has the necessary permissions in Azure AD for Mail.Send, Application.Read.All, and Directory.Read.All. You can assign these permissions through the Azure portal or using PowerShell.

    By following these steps, you can effectively use Azure Managed Identity to send emails without hard-coding sensitive information in your script.

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.