title: Microsoft Graph accessing Me
body: <p>I have an application setup that using Azure AD (Work or School Account) to log a user into the application.  I also want to be able to query Microsoft Graph from this application using Delegated Permissions.  I believe what I have setup is using Application Permissions and I don't see what I'm missing to get this setup correctly.  The application is ASP.NET Core 2 application.</p>
  
  <p>In my Startup.cs I have the following code.</p>
  
  <pre><code>public void ConfigureServices(IServiceCollection services)
  {
      services.AddAuthentication(sharedOptions =&gt;
      {
          sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
          sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
          sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
      })
      .AddAzureAd(options =&gt; Configuration.Bind("AzureAd", options))
      .AddCookie();
  
      services.AddMvc();
  
      services.AddSingleton(Configuration);
      services.AddSingleton&lt;IGraphAuthProvider, GraphAuthProvider&gt;();
      services.AddTransient&lt;IGraphSDKHelper, GraphSDKHelper&gt;();
  }
  
  // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  {
      if (env.IsDevelopment())
      {
          app.UseDeveloperExceptionPage();
          app.UseBrowserLink();
      }
      else
      {
          app.UseExceptionHandler("/Home/Error");
      }
  
      app.UseStaticFiles();
  
      app.UseAuthentication();
  
      app.UseMvc(routes =&gt;
      {
          routes.MapRoute(
              name: "default",
              template: "{controller=Home}/{action=Index}/{id?}");
      });
  }
  </code></pre>
  
  <p>The AddAzureAd is an extension method defined here:  </p>
  
  <p><strong>After working with Marc</strong> 
  I have found that problem is that the OnAuthorizationCodeReceived event below is never firing.  I don't know why, but is the root of the problem.</p>
  
  <pre><code>public static class AzureAdAuthenticationBuilderExtensions
  {        
      public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder)
          =&gt; builder.AddAzureAd(_ =&gt; { });
  
      public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder, Action&lt;AzureAdOptions&gt; configureOptions)
      {
          builder.Services.Configure(configureOptions);
          builder.Services.AddSingleton&lt;IConfigureOptions&lt;OpenIdConnectOptions&gt;, ConfigureAzureOptions&gt;();
          builder.AddOpenIdConnect(opts =&gt;
          {
              opts.Events = new OpenIdConnectEvents
              {
                  OnAuthorizationCodeReceived = async ctx =&gt;
                  {
                      var request = ctx.HttpContext.Request;
                      var currentUri =
                          UriHelper.BuildAbsolute(request.Scheme, request.Host, request.PathBase, request.Path);
                      var credential = new ClientCredential(ctx.Options.ClientId, ctx.Options.ClientSecret);
  
                      var distributedCache = ctx.HttpContext.RequestServices.GetRequiredService&lt;IDistributedCache&gt;();
                      var userId = ctx.Principal
                          .FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")
                          .Value;
                      var cache = new AdalDistributedTokenCache(distributedCache, userId);
                      var authContext = new AuthenticationContext(ctx.Options.Authority, cache);
                      var result = await authContext.AcquireTokenByAuthorizationCodeAsync(ctx.ProtocolMessage.Code,
                          new Uri(currentUri), credential, ctx.Options.Resource);
                      ctx.HandleCodeRedemption(result.AccessToken, result.IdToken);
                  }
              };
          });
          return builder;
      }
  
      private class ConfigureAzureOptions: IConfigureNamedOptions&lt;OpenIdConnectOptions&gt;
      {
          private readonly AzureAdOptions _azureOptions;
  
          public ConfigureAzureOptions(IOptions&lt;AzureAdOptions&gt; azureOptions)
          {
              _azureOptions = azureOptions.Value;
          }
  
          public void Configure(string name, OpenIdConnectOptions options)
          {
              options.ClientId = _azureOptions.ClientId;
              options.Authority = $"{_azureOptions.Instance}{_azureOptions.TenantId}";
              options.UseTokenLifetime = true;
              options.CallbackPath = _azureOptions.CallbackPath;
              options.RequireHttpsMetadata = false;
          }
  
          public void Configure(OpenIdConnectOptions options)
          {
              Configure(Options.DefaultName, options);
          }
      }
  }
  </code></pre>
  
  <p>The AdalDistributeTokenCache class looks like this:</p>
  
  <pre><code>    internal class AdalDistributedTokenCache : TokenCache
      {
          private readonly IDistributedCache cache;
          private readonly string userId;
  
          public AdalDistributedTokenCache(IDistributedCache cache, string userId)
          {
              this.cache = cache;
              this.userId = userId;
  
              BeforeAccess = OnBeforeAccess;
              AfterAccess = OnAfterAccess;
          }
  
          private void OnBeforeAccess(TokenCacheNotificationArgs args)
          {
              var userTokenCachePayload = cache.Get(CacheKey);
              if (userTokenCachePayload != null)
              {
                  Deserialize(userTokenCachePayload);
              }
          }
  
          private void OnAfterAccess(TokenCacheNotificationArgs args)
          {
              if (HasStateChanged)
              {
                  var cacheOptions = new DistributedCacheEntryOptions
                  {
                      AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(14)
                  };
  
                  cache.Set(CacheKey, Serialize(), cacheOptions);
  
                  HasStateChanged = false;
              }
          }
  
          private string CacheKey =&gt; $"TokenCache_{userId}";
      }
  }
  </code></pre>
  
  <p>From everything that I have read this looks like the correct setup for what I'm trying to do.  Now in the homepage controller I have the following code</p>
  
  <pre><code>public async Task&lt;IActionResult&gt; Index(string email)
  {
      // Get users's email.
      email = email ?? User.Identity.Name;
      ViewData["Email"] = email;
  
      // Get user's id for token cache.
      var identifier = User.FindFirst(Startup.ObjectIdentifierType)?.Value;
  
      // Initialize the GraphServiceClient.
      var graphClient = _graphSdkHelper.GetAuthenticatedClient(identifier);
  
      ViewData["Response"] = await GraphService.GetUserJson(graphClient, email);
      ViewData["Response"] = await GraphService.GetMeJson(graphClient, email);
  
      //ViewData["Picture"] = await GraphService.GetPictureBase64(graphClient, email);
      var groups = await GraphService.GetGroups(graphClient);
      return View();
  }
  </code></pre>
  
  <p>The line that says GetUserJson works and calls a method that looks like this</p>
  
  <pre><code>var user = await graphClient.Users[email].Request().GetAsync();
  return JsonConvert.SerializeObject(user, Formatting.Indented);
  </code></pre>
  
  <p>The line that says GetMeJson does work and through an error and it looks like</p>
  
  <pre><code>var user = await graphClient.Me.Request().GetAsync();
  return JsonConvert.SerializeObject(user, Formatting.Indented);
  </code></pre>
  
  <p>The last piece of code is the GetAuthenticatedClient and it looks like</p>
  
  <pre><code>public GraphServiceClient GetAuthenticatedClient(string userId)
  {
      _graphClient = new GraphServiceClient("https://graph.microsoft.com/beta", new DelegateAuthenticationProvider(
          async (requestMessage) =&gt;
          {
              // Passing tenant ID to the sample auth provider to use as a cache key
              AccessToken = await _authProvider.GetUserAccessTokenAsync(userId);
  
              // Append the access token to the request
              requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
          }));
  
      return _graphClient;
  }
  </code></pre>
  
  <p>The error message that I get is this:</p>
  
  <pre><code>Microsoft.Graph.ServiceException: 
     Code: Request_ResourceNotFound
     Message: Resource '40f381c1-55f3-4295-99e3-0309a704374e' does not 
              exist or one of its queried reference-property objects 
              are not present.
  </code></pre>
  
  <p>Can somebody help me get through this hurdle, so I can call the Graph API as the authenticated user.</p>
  
  <p>***********Additional Info request by Marc*************</p>
  
  <p>The application is registered through portal.azure.com and has the following permissions.</p>
  
  <p>Under Microsoft Graph
  Under Application Permissions, User.Read.All, Directory.Read.All, Group.Read.All
  Under Delegated Permissions, Profile (View users' basic profile), email (View users' email address), Directory.Read.All. Group.Read.All, User.Read.All, User.ReadBasic.All</p>
  
  <p>Under Windows Azure Active Directory
  Under Delegated Permissions: User.Read (Sign in and read user profile)</p>
  
  <p>I now know that I shouldn't need the Application Permissions and can remove them at some point, but I don't have permission to do that and need to get somebody else to do it for me.</p>
  
  <p>**********Debugging token*********
  I put a breakpoint at the line</p>
  
  <pre><code>AccessToken = await _authProvider.GetUserAccessTokenAsync(userId);
  </code></pre>
  
  <p>Then took the AccessToken that it got here and put it in calebb.net and got the following results.</p>
  
  <pre><code>{
   typ: "JWT",
   nonce: "bunch of letters",
   alg: "RS256",
   x5t: "bunch of letters",
   kid: "bunch of letters"
  }.
  {
   aud: "https://graph.microsoft.com/",
   iss: "https://sts.windows.net/dde15eeb-a6bd-46a2-9f03-d44429074ecf/",
   iat: 1503942101,
   nbf: 1503942101,
   exp: 1503946001,
   aio: "bunch of letters",
   app_displayname: "Test App",
   appid: "Guid",
   appidacr: "1",
   e_exp: 262800,
   idp: "https://sts.windows.net/dde15eeb-a6bd-46a2-9f03-d44429074ecf/",
   oid: "Guid",
   roles: [
    "Group.Read.All",
    "Directory.Read.All",
    "User.Read.All"
   ],
   sub: "Guid",
   tid: "Guid",
   uti: "bunch of letters",
   ver: "1.0"
  }.
  [signature]
  </code></pre>
  
  <p>As you suspected it only as the App Permissions and not the Delegated Permissions.  So what is wrong with this section of where it gets the token.  I'm obviously not doing the correct type of authentication here, but I don't know what I'm doing wrong.</p>
  
  <pre><code>public async Task&lt;string&gt; GetUserAccessTokenAsync(string userId)
  {
      TokenCache userTokenCache = new SessionTokenCache(userId, _memoryCache).GetCacheInstance();
  
      try
      {
          AuthenticationContext authContext = new AuthenticationContext(_aadInstance, userTokenCache);
          ClientCredential credential = new ClientCredential(_appId, _appSecret);
          AuthenticationResult result = await authContext.AcquireTokenAsync(_graphResourceId, credential);
  
          return result.AccessToken;
      }
      catch (Exception ex)
      {
          return null;
      }
  }
  </code></pre>