Microsoft Graph API.NET - Ability to pull out all users (including me), but not just me

I opened this question again. See My Editing below.

Using the VS 2017 Template ASP.NET MVC Web Application Using the Job / School-Based Authentication Project

I get this error:

The Graph API has expired. Click here to log in and get a new access token.

when I try to get basic information only about myself, and I have no problem when I retrieve my information along with basically everyone else in my AD.

UserProfileController.cs: (function definitions)

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using System.Threading.Tasks;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.OpenIdConnect;
using MY_PROJECT.Utilities;
using Microsoft.Graph;

namespace MY_PROJECT.Controllers
{
    [Authorize]
    public class UserProfileController : Controller
    {
        /// <summary>
        /// Get the signed-in user
        /// </summary>
        /// <returns>A single User</returns>
        public async Task<User> GetMe()
        {
            GraphServiceClient graphClient = new GraphServiceClient(new AzureAuthenticationProvider());

            return await graphClient.Me.Request().GetAsync();
        }

        /// <summary>
        /// Get all users in the organization
        /// </summary>
        /// <returns>A list of Users</returns>
        public async Task<List<User>> GetAllUsers()
        {
            List<User> userResult = new List<User>();

            GraphServiceClient graphClient = new GraphServiceClient(new AzureAuthenticationProvider());
            IGraphServiceUsersCollectionPage users = await graphClient.Users.Request().Top(500).GetAsync(); // Hard coded to pull 500 users
            userResult.AddRange(users);

            // Users are returned as pages; keep pulling pages until we run out of them
            while (users.NextPageRequest != null)
            {
                users = await users.NextPageRequest.GetAsync();
                userResult.AddRange(users);
            }

            return userResult;
        }

        public async Task<ActionResult> Index()
        {
            try
            {
                // Get the signed-in user profile
                User me = await GetMe();

                return View(me);
            }
            catch (AdalException)
            {
                // Return to error page.
                return View("Error");
            }
            // if the above failed, the user needs to explicitly re-authenticate for the app to obtain the required token
            catch (Exception)
            {
                return View("Relogin");
            }
        }

        [Authorize(Roles = "Admin")]
        public async Task<ActionResult> Admin()
        {
            try
            {
                var user = await GetAllUsers();

                return View(user);
            }
            catch (AdalException)
            {
                // Return to error page.
                return View("Error");
            }
            // if the above failed, the user needs to explicitly re-authenticate for the app to obtain the required token
            catch (Exception)
            {
                return View("Relogin");
            }
        }

        public void RefreshSession()
        {
            HttpContext.GetOwinContext().Authentication.Challenge(
                new AuthenticationProperties { RedirectUri = "/UserProfile" },
                OpenIdConnectAuthenticationDefaults.AuthenticationType);
        }
    }
}

AzureAuthenticationProvider.cs (handles MS Graph API connection)

using System.Configuration;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using MY_PROJECT.Models;
using Microsoft.Graph;
using Microsoft.IdentityModel.Clients.ActiveDirectory;

namespace MY_PROJECT.Utilities
{
    class AzureAuthenticationProvider : IAuthenticationProvider
    {
        private string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
        private string appKey = ConfigurationManager.AppSettings["ida:ClientSecret"];
        private string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];

        public async Task AuthenticateRequestAsync(HttpRequestMessage request)
        {
            string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
            string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;

            // get a token for the Graph without triggering any user interaction (from the cache, via multi-resource refresh token, etc)
            ClientCredential creds = new ClientCredential(clientId, appKey);
            // initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app database
            AuthenticationContext authenticationContext = new AuthenticationContext(aadInstance + tenantID, new ADALTokenCache(signedInUserID));
            AuthenticationResult authResult = await authenticationContext.AcquireTokenAsync("https://graph.microsoft.com/", creds);

            request.Headers.Add("Authorization", "Bearer " + authResult.AccessToken);
        }
    }
}

Admin.cshtml (where all users end)

@using Microsoft.Ajax.Utilities
@using Microsoft.Graph
@model List<User>

@{
    ViewBag.Title = "Admin";
}
<h2>@ViewBag.Title.</h2>

<div class="input-group">
    // search text box
</div>

<table id="userTable" class="table table-bordered table-responsive">
    <thead>
    <tr>
        <th>Name</th>
        <th>Email</th>
    </tr>
    </thead>
    @foreach (var user in Model
        .Where(u => !u.Surname.IsNullOrWhiteSpace()))
    {
        <tr>
            <td>@user.DisplayName</td>
            <td>@user.Mail</td>
        </tr>
    }
</table>

<script>
    // search function
</script>

Admin, , : Admin page

Index.cshtml ( , )

@model Microsoft.Graph.User

@{
    ViewBag.Title = "User Profile";
}
<h2>@ViewBag.Title.</h2>

<table class="table table-bordered table-striped">
    <tr>
        <td>Display Name</td>
        <td>@Model.DisplayName</td>
    </tr>
    <tr>
        <td>First Name</td>
        <td>@Model.GivenName</td>
    </tr>
    <tr>
        <td>Last Name</td>
        <td>@Model.Surname</td>
    </tr>
    <tr>
        <td>Job Title</td>
        <td>@Model.JobTitle</td>
    </tr>
</table>

, : Redirect from index to UserProfile Graph Api Token Error

Azure Portal:

Application Permissions

, GetAllUsers() , GetMe(), , , .

?


:

TL; DR: , , ( ASP.NET)

, " " , : . . .

, , .

, : ( , , , , , . , , , . , , , ! .)

  • AAD, AAD, (, , ).
  • AAD ( , - Microsoft.IdentityModel.Clients.ActiveDirectory aka ADAL)
  • AAD ( MS Graph).
  • , Azure, - ( , , ADAL)
  • / [Authorize(Roles = "Admin")], ( ADAL System.Security.Claims)
  • AAD , ( )

:

  • , .NET, API- Microsoft Graph Azure AD, Microsoft Graph, :

graphServiceClient.Users.Request().Top(500).GetAsync();
graphServiceClient.Me.Request().GetAsync();

  • - Microsoft Graph AAD Implicit Flow, , , .
  • ADAL? Azure AD, , , ADAL , MSAL .

, .

</" >

:

Microsoft.Graph graphServiceClient, , Easy Auth .
: SDK Microsoft Graph Azure AD Easy Auth
cgillum , - Azure Portal/Resource.

+4
1

Client Credential, . me. me, Authorization Code.

:

Microsoft Authentication Library (MSAL), .

, v1, Azure AD v2. Microsoft Graph API , .

, . , , Implicit Flow, , (~ 1 ), . , Implicit Flow, , , javascript .

, , v2, :

ASP.NET, , MDAL v2 ASP.NET Microsoft Graph.NET:

+2

Source: https://habr.com/ru/post/1685117/


All Articles