title: Calling Graph API through ViewModel in MVC Web App
body: <p>I'm trying to use Graph API to create my own "User Profile" section of the navbar of my web app.  To do this I have an AJAX call to a GetUser Action of my UserProfile Controller:</p>
  
  <pre><code>        $.ajax({
          type: "GET",
          url: "@Url.Action("GetUser", "UserProfile", null)",
          dataType: "json",
          success: function (data, status, xhr) {
              console.log("in AJAX");
              $(".img-circle, .user-image").attr("src", data.Picture);
              $("#user-menu-expanded").text(data.User.DisplayName + " - " + data.User.JobTitle);
              $("#user-menu-spinner").remove();
              console.log(data);
          },
          error: function (ex) {
              console.log(ex);
              }
          });
  </code></pre>
  
  <p>The controller returns my UserProfileViewModel as a Json which I use to replace the above elements as shown in my AJAX success function.</p>
  
  <p>UserProfile Controller:</p>
  
  <pre><code>    public JsonResult GetUser()
      {
          var model = new UserProfileViewModel();
          return Json(model, JsonRequestBehavior.AllowGet); 
      }
  </code></pre>
  
  <p>My UserProfileViewModel looks like this: </p>
  
  <pre><code>    public UserProfileViewModel()
      { 
              var graphClient = GetAuthGraphClient();
              GetPicture(graphClient);
              GetUserProfile(graphClient); 
       }
      public GraphServiceClient GetAuthGraphClient()
      {
          string graphResourceID = "https://graph.microsoft.com/";
  
          return new GraphServiceClient(
              new DelegateAuthenticationProvider((requestMessage) =&gt;
              {
                  string accessToken =  GetTokenForApplication(graphResourceID);
                  requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
                  return Task.FromResult(0);
              }
              ));
      }
      public string GetTokenForApplication(string graphResourceID)
      {
          string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
          string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
          string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
          string authority = "https://login.microsoftonline.com/" + tenantID;
  
          try {
              ClientCredential clientcred = new ClientCredential(clientId, appKey);
              // initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app's database
              AuthenticationContext authenticationContext = new AuthenticationContext(authority);
              var token = authenticationContext.AcquireTokenAsync(graphResourceID, clientcred).Result.AccessToken;
              return token;
          }
          catch (Exception e)
          {
                  // Capture error for handling outside of catch block
                  ErrorMessage = e.Message;
  
              return null;
          }
  
      }
      public void GetPicture(GraphServiceClient graphClient)
      { 
          Stream photo = Task.Run(async () =&gt; { return await graphClient.Me.Photo.Content.Request().GetAsync(); }).Result;
  
          using (var memoryStream = new MemoryStream())
          {
              photo.CopyTo(memoryStream);
              var base64pic = Convert.ToBase64String(memoryStream.ToArray());
              this.Picture = "data:image;base64," + base64pic;
              HttpContext.Current.Cache.Add("Pic", this.Picture, null, DateTime.Now.AddHours(5), Cache.NoSlidingExpiration, CacheItemPriority.AboveNormal, null);
          }
      }
  
      public void GetUserProfile(GraphServiceClient graphClient)
      {       
          this.User = Task.Run(async () =&gt; { return await graphClient.Me.Request().GetAsync(); }).Result;
      }
  </code></pre>
  
  <p>I am successfully getting an access token, however my AJAX call is not returning any data.<br>
  <a href="https://i.stack.imgur.com/dxWSm.png" rel="nofollow noreferrer">Access Token from IIS Log</a>
  <a href="https://i.stack.imgur.com/VBboi.png" rel="nofollow noreferrer">Console Log</a></p>
  
  <p>I have two questions (possibly 3):</p>
  
  <ol>
  <li>What am I doing wrong? </li>
  <li><p>Is it possible to use the access token
  from my Startup.Auth to create an authenticated Graph Client? If so,
  how would I go about doing that?</p>
  
  <pre><code>    // This is the resource ID of the AAD Graph API.  We'll need this to request a token to call the Graph API.
      string graphResourceId = "https://graph.microsoft.com"; //https://graph.windows.net
  
      public void ConfigureAuth(IAppBuilder app)
      {
          ApplicationDbContext db = new ApplicationDbContext();
  
          app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
          app.UseKentorOwinCookieSaver();
          app.UseCookieAuthentication(new CookieAuthenticationOptions());
  
          app.UseOpenIdConnectAuthentication(
              new OpenIdConnectAuthenticationOptions
              {
                  ClientId = clientId,
                  Authority = Authority,
                  PostLogoutRedirectUri = postLogoutRedirectUri,
  
                  Notifications = new OpenIdConnectAuthenticationNotifications()
                  {
                      // If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
                      AuthorizationCodeReceived = (context) =&gt;
                      {
                          var code = context.Code;                            
                          ClientCredential credential = new ClientCredential(clientId, appKey);
                          string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
                          AuthenticationContext authContext = new AuthenticationContext(Authority, new ADALTokenCache(signedInUserID));
                          AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
                          code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId);
                          HttpContext.Current.Cache.Add("Token", result.AccessToken, null, DateTime.Now.AddHours(5), Cache.NoSlidingExpiration, CacheItemPriority.AboveNormal, null);
  
                          return Task.FromResult(0);
                      }
                  }
              });
      }
  }
  </code></pre></li>
  </ol>
  
  <p><strong>Updated Code per Comment Below</strong></p>
  
  <pre><code>    public string GetTokenForApplication(string graphResourceID)
      {
          string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
          string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
          string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
          string authority = "https://login.microsoftonline.com/" + tenantID;
  
  
          try {
              // get a token for the Graph without triggering any user interaction (from the cache, via multi-resource refresh token, etc)
              ClientCredential clientcred = new ClientCredential(clientId, appKey);
              // initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app's database
              AuthenticationContext authenticationContext = new AuthenticationContext(Startup.Authority, new ADALTokenCache(userObjectID));
              var result = authenticationContext.AcquireTokenSilent(graphResourceID, clientcred, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
              return result.AccessToken;
          }
          catch (Exception e)
          {
                  // Capture error for handling outside of catch block
                  ErrorMessage = e.Message;
  
              return null;
          }
  
      }
  </code></pre>
  
  <p><strong>Update 2: The Fix.. Kind of</strong></p>
  
  <p>Thanks to @Fei Xue I figured out the problem.. kind of.  This fixes my problem when running locally, but I still fail to acquire the token silently when publishing to my stage application..  When I first created the application, I included Work/School authentication that was Azure AD.  This created a local DB Context that it used for the ADAL token cache.  While developing the application, I created another DB Context for the Azure SQL DB I created for the app.  I had to update my AdalTokenCache.cs to reflect my app's DB context and the new model.  I updated the line:</p>
  
  <pre><code>private ApplicationDbContext db = new ApplicationDbContext();
  </code></pre>
  
  <p>with my own context and updated the UserTokenCache model to my new context's UserTokenCache model.  In this case I changed:</p>
  
  <pre><code>private UserTokenCache Cache;
  </code></pre>
  
  <p>to:</p>
  
  <pre><code>private UserTokenCach Cache;
  </code></pre>
  
  <p>I then updated the rest of the CS to match the UserTokenCach from the app's DB context.</p>
  
  <p>I then just used the AcquireToken method that came OOB in the UserProfile controller to get a token.  This is what it wound up looking like (Note: I also updated the strings in my startup.auth from private to public so I could use them in my viewmodel):</p>
  
  <pre><code>    public string GetTokenForApplication(string graphResourceID)
      {
          string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
          string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
          string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
          string authority = "https://login.microsoftonline.com/" + tenantID;
  
  
          try {
              // get a token for the Graph without triggering any user interaction (from the cache, via multi-resource refresh token, etc)
              ClientCredential clientcred = new ClientCredential(Startup.clientId, Startup.appKey);
              // initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app's database
              AuthenticationContext authenticationContext = new AuthenticationContext(Startup.Authority, new ADALTokenCache(signedInUserID));
              var result = authenticationContext.AcquireTokenSilent(graphResourceID, clientcred, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
              return result.AccessToken;
          }
          catch (Exception e)
          {
                  // Capture error for handling outside of catch block
                  ErrorMessage = e.Message;
  
              return null;
          }
  
      }
  </code></pre>
  
  <p>I'll update as I play around some more. </p>