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

Azure AD:如何防止跨设备复用令牌,强制设备注册或验证设备令牌?

解决Azure AD令牌跨设备复用的问题

这是企业级应用里很常见的安全诉求——要确保访问令牌只能在用户的注册设备上使用,防止令牌泄露后被跨设备滥用。我来给你拆解几个核心解决方案,一步步落实:

1. 强制用户注册设备(通过Azure AD条件访问)

首先从源头管控:只有已注册/合规的设备才能获取访问你的Web API的令牌。你可以通过Azure AD的条件访问策略实现这一点:

  • 登录Azure门户,进入Azure AD > 条件访问,点击「新建策略」
  • 给策略起个清晰的名字,比如「Web API仅允许注册设备访问」
  • 在「用户和组」里选择需要强制设备注册的用户/安全组
  • 在「云应用或操作」中选中你的目标Web API
  • 切换到「授予」标签,选择需要设备标记为合规或者需要已加入Azure AD的设备(前者适合MDM管理的设备,后者适合自带设备场景)
  • 最后把策略状态设为「开」,保存生效

这样一来,未注册的设备(比如Postman所在的设备如果没注册)根本无法获取到有效的访问令牌。

2. 让令牌绑定设备上下文

确保原生应用请求令牌时携带设备信息,这样Azure AD会在访问令牌和ID令牌中加入设备相关声明(比如device_id、device_oid),让API能识别令牌对应的设备:

  • UWP应用:使用MSAL.NET时,调用AcquireTokenInteractive或AcquireTokenSilent时,加上.WithDeviceInfo(DeviceInfo.CreateFromCurrentDevice())参数,确保设备信息被传递到Azure AD。
  • iOS应用:使用MSALiOS时,MSALPublicClientApplication会自动收集设备信息并包含在请求中,只要你用的是最新版本的MSAL库。

拿到令牌后,你可以用jwt.ms解码查看,确认是否包含device_id声明——这是后续验证的关键依据。

3. 在Web API端验证设备特定令牌

光有设备声明还不够,你需要在API层添加验证逻辑,确保每个请求的令牌对应的设备确实属于当前用户,且状态正常。以ASP.NET Core API为例:

步骤1:自定义授权要求和处理程序

// 定义设备验证的授权要求
public class ValidDeviceRequirement : IAuthorizationRequirement { }

// 实现授权处理逻辑
public class ValidDeviceHandler : AuthorizationHandler<ValidDeviceRequirement>
{
    private readonly GraphServiceClient _graphClient; // 注入Microsoft Graph客户端

    public ValidDeviceHandler(GraphServiceClient graphClient)
    {
        _graphClient = graphClient;
    }

    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, ValidDeviceRequirement requirement)
    {
        // 从令牌中提取设备ID和用户ID
        var deviceId = context.User.FindFirst("device_id")?.Value;
        var userId = context.User.FindFirst("oid")?.Value;

        if (string.IsNullOrEmpty(deviceId) || string.IsNullOrEmpty(userId))
        {
            context.Fail();
            return;
        }

        // 调用Microsoft Graph验证设备是否属于该用户且状态正常
        try
        {
            var device = await _graphClient.Devices[deviceId].Request().GetAsync();
            // 检查设备是否已启用,且所有者包含当前用户
            if (device.AccountEnabled && device.Owners.Any(o => o.Id == userId))
            {
                context.Succeed(requirement);
            }
            else
            {
                context.Fail();
            }
        }
        catch (ServiceException)
        {
            // 设备不存在或无权限访问,直接拒绝
            context.Fail();
        }
    }
}

步骤2:注册授权策略

在Program.cs中添加以下代码:

// 注册Microsoft Graph客户端(需配置Device.Read.All等权限)
builder.Services.AddGraphServiceClient(builder.Configuration.GetSection("AzureAd"));

// 添加自定义授权策略
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("RequireValidDevice", policy =>
        policy.Requirements.Add(new ValidDeviceRequirement()));
});

// 注册授权处理程序
builder.Services.AddSingleton<IAuthorizationHandler, ValidDeviceHandler>();

步骤3:在API中应用策略

在需要验证设备的控制器或方法上添加[Authorize(Policy = "RequireValidDevice")]:

[ApiController]
[Route("api/[controller]")]
[Authorize(Policy = "RequireValidDevice")]
public class ProtectedController : ControllerBase
{
    // 你的API方法逻辑
}

4. 强化刷新令牌的设备绑定

Azure AD的刷新令牌默认是与设备绑定的——原生应用会把刷新令牌存储在设备的安全存储中(比如UWP的Credential Locker、iOS的Keychain),无法跨设备导出。即使攻击者拿到了短期的访问令牌,没有对应的刷新令牌(绑定原设备),也无法获取新的访问令牌,大大降低了滥用风险。

要确保你的原生应用使用授权码流+PKCE(禁止使用密码流),这是Azure AD推荐的原生应用认证方式,能进一步防止令牌泄露。

补充:为什么Postman能复用令牌?

因为Postman只是单纯传递令牌,没有验证设备上下文——而你的API之前没有做设备验证。一旦你落实了上面的步骤,即使Postman拿到了令牌,由于它的设备未注册,API会直接返回401未授权。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:21:43