Verify if user account exists in Azure Active Directory

纵饮孤独 提交于 2021-02-08 04:29:12

问题


I need to send an email to users from an ASP.NET Core 2 application, following some business rules. However, I need to ensure that the account the email is being sent to actually exists (for some reason, it may be that the account stopped being valid). The customer is using Azure Active Directory, so I need to query AAD somehow so it lets me know whether the account exists or not.

So far I have been looking for Microsoft Graph as a way to do this, however every example I have seen so far requires prior authentication and use a delegate authentication mechanism. I don't want my users having to authenticate nor to prompt the authentication screen.

Given this situation, what would you recommend using? If you can also point me to an example, that would be great. Thanks!


回答1:


You don't really need to throw/catch exception for every invalid user as you're doing in current code. I have nothing against exception handling in general for other reasons but to see if the user exists or not you can try using Filter.

So your graph query could look like -

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

I have shown startswith here becuase eq didn't work for me in a quick trial. Although I would recommend two things:

  • Go through Microsoft documentation on Filters here and see what works best for your requirements - Use query parameters to customize responses with Microsoft Graph
  • Play a little bit with different queries in Microsoft Graph Explorer it's very simple and easy to use.

Here is a modified version for your code.

Note that I'm checking for the collection count to be > 0 and not checking for it to be null, as even in case user is not found the UsersCollectionPage was not null for my test run.

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;
}

On a side note, I'm not not sure of your requirements but you could probably get creative by combining multiple user names in single query and then checking for result counts or other propertes. You could use or between multiple criteria or probably use any operator. I haven't really tried this out though.




回答2:


Finally I came up with something workable. It's not nice, and it uses preview software. First, install Microsoft.Graph and Microsoft.Identity.Client packages. Then install Microsoft.Graph.Auth, which at the time of this writing, is in preview (v1.0.0-preview.1) so you'll need to tick "include prerelease" checkbox in nuget manager.

Then in your AAD, you need to get the ClientId, TenantId and SecretId. In my case, my app was already using AAD authentication so I already had ClientId and TenantId in my appsettings.json file. I only needed to create a new SecretId (in the Certificate & secrets section of my app registration). Then I needed to add permissions (in the API permissions section of my app registration) to include Microsoft.Graph with at least User.Read.All permission.

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;
}

Here, the function takes a semicolon-separated string for each account. The GetAsync method will throw a ServiceException if the user does not exist. I don't like that, but couldn't find another way. So that's about it. Hope this helps someone else, and hope someone could come up with a better solution eventually.




回答3:


Import following namespaces (You needs to install relevant packages using nuget):

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

Set your Azure AD app values:

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

Create Graph Service Client using this:

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();

Then call graph api and filter users by Email Address as follows:

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


来源:https://stackoverflow.com/questions/58380915/verify-if-user-account-exists-in-azure-active-directory

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!