根据方案选择 Microsoft Graph 身份验证提供程序

身份验证提供程序实现使用 Microsoft 身份验证库 (MSAL) 获取令牌所需的代码,处理增量许可、过期密码和条件访问等情况的一些潜在错误,然后设置 HTTP 请求授权标头。 下表列出了与不同 应用程序类型的方案匹配的提供程序。

应用场景 Flow/Grant 受众 提供程序
单页应用 使用 PKCE 授权代码 委托的使用者/组织 授权代码提供程序
调用 Web API 的 Web 应用
授权代码 委托的使用者/组织 授权代码提供程序
客户端凭据 仅限应用 客户端凭据提供程序
调用 Web API 的 Web API
代表 委托的使用者/组织 代表提供程序
客户端凭据 仅限应用 客户端凭据提供程序
调用 Web API 的桌面应用
交互 委托的使用者/组织 交互式提供程序
集成 Windows 委托组织 集成的 Windows 提供程序
资源所有者 委托组织 用户名/密码提供程序
设备代码 委托组织 设备代码提供程序
守护程序应用
客户端凭据 仅限应用 客户端凭据提供程序
调用 Web API 的移动应用
交互 委托的使用者/组织 交互式提供程序

注意

以下代码片段是使用各自 SDK 的最新版本编写的。 如果遇到这些代码片段的编译器错误,请确保具有最新版本。 以下 Azure 标识库提供使用的身份验证提供程序:

授权代码提供程序

授权代码流使本机和 Web 应用能够安全地获取用户名中的令牌。 若要了解详细信息,请参阅 Microsoft 标识平台 和 OAuth 2.0 授权代码流

var scopes = new[] { "User.Read" };

// Multi-tenant apps can use "common",
// single-tenant apps must use the tenant ID from the Azure portal
var tenantId = "common";

// Values from app registration
var clientId = "YOUR_CLIENT_ID";
var clientSecret = "YOUR_CLIENT_SECRET";

// For authorization code flow, the user signs into the Microsoft
// identity platform, and the browser is redirected back to your app
// with an authorization code in the query parameters
var authorizationCode = "AUTH_CODE_FROM_REDIRECT";

// using Azure.Identity;
var options = new AuthorizationCodeCredentialOptions
{
    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
};

// https://learn.microsoft.com/dotnet/api/azure.identity.authorizationcodecredential
var authCodeCredential = new AuthorizationCodeCredential(
    tenantId, clientId, clientSecret, authorizationCode, options);

var graphClient = new GraphServiceClient(authCodeCredential, scopes);

客户端凭据提供程序

客户端凭据流使服务应用程序无需用户交互即可运行。 访问基于应用程序的标识。 有关详细信息,请参阅 Microsoft 标识平台 和 OAuth 2.0 客户端凭据流

使用客户端证书

var scopes = new[] { "https://graph.microsoft.com/.default" };

// Values from app registration
var clientId = "YOUR_CLIENT_ID";
var tenantId = "YOUR_TENANT_ID";
var clientCertificate = new X509Certificate2("MyCertificate.pfx");

// using Azure.Identity;
var options = new ClientCertificateCredentialOptions
{
    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
};

// https://learn.microsoft.com/dotnet/api/azure.identity.clientcertificatecredential
var clientCertCredential = new ClientCertificateCredential(
    tenantId, clientId, clientCertificate, options);

var graphClient = new GraphServiceClient(clientCertCredential, scopes);

使用客户端密码

// The client credentials flow requires that you request the
// /.default scope, and pre-configure your permissions on the
// app registration in Azure. An administrator must grant consent
// to those permissions beforehand.
var scopes = new[] { "https://graph.microsoft.com/.default" };

// Values from app registration
var clientId = "YOUR_CLIENT_ID";
var tenantId = "YOUR_TENANT_ID";
var clientSecret = "YOUR_CLIENT_SECRET";

// using Azure.Identity;
var options = new ClientSecretCredentialOptions
{
    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
};

// https://learn.microsoft.com/dotnet/api/azure.identity.clientsecretcredential
var clientSecretCredential = new ClientSecretCredential(
    tenantId, clientId, clientSecret, options);

var graphClient = new GraphServiceClient(clientSecretCredential, scopes);

代表提供程序

当应用程序调用服务/Web API(调用 Microsoft 图形 API)时,代理流适用。 有关详细信息,请阅读 Microsoft 标识平台 和 OAuth 2.0 代理流

var scopes = new[] { "https://graph.microsoft.com/.default" };

// Multi-tenant apps can use "common",
// single-tenant apps must use the tenant ID from the Azure portal
var tenantId = "common";

// Values from app registration
var clientId = "YOUR_CLIENT_ID";
var clientSecret = "YOUR_CLIENT_SECRET";

// using Azure.Identity;
var options = new OnBehalfOfCredentialOptions
{
    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
};

// This is the incoming token to exchange using on-behalf-of flow
var oboToken = "JWT_TOKEN_TO_EXCHANGE";

var onBehalfOfCredential = new OnBehalfOfCredential(
    tenantId, clientId, clientSecret, oboToken, options);

var graphClient = new GraphServiceClient(onBehalfOfCredential, scopes);

隐式提供程序

不建议使用隐式身份验证流,因为它 的缺点。 公共客户端(如本机应用和单页应用)现在应改用具有 PKCE 扩展的授权代码流。 引用

设备代码提供程序

设备代码流允许通过其他设备登录到设备。 有关详细信息,请参阅 Microsoft 标识平台 和 OAuth 2.0 设备代码流

var scopes = new[] { "User.Read" };

// Multi-tenant apps can use "common",
// single-tenant apps must use the tenant ID from the Azure portal
var tenantId = "common";

// Value from app registration
var clientId = "YOUR_CLIENT_ID";

// using Azure.Identity;
var options = new DeviceCodeCredentialOptions
{
    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
    ClientId = clientId,
    TenantId = tenantId,
    // Callback function that receives the user prompt
    // Prompt contains the generated device code that user must
    // enter during the auth process in the browser
    DeviceCodeCallback = (code, cancellation) =>
    {
        Console.WriteLine(code.Message);
        return Task.FromResult(0);
    },
};

// https://learn.microsoft.com/dotnet/api/azure.identity.devicecodecredential
var deviceCodeCredential = new DeviceCodeCredential(options);

var graphClient = new GraphServiceClient(deviceCodeCredential, scopes);

集成的 Windows 提供程序

集成的 Windows 流允许 Windows 计算机在以无提示方式加入域时获取访问令牌。 有关详细信息,请参阅集成Windows 身份验证

Azure.Identity 当前不支持 Windows 集成身份验证。 而是使用 MSAL 创建自定义访问令牌提供程序。

访问令牌提供程序

public class IntegratedWindowsTokenProvider : IAccessTokenProvider
{
    private readonly IPublicClientApplication publicClient;

    /// <summary>
    /// Initializes a new instance of the <see cref="IntegratedWindowsTokenProvider"/> class.
    /// </summary>
    /// <param name="clientId">The client ID from the app registration in Azure.</param>
    /// <param name="tenantId">The tenant ID from the app registration in Azure.</param>
    public IntegratedWindowsTokenProvider(string clientId, string tenantId)
    {
        // From MSAL (Microsoft.Identity.Client)
        publicClient = PublicClientApplicationBuilder
            .Create(clientId)
            .WithTenantId(tenantId)
            .Build();

        AllowedHostsValidator = new AllowedHostsValidator();
    }

    /// <summary>
    /// Gets an <see cref="AllowedHostsValidator"/> that validates if the
    /// target host of a request is allowed for authentication.
    /// </summary>
    public AllowedHostsValidator AllowedHostsValidator { get; }

    /// <inheritdoc/>
    public async Task<string> GetAuthorizationTokenAsync(
        Uri uri,
        Dictionary<string, object>? additionalAuthenticationContext = null,
        CancellationToken cancellationToken = default)
    {
        var scopes = new[] { "User.Read" };
        var result = await publicClient
            .AcquireTokenByIntegratedWindowsAuth(scopes)
            .ExecuteAsync(cancellationToken);
        return result.AccessToken;
    }
}

创建客户端

// Multi-tenant apps can use "common",
// single-tenant apps must use the tenant ID from the Azure portal
var tenantId = "common";

// Value from app registration
var clientId = "YOUR_CLIENT_ID";

var authenticationProvider = new BaseBearerTokenAuthenticationProvider(
    new IntegratedWindowsTokenProvider(clientId, tenantId));

var graphClient = new GraphServiceClient(authenticationProvider);

return graphClient;

交互式提供程序

交互式流由移动应用程序 (Xamarin 和 UWP) 和桌面应用程序使用,以用户的名义调用 Microsoft Graph。 有关详细信息,请参阅 以交互方式获取令牌

var scopes = new[] { "User.Read" };

// Multi-tenant apps can use "common",
// single-tenant apps must use the tenant ID from the Azure portal
var tenantId = "common";

// Value from app registration
var clientId = "YOUR_CLIENT_ID";

// using Azure.Identity;
var options = new InteractiveBrowserCredentialOptions
{
    TenantId = tenantId,
    ClientId = clientId,
    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
    // MUST be http://localhost or http://localhost:PORT
    // See https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/System-Browser-on-.Net-Core
    RedirectUri = new Uri("http://localhost"),
};

// https://learn.microsoft.com/dotnet/api/azure.identity.interactivebrowsercredential
var interactiveCredential = new InteractiveBrowserCredential(options);

var graphClient = new GraphServiceClient(interactiveCredential, scopes);

用户名/密码提供程序

用户名/密码提供程序允许应用程序使用其用户名和密码登录用户。 仅当不能使用任何其他 OAuth 流时,才使用此流。 有关详细信息,请参阅 Microsoft 标识平台 和 OAuth 2.0 资源所有者密码凭据

var scopes = new[] { "User.Read" };

// Multi-tenant apps can use "common",
// single-tenant apps must use the tenant ID from the Azure portal
var tenantId = "common";

// Value from app registration
var clientId = "YOUR_CLIENT_ID";

// using Azure.Identity;
var options = new UsernamePasswordCredentialOptions
{
    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
};

var userName = "adelev@contoso.com";
var password = "Password1!";

// https://learn.microsoft.com/dotnet/api/azure.identity.usernamepasswordcredential
var userNamePasswordCredential = new UsernamePasswordCredential(
    userName, password, tenantId, clientId, options);

var graphClient = new GraphServiceClient(userNamePasswordCredential, scopes);

后续步骤