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

.NET Core 6 API中基于Azure AD实现双认证方案求助

解决方案:.NET Core 6 API实现Azure AD内部用户认证(适配双认证流程)

一、Azure AD配置与后端服务注册

首先在appsettings.json中添加Azure AD相关配置:

"AzureAd": {
  "Instance": "https://login.microsoftonline.com/",
  "Domain": "你的租户域名",
  "TenantId": "你的租户ID",
  "ClientId": "API应用注册的ClientId",
  "ClientSecret": "API应用注册的ClientSecret",
  "CallbackPath": "/api/auth/internal/callback"
}

然后在Program.cs中注册Azure AD认证服务:

using Microsoft.AspNetCore.Authentication.AzureAD.UI;
using Microsoft.Identity.Web;
using Microsoft.IdentityModel.Tokens;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

// 注册Azure AD认证方案
builder.Services.AddAuthentication()
    .AddAzureAD(options => builder.Configuration.Bind("AzureAd", options));

// 配置JWT验证(用于保护后续API接口)
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
        };
    });

builder.Services.AddControllers();
builder.Services.AddHttpClient();

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();
app.Run();

二、内部认证API实现(含回调处理)

创建InternalAuthController,处理前端认证请求和Azure AD回调逻辑:

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.AzureAD.UI;
using Microsoft.AspNetCore.Mvc;
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http;
using System.Threading.Tasks;

[Route("api/auth/internal")]
[ApiController]
[AllowAnonymous]
public class InternalAuthController : ControllerBase
{
    private readonly IConfiguration _configuration;
    private readonly IHttpClientFactory _httpClientFactory;

    public InternalAuthController(IConfiguration configuration, IHttpClientFactory httpClientFactory)
    {
        _configuration = configuration;
        _httpClientFactory = httpClientFactory;
    }

    // 前端触发内部认证的入口
    [HttpGet("login")]
    public IActionResult InitiateAzureAdLogin()
    {
        var authProps = new AuthenticationProperties
        {
            RedirectUri = _configuration["AzureAd:CallbackPath"],
            Items = { { "scheme", AzureADDefaults.AuthenticationScheme } }
        };
        // 引导用户到Azure AD登录页
        return Challenge(authProps, AzureADDefaults.AuthenticationScheme);
    }

    // Azure AD认证完成后的回调处理
    [HttpGet("callback")]
    public async Task<IActionResult> AzureAdCallback()
    {
        // 获取Azure AD认证结果
        var authResult = await HttpContext.AuthenticateAsync(AzureADDefaults.AuthenticationScheme);
        if (!authResult.Succeeded)
        {
            return BadRequest("Azure AD认证失败");
        }

        // 解析ID令牌,提取用户核心信息
        var idToken = authResult.Properties.GetTokenValue("id_token");
        var jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(idToken);
        var userEmail = jwtToken.Claims.FirstOrDefault(c => c.Type == "email")?.Value;
        var userRoles = jwtToken.Claims.Where(c => c.Type == "roles").Select(c => c.Value).ToList();

        // 调用已实现的令牌生成API,生成自定义JWT
        var client = _httpClientFactory.CreateClient();
        var tokenReq = new
        {
            Email = userEmail,
            Roles = userRoles,
            UserType = "Internal"
        };
        var response = await client.PostAsJsonAsync($"{_configuration["ApiBaseUrl"]}/api/token/generate", tokenReq);
        
        if (!response.IsSuccessStatusCode)
        {
            return BadRequest("生成自定义令牌失败");
        }

        var customToken = await response.Content.ReadFromJsonAsync<TokenResponse>();
        // 返回自定义JWT给前端
        return Ok(new { AccessToken = customToken.AccessToken, ExpiresIn = customToken.ExpiresIn });
    }
}

// 令牌生成API的响应模型
public class TokenResponse
{
    public string AccessToken { get; set; }
    public int ExpiresIn { get; set; }
}

三、关键注意事项

  • Azure AD应用配置:在Azure门户注册API应用时,需启用ID令牌,确保回调路径与配置的CallbackPath完全一致;同时要为内部用户分配对应角色,保证角色声明能被包含在ID令牌中。
  • 前端适配:前端请求/api/auth/internal/login后,会跳转至Azure AD登录页,认证完成后自动回调到API,前端接收返回的自定义JWT后存入本地存储,后续请求携带该令牌访问受保护接口。
  • 令牌生成API复用:内部、外部认证共用同一令牌生成API,仅通过UserType参数区分用户类型,API统一生成包含角色、邮箱的标准JWT即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 08:05:58