Bitzsoft.Integrations.AzureAD 1.0.0-alpha.9

This is a prerelease version of Bitzsoft.Integrations.AzureAD.
dotnet add package Bitzsoft.Integrations.AzureAD --version 1.0.0-alpha.9
                    
NuGet\Install-Package Bitzsoft.Integrations.AzureAD -Version 1.0.0-alpha.9
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Bitzsoft.Integrations.AzureAD" Version="1.0.0-alpha.9" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Bitzsoft.Integrations.AzureAD" Version="1.0.0-alpha.9" />
                    
Directory.Packages.props
<PackageReference Include="Bitzsoft.Integrations.AzureAD" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Bitzsoft.Integrations.AzureAD --version 1.0.0-alpha.9
                    
#r "nuget: Bitzsoft.Integrations.AzureAD, 1.0.0-alpha.9"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Bitzsoft.Integrations.AzureAD@1.0.0-alpha.9
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Bitzsoft.Integrations.AzureAD&version=1.0.0-alpha.9&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Bitzsoft.Integrations.AzureAD&version=1.0.0-alpha.9&prerelease
                    
Install as a Cake Tool

Bitzsoft.Integrations.AzureAD

Azure AD / Microsoft Entra ID 集成客户端 — OAuth 2.0 PKCE 流程、OIDC Token 验证、Graph API 组查询、用户自动供应。

功能特性

  • OAuth 2.0 PKCE 授权码流程:完整实现 Auth Code Flow + PKCE,支持 MVC / Web App 场景
  • OIDC Token 验证:区分 ID Token(登录验证)和 Access Token(API 鉴权)两类场景
  • ASP.NET Core JwtBearer 集成:一键注册后 [Authorize] 直接生效
  • Graph API 组查询:通过 Client Credentials 应用身份查询用户组 + 角色映射
  • 用户自动供应:外部登录绑定 + 邮箱匹配
  • JWKS 自动轮换:基于 ConfigurationManager 自动刷新签名密钥
  • 多租户支持:自动处理 common / organizations 多租户场景
  • 第三方请求日志:内置 RequestLogging DelegatingHandler,记录所有出站 HTTP 请求与响应,便于问题排查

安装

.NET CLI

dotnet add package Bitzsoft.Integrations.AzureAD

PackageReference

<PackageReference Include="Bitzsoft.Integrations.AzureAD" Version="1.0.0" />

配置

appsettings.json

{
  "AzureAD": {
    "Enabled": true,
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "common",
    "ClientId": "your-client-id",
    "ClientSecret": "your-client-secret",
    "CallbackPath": "/api/callback/azuread",
    "Audience": "api://your-client-id",
    "Scopes": [ "openid", "profile", "email" ]
  }
}
配置项 说明 默认值
Enabled 是否启用 false
Instance Azure AD 实例地址 https://login.microsoftonline.com/
TenantId 租户 ID,多租户使用 common common
ClientId 应用程序(客户端)ID --
ClientSecret 客户端密钥 --
CallbackPath OAuth 回调路径 /api/callback/azuread
Audience Access Token 受众(SPA 场景必填) 默认 fallback 为 ClientId
Scopes OAuth 请求的 Scope ["openid","profile","email"]

注册服务

核心注册(必选)

using Bitzsoft.Integrations.AzureAD.DependencyInjection;

// 注册核心服务(OAuth + Token 验证)
services.AddBitzsoftAzureAD(options =>
{
    options.Instance = "https://login.microsoftonline.com/";
    options.TenantId = "common";
    options.ClientId = "your-client-id";
    options.ClientSecret = "your-client-secret";
    options.Audience = "api://your-client-id";
});

// 或从 IConfiguration 绑定
services.AddBitzsoftAzureAD(configuration.GetSection("AzureAD").Bind);

ASP.NET Core JwtBearer 集成(可选)

// 注册后 [Authorize] 直接生效,User.Identity 即为 AAD 用户
services.AddBitzsoftAzureADJwtBearer();

Graph API 组查询(可选)

services.AddBitzsoftAzureADGraph()
    .WithGroupRoleMapping<SqlGroupRoleMappingRepository>();

重要: Graph API 使用 Client Credentials(应用身份),需在 Azure Portal 授予 Application permissions(如 GroupMember.Read.All),并点击"授予管理员同意"。不是 Delegated permissions。

用户自动供应(可选)

services.AddBitzsoftAzureADProvisioning()
    .WithExternalLogin<SqlExternalLoginRepository>()
    .WithUserLookup<SqlUserLookupRepository>();

第三方请求日志

内置 Bitzsoft.Integrations.RequestLogging 出站请求记录管道,默认使用 NullRequestLogStore 不持久化。

// ① 默认:启用记录管道但不持久化(日志丢弃)
services.AddBitzsoftAzureAD(options => { /* ... */ });

// ② 持久化:宿主注册 IRequestLogStore 实现后,所有出站请求自动落库
services.AddRequestLogging<MyRequestLogStore>(opts =>
{
    opts.MaxBodyLength = 8192;
    opts.SensitiveFields.Add("mySecret");
});
services.AddBitzsoftAzureAD(options => { /* ... */ });

使用示例

MVC / Web App — OAuth 登录流程

using Bitzsoft.Integrations.AzureAD.Interfaces;

public class AccountController : Controller
{
    private readonly IAzureADClient _aadClient;

    public AccountController(IAzureADClient aadClient)
    {
        _aadClient = aadClient;
    }

    // Step 1: 生成授权 URL
    public IActionResult Login()
    {
        var codeVerifier = _aadClient.GenerateCodeVerifier();
        var codeChallenge = _aadClient.GenerateCodeChallenge(codeVerifier);
        var nonce = _aadClient.GenerateNonce();
        var state = Guid.NewGuid().ToString("N");

        HttpContext.Session.SetString("pkce_verifier", codeVerifier);
        HttpContext.Session.SetString("nonce", nonce);
        HttpContext.Session.SetString("state", state);

        var authUrl = _aadClient.GetAuthorizationUrl(
            Url.Action("Callback", null, null, Request.Scheme),
            state, codeChallenge, nonce);

        return Redirect(authUrl);
    }

    // Step 2: 处理回调
    public async Task<IActionResult> Callback(string code, string state)
    {
        var codeVerifier = HttpContext.Session.GetString("pkce_verifier");
        var expectedNonce = HttpContext.Session.GetString("nonce");

        var tokenResponse = await _aadClient.ExchangeCodeForTokenAsync(
            code, Url.Action("Callback", null, null, Request.Scheme), codeVerifier!);

        if (tokenResponse?.IdToken is null)
            return BadRequest("Token exchange failed");

        var userInfo = await _aadClient.ValidateIdTokenAsync(
            tokenResponse.IdToken, expectedNonce);

        if (userInfo is null)
            return BadRequest("ID Token validation failed");

        // 使用 userInfo 登录系统
        return RedirectToAction("Index", "Home");
    }
}

SPA / Mobile App — Access Token 验证

using Bitzsoft.Integrations.AzureAD.Interfaces;

[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
    private readonly IAzureADClient _aadClient;

    public AuthController(IAzureADClient aadClient)
    {
        _aadClient = aadClient;
    }

    [HttpPost("validate")]
    public async Task<IActionResult> ValidateToken()
    {
        var accessToken = Request.Headers["Authorization"]
            .ToString().Replace("Bearer ", "");

        var userInfo = await _aadClient.ValidateAccessTokenAsync(accessToken);

        if (userInfo is null)
            return Unauthorized();

        return Ok(userInfo);
    }
}

使用 [Authorize](需注册 JwtBearer 扩展)

using Microsoft.AspNetCore.Authorization;

[ApiController]
[Route("api/[controller]")]
public class ApiController : ControllerBase
{
    [HttpGet("profile")]
    [Authorize(AuthenticationSchemes = "AzureADJwtBearer")]
    public IActionResult GetProfile()
    {
        var oid = User.FindFirst("oid")?.Value;
        var name = User.FindFirst("name")?.Value;
        return Ok(new { ObjectId = oid, Name = name });
    }
}

Graph API — 查询用户组并匹配角色

using Bitzsoft.Integrations.AzureAD.Interfaces;

public class RoleService
{
    private readonly IAzureADGraphClient _graphClient;

    public RoleService(IAzureADGraphClient graphClient)
    {
        _graphClient = graphClient;
    }

    public async Task<List<string>> GetUserRolesAsync(
        string tenantId, string userObjectId)
    {
        return await _graphClient.GetMatchedRoleIdsAsync(tenantId, userObjectId);
    }
}

核心类型一览

类型 说明
IAzureADClient 核心 OAuth + Token 验证接口
IAzureADGraphClient Graph API 组查询接口(Client Credentials)
IAzureADProvisioningClient 用户自动供应接口
AzureADOptions 配置模型
AADTokenResponse OAuth 令牌响应
AADUserInfo 用户信息
AADGroupInfo 组信息
GroupRoleMapping 组-角色映射
ProvisioningResult 供应结果
AzureADException 自定义异常

ID Token vs Access Token

场景 Token 类型 验证方法 Audience
MVC/Web App 登录 ID Token ValidateIdTokenAsync ClientId
SPA/Mobile App 调用 API Access Token ValidateAccessTokenAsync api://xxx
ASP.NET Core [Authorize] Access Token 自动(中间件) api://xxx

多租户说明

TenantId 设为 commonorganizations 时:

  • 自动关闭 Issuer 固定验证(AAD 签发 Token 时 Issuer 为用户真实 Tenant ID)
  • Audience 验证始终开启,安全性有保障

依赖

  • Bitzsoft.Integrations.Compatibility — 基础工具库
  • Microsoft.Extensions.Http — IHttpClientFactory
  • Microsoft.Extensions.Options — 选项模式
  • Microsoft.IdentityModel.Protocols.OpenIdConnect — OIDC 协议
  • System.IdentityModel.Tokens.Jwt — JWT Token 处理
  • Microsoft.AspNetCore.Authentication.JwtBearer — ASP.NET Core JwtBearer 集成(可选)

相关包

Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0-alpha.9 45 7/12/2026
1.0.0-alpha.8 161 7/1/2026
1.0.0-alpha.7 319 6/16/2026
1.0.0-alpha.6 62 6/16/2026
1.0.0-alpha.5 57 6/14/2026
1.0.0-alpha.4 51 7/1/2026
1.0.0-alpha.3 59 6/7/2026
1.0.0-alpha.2 59 5/29/2026