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

基于ADFS OAuth2的Vue+JS/C#应用:登录后操作触发MFA/OTP方案咨询

针对ADFS OAuth2应用的操作级MFA验证方案

核心思路

利用ADFS支持的基于请求的动态认证规则,结合OAuth2的重新授权流程,在用户执行敏感操作时触发二次MFA验证,无需登出整个会话。


1. ADFS端配置

首先需要在ADFS的依赖方信任中配置附加认证规则,让ADFS能识别需要触发MFA的请求:

  • 打开ADFS管理控制台,找到你的应用对应的依赖方信任,进入编辑声明规则
  • 添加一个自定义规则,当请求中包含特定标识时,触发MFA认证
  • 示例自定义规则:
    c:[Type == "http://yourdomain.com/claims/needmfa", Value == "true"]
    => issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", Value = "http://schemas.microsoft.com/claims/multipleauthn");
    
  • 确保ADFS全局认证策略中已启用MFA方法(如短信、微软验证器)

2. 后端C#实现

后端需要处理敏感操作的MFA校验与回调逻辑:

2.1 敏感操作前置检查

当用户发起敏感操作请求时,先校验当前会话是否已完成本次操作的MFA验证:

[HttpPost("sensitive-operation")]
public async Task<IActionResult> SensitiveOperation()
{
    var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
    var hasValidMfa = await _cacheService.GetAsync<bool>($"mfa_valid_{userId}");

    if (!hasValidMfa)
    {
        var state = Guid.NewGuid().ToString();
        await _cacheService.SetAsync($"mfa_state_{state}", userId, TimeSpan.FromMinutes(10));

        // 构造ADFS授权请求URL,强制触发MFA
        var adfsAuthUrl = $"https://your-adfs-server/adfs/oauth2/authorize?" +
            $"client_id=your-client-id" +
            $"&response_type=code" +
            $"&redirect_uri=https://your-app.com/mfa-callback" +
            $"&scope=openid+profile" +
            $"&prompt=login" +
            $"&state={state}" +
            $"&claims={{\"id_token\":{{\"http://yourdomain.com/claims/needmfa\":{{\"value\":\"true\"}}}}}}";

        return Json(new { needMfa = true, authUrl = adfsAuthUrl });
    }

    // 执行敏感操作逻辑
    // ...
    return Ok();
}

2.2 MFA回调处理

用户完成ADFS认证后,后端验证授权码并标记MFA有效:

[HttpGet("mfa-callback")]
public async Task<IActionResult> MfaCallback(string code, string state)
{
    var userId = await _cacheService.GetAsync<string>($"mfa_state_{state}");
    if (userId == null) return BadRequest("无效的认证状态");

    // 使用MSAL交换授权码获取ID Token
    var confidentialClient = ConfidentialClientApplicationBuilder
        .Create("your-client-id")
        .WithClientSecret("your-client-secret")
        .WithAuthority("https://your-adfs-server/adfs")
        .Build();

    var result = await confidentialClient.AcquireTokenByAuthorizationCode(
        new[] { "openid", "profile" },
        code)
        .WithRedirectUri("https://your-app.com/mfa-callback")
        .ExecuteAsync();

    // 校验ID Token中的MFA认证标识
    var amrClaim = result.IdTokenClaims.FirstOrDefault(c => c.Type == "amr")?.Value;
    if (amrClaim != null && amrClaim.Contains("mfa"))
    {
        await _cacheService.SetAsync($"mfa_valid_{userId}", true, TimeSpan.FromMinutes(30));
        return Redirect($"https://your-app.com/sensitive-page?state={state}");
    }

    return BadRequest("MFA认证未通过");
}

3. 前端Vue/JavaScript处理

前端配合后端完成跳转、回调与操作重试逻辑:

<template>
  <button @click="handleSensitiveOperation">执行敏感操作</button>
</template>

<script>
export default {
  methods: {
    async handleSensitiveOperation() {
      try {
        const response = await fetch('/api/sensitive-operation', {
          method: 'POST',
          credentials: 'include'
        });
        const data = await response.json();
        
        if (data.needMfa) {
          // 跳转至ADFS进行MFA认证,可替换为弹窗提升体验
          window.location.href = data.authUrl;
        } else {
          alert('操作执行成功');
        }
      } catch (err) {
        console.error(err);
      }
    }
  },
  async mounted() {
    const urlParams = new URLSearchParams(window.location.search);
    const state = urlParams.get('state');
    if (state) {
      await this.handleSensitiveOperation();
      window.history.replaceState({}, document.title, window.location.pathname);
    }
  }
}
</script>

关键注意事项

  • ADFS版本:需使用ADFS 2016及以上版本,支持动态认证规则与claims参数传递
  • 会话安全:MFA验证有效期建议设为短期(如30分钟),避免权限滥用
  • 防攻击:回调时必须校验state参数有效性,防范CSRF攻击
  • 用户体验:可使用弹窗打开ADFS认证页面,避免全页面跳转

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 15:54:58