【问题标题】:Verify if user account exists in Azure Active Directory验证 Azure Active Directory 中是否存在用户帐户
【发布时间】:2021-03-03 13:08:13
【问题描述】:

我需要按照一些业务规则从 ASP.NET Core 2 应用程序向用户发送电子邮件。但是,我需要确保发送电子邮件的帐户确实存在(由于某种原因,可能是该帐户不再有效)。客户正在使用 Azure Active Directory,因此我需要以某种方式查询 AAD,以便让我知道该帐户是否存在。

到目前为止,我一直在寻找 Microsoft Graph 作为一种方法来执行此操作,但是到目前为止我看到的每个示例都需要预先身份验证并使用委托身份验证机制。我不希望我的用户必须进行身份验证,也不想提示身份验证屏幕。

鉴于这种情况,您建议使用什么?如果你也可以给我举个例子,那就太好了。谢谢!

【问题讨论】:

    标签: asp.net-core azure-active-directory microsoft-graph-api


    【解决方案1】:

    您实际上不需要像在当前代码中那样为每个无效用户抛出/捕获异常。出于其他原因,我一般不反对异常处理,但要查看用户是否存在,您可以尝试使用 Filter

    所以你的图形查询可能看起来像 -

    https://graph.microsoft.com/v1.0/users?$filter=startswith(userPrincipalName,'someuser@mytenant.onmicrosoft.com')
    

    我在这里展示了 startswith 因为eq 在快速试用中对我不起作用。虽然我会推荐两件事:

    这是您的代码的修改版本。

    请注意,我正在检查集合计数是否大于 0,而不是检查它是否为空,因为即使在未找到用户的情况下,我的测试运行的 UsersCollectionPage 也不为空。

    using Microsoft.Identity.Client;
    using Microsoft.Graph.Auth;
    using Microsoft.Graph;
    ...
    
    private async Task<bool> ValidateAccounts(string accounts) {
        var confidentialClientApplication = ConfidentialClientApplicationBuilder
            .Create("clientId here")
            .WithTenantId("tokenId here")
            .WithClientSecret("secret here")
            .Build();
        var authProvider = new ClientCredentialProvider(confidentialClientApplication);
        var graphClient = new GraphServiceClient(authProvider);
    
        var valid = true;
        try {
            foreach (var account in accounts.Split(';')) {
                var user = await graphClient.Users.Request().Filter("startswith(userPrincipalName, '" + account + "')").GetAsync();
    
                if (user.Count <= 0) {
                    valid = false;
                    break;
                }
            }
        } catch (ServiceException ex) {
            valid = false;
        }
    
        return valid;
    }
    

    附带说明,我不确定您的要求,但您可以通过在单个查询中组合多个用户名然后检查结果计数或其他属性来获得创意。您可以在多个条件之间使用 or 或可能使用 any 运算符。不过我还没有真正尝试过。

    【讨论】:

      【解决方案2】:

      最后我想出了一些可行的方法。这不好,它使用预览软件。首先,安装 Microsoft.Graph 和 Microsoft.Identity.Client 包。然后安装 Microsoft.Graph.Auth,在撰写本文时,它处于预览阶段 (v1.0.0-preview.1),因此您需要在 nuget 管理器中勾选“包含预发布”复选框。

      然后在您的 AAD 中,您需要获取 ClientId、TenantId 和 SecretId。就我而言,我的应用程序已经在使用 AAD 身份验证,因此我的 appsettings.json 文件中已经有了 ClientId 和 TenantId。我只需要创建一个新的 SecretId(在我的应用注册的证书和机密部分)。然后我需要添加权限(在我的应用注册的 API 权限部分)以包含 Microsoft.Graph 至少具有 User.Read.All 权限。

      using Microsoft.Identity.Client;
      using Microsoft.Graph.Auth;
      using Microsoft.Graph;
      ...
      
      private async Task<bool> ValidateAccounts(string accounts) {
          var confidentialClientApplication = ConfidentialClientApplicationBuilder
              .Create("clientId here")
              .WithTenantId("tokenId here")
              .WithClientSecret("secret here")
              .Build();
          var authProvider = new ClientCredentialProvider(confidentialClientApplication);
          var graphClient = new GraphServiceClient(authProvider);
      
          var valid = true;
          try {
              foreach (var account in accounts.Split(';')) {
                  var user = await graphClient.Users[account]
                      .Request()
                      .GetAsync();
                  if (user == null) {
                      valid = false;
                      break;
                  }
              }
          } catch (ServiceException ex) {
              valid = false;
          }
      
          return valid;
      }
      

      这里,该函数为每个帐户采用分号分隔的字符串。如果用户不存在,GetAsync 方法将引发 ServiceException。我不喜欢这样,但找不到其他方法。就是这样。希望这对其他人有所帮助,并希望有人最终能提出更好的解决方案。

      【讨论】:

        【解决方案3】:

        导入以下命名空间(需要使用nuget安装相关包):

        using Microsoft.Graph;
        using Microsoft.IdentityModel.Clients.ActiveDirectory;
        

        设置您的 Azure AD 应用值:

        private string _tenant => "your_tenant_id";
        private string _appId => "your_ad_app_client_id";
        private string _appSecret => "your_app_client_secret";
        

        使用此创建图形服务客户端:

        public static GraphServiceClient CreateGraphServiceClient()
        {
          var clientCredential = new ClientCredential(_appId, _appSecret);
          var authenticationContext = new AuthenticationContext("https://login.microsoftonline.com/{_tenant}");
          var authenticationResult = authenticationContext.AcquireTokenAsync("https://graph.microsoft.com", clientCredential).Result;
        
          var delegateAuthProvider = new DelegateAuthenticationProvider((requestMessage) =>
          {
            requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", authenticationResult.AccessToken);
        
            return Task.FromResult(0);
           });
        
          return new GraphServiceClient(delegateAuthProvider);
         }
        
        
        var graphServiceClient = GraphServiceClientHelper.CreateGraphServiceClient();
        

        然后调用graph api并通过Email地址过滤用户如下:

        var user = await graphServiceClient.Users.Request().Filter("mail eq '" + UserEmailAddress + "'").GetAsync();
        if (user.Count == 0) {
            //user not exist
        }
        

        【讨论】:

          【解决方案4】:

          下面的代码对我有用。

          using Microsoft.Graph;
          using Microsoft.Graph.Auth;
          using Microsoft.Identity.Client;
          
          
          private static async Task<bool> ValidateAccounts(string accounts)
          {
                  var confidentialClientApplication = ConfidentialClientApplicationBuilder
                      .Create("client id")
                      .WithTenantId("tenant id")
                      .WithClientSecret("client secret")
                      .Build();
          
                  var authProvider = new ClientCredentialProvider(confidentialClientApplication);
                  var graphClient = new GraphServiceClient(authProvider);
          
                  var valid = true;
                  try
                  {
                      foreach (var account in accounts.Split(';'))
                      {
                      var user = await 
          graphClient.Users.Request().Filter($"identities/any(c:c/issuerAssignedId eq 
          '{account}' and c/issuer eq 'xyz.onmicrosoft.com')").GetAsync();
                      
                          if (user.Count <= 0)
                          {
                              valid = false;
                              break;
                          }
                      }
                  }
                  catch(Exception ex)
                  {
                      valid = false;
                  }
                  return valid;
              }
          

          【讨论】:

          • 代码中有错字 (lientCredentialProvider)。另外,请不要发布只是代码的答案。解释您提供的代码如何解决问题以及您知道的任何假设或限制。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-15
          • 2015-04-24
          • 2020-09-20
          • 1970-01-01
          • 2015-01-02
          • 2021-10-29
          相关资源
          最近更新 更多