You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Automation Runbook使用Connect-MgGraph -Identity时JWT令牌无效问题

问题:Azure Automation Runbook 连接 Microsoft Graph API 身份验证失败

错误信息

Invalid JWT access token.
Could not retrieve user 'john.carpenter@ekimetrics.com'. Error: Authentication needed. Please call Connect-MgGraph.

环境配置

  • 自动化账户:启用系统分配托管身份
  • PowerShell版本:PowerShell 7.2 Runbook
  • Microsoft Graph模块:已在自动化账户中安装
  • 权限:已为托管身份分配以下Microsoft Graph API应用权限(均已授予管理员同意):User.Read.All、Group.ReadWrite.All、Directory.ReadWrite.All、GroupMember.ReadWrite.All

Runbook脚本

Connect-MgGraph -Identity

# Define group mappings based on job title and location
$groupMapping = @{
    "Intern" = @{
        "GB" = @("GlobalGroup|DistributionList", "UKGroup|DistributionList")
        "HK" = @("GlobalGroup|DistributionList", "HKGroup|DistributionList")
        "US" = @("GlobalGroup|DistributionList", "USGroup|DistributionList")
        "FR" = @("GlobalGroup|DistributionList", "InternsFR|DistributionList")
        "CN" = @("GlobalGroup|DistributionList", "CNContact|DistributionList")
    }
    "Consultant" = @{
        "GB" = @("GlobalGroup|DistributionList", "UKGroup|DistributionList")
        "HK" = @("GlobalGroup|DistributionList", "HKGroup|DistributionList")
        "US" = @("GlobalGroup|DistributionList", "USGroup|DistributionList")
        "FR" = @("GlobalGroup|DistributionList", "ConsultantsFR|DistributionList")
        "CN" = @("GlobalGroup|DistributionList", "CNContact|DistributionList")
    }
    "Senior Manager" = @{
        "GB" = @("GlobalGroup|DistributionList", "SeniorWW|DistributionList", "Managers|DistributionList", "UKManagerGroup|AzureADGroup")
        "HK" = @("GlobalGroup|DistributionList", "SeniorWW|DistributionList", "Managers|DistributionList", "HKManagerGroup|AzureADGroup")
        "US" = @("GlobalGroup|DistributionList", "SeniorWW|DistributionList", "USManagerGroup|AzureADGroup")
        "FR" = @("GlobalGroup|DistributionList", "Managers|DistributionList", "SeniorManagersFR|DistributionList", "FRManagerGroup|AzureADGroup")
        "CN" = @("GlobalGroup|DistributionList", "CNContact|DistributionList")
    }
}

# Define user email (replace with dynamic input if needed)
$userUPN = "user@example.com"

try {
    # Retrieve user details from Microsoft Graph
    $user = Get-MgUser -UserId $userUPN -Property UserPrincipalName, JobTitle, UsageLocation -ErrorAction Stop
    Write-Output "User '$($user.UserPrincipalName)' retrieved successfully."
}
catch {
    Write-Error "Could not retrieve user '$userUPN'. Error: $_"
    exit
}

$jobTitle = $user.JobTitle
$location = $user.UsageLocation

if ([string]::IsNullOrEmpty($jobTitle) -or [string]::IsNullOrEmpty($location)) {
    Write-Warning "User '$($user.UserPrincipalName)' does not have a Job Title or Usage Location set."
}
elif ($groupMapping.ContainsKey($jobTitle) -and $groupMapping[$jobTitle].ContainsKey($location)) {
    $groups = $groupMapping[$jobTitle][$location]

    foreach ($groupEntry in $groups) {
        $splitEntry = $groupEntry -split '\|'
        $groupNameOrId = $splitEntry[0]

        # Get the group from Azure AD
        $group = Get-MgGroup -Filter "displayName eq '$groupNameOrId'" -ConsistencyLevel eventual -Top 1
        if ($group) {
            try {
                New-MgGroupMemberByRef -GroupId $group.Id -BodyParameter @{ "@odata.id" = "https://graph.microsoft.com/v1.0/directoryObjects/$($user.Id)" }
                Write-Output "Successfully added $($user.UserPrincipalName) to group: $groupNameOrId"
            }
            catch {
                Write-Warning "Could not add $($user.UserPrincipalName) to group '$groupNameOrId'. Error: $_"
            }
        }
        else {
            Write-Warning "Group '$groupNameOrId' not found in Azure AD."
        }
    }
}
else {
    Write-Warning "No group mappings found for Job Title '$jobTitle' and Location '$location'."
}

# Disconnect from Microsoft Graph
Disconnect-MgGraph

已执行的排查步骤

  • 确认托管身份已在Microsoft Entra ID企业应用列表中
  • 验证Graph API权限已分配且管理员同意已授予
  • 确认Runbook使用PowerShell 7.2版本
  • 确认自动化账户已安装Microsoft.Graph模块
  • 通过Get-AzContext | Select-Object Subscription验证订阅上下文正确

疑问

  1. 为何已启用托管身份仍出现JWT令牌无效的情况?
  2. 如何确保Runbook通过托管身份正确完成身份验证?
  3. 在Azure Automation中是否可以手动刷新或验证身份令牌?

解决方案

针对问题1:JWT令牌无效的可能原因

  • 模块版本bug:旧版本的Microsoft.Graph.Authentication模块在Azure Automation环境下使用托管身份时存在令牌获取异常,建议升级到最新稳定版。
  • 权限类型错误:托管身份仅支持应用权限,需确认分配的权限不是委托权限。
  • 身份关联异常:检查自动化账户的系统分配身份状态是否为“开启”,且Microsoft Entra ID中企业应用的对象ID与自动化账户的身份ID完全一致。
  • 令牌受众不匹配:若脚本调用了Graph Beta端点,但Connect-MgGraph默认获取v1.0令牌会导致无效,你的脚本使用v1.0可排除此情况。

针对问题2:确保Runbook通过托管身份正确认证的步骤

  1. 明确指定权限范围:修改Connect-MgGraph命令,显式声明所需应用权限,避免自动范围匹配问题:
    Connect-MgGraph -Identity -Scopes "User.Read.All", "Group.ReadWrite.All", "Directory.ReadWrite.All", "GroupMember.ReadWrite.All"
    
  2. 统一模块版本:确保自动化账户中Microsoft.Graph及其子模块(尤其是Microsoft.Graph.Authentication)版本一致,若版本混乱,卸载后重新安装完整的Microsoft.Graph模块。
  3. 添加身份验证前置测试:在脚本开头加入身份状态检查,提前排查认证问题:
    try {
        $context = Get-MgContext
        if (-not $context) {
            Connect-MgGraph -Identity -Scopes "User.Read.All", "Group.ReadWrite.All"
            $context = Get-MgContext
        }
        Write-Output "Authenticated successfully. Tenant ID: $($context.TenantId), Account: $($context.Account)"
    }
    catch {
        Write-Error "Authentication failed: $_"
        exit
    }
    
  4. 检查网络限制:若自动化账户配置了专用链接或虚拟网络,需确保允许访问https://graph.microsoft.com端点。

针对问题3:Azure Automation中令牌的刷新与验证

  • 手动刷新令牌:Azure Automation中托管身份的令牌由平台自动管理,无法手动触发刷新,但可通过重新调用Connect-MgGraph -Identity获取新令牌。
  • 验证令牌有效性:可在脚本中添加令牌过期检查或端点测试:
    $context = Get-MgContext
    if ($context.ExpiresOn -lt (Get-Date).AddMinutes(5)) {
        Write-Output "Token is about to expire, re-authenticating..."
        Disconnect-MgGraph
        Connect-MgGraph -Identity -Scopes "User.Read.All", "Group.ReadWrite.All"
    }
    

内容的提问来源于stack exchange,提问作者Thulaksan Jayapal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 17:45:58