Programmable authentication flow for accessing to Microsoft Graph

It is good that an app access user resource using minimum permission.
Microsoft Graph API provides a token restricted by a scope that has minimum permission to access domain resources. Therefore the app to leverage these features has to use appropriate the grant type and the scope when acquires a token.
As one of the ideas to correspond these case, the app would provide a feature which acquires a token with the ‘user.read’ scope when login and accessing information of self. And when accessing resources of the OneDrive of the login user, acquires another token with the ‘file.read’ scope without the ‘user.read’ scope.
Using a token that has properly minimum permission to do execute per an individual feature of the app is better than using a token that has all permission that is enough to execute all features of the app.
This article describes how to control tokens that have minimum permission to execute per feature. This article uses the code sample of the previous article. the previous article describes the scenario of the code sample, this article continues the 4th part of the scenario.

>>The code sample of this article

・Take token as change scope

Create acquire a token that has the ‘files.readwrite’ permission and acquire a web link that sharing the OneDrive file of the user at the ‘Index’ action of the ‘Home’ controller. Insert below code after set the ‘GlobalName’ value of the ‘user’ object to the ViewBag.

if (signIn)
{
  new AccessGraph().SetUserInfo(user);
  //Regist '髙尾 哲朗(Tetsuro Takao)' as Azure Active Directory account.
  user.GlobalName = string.Join("", Regex.Matches(user.displayName, @"[a-z | A-Z]*")).Trim();
  ViewBag.AccountName = user.GlobalName;

  var grant = "{\"password\":\"__PASSWORD__\",\"username\":\"__ACCOUNT__\"}";
  var history = new AccessHistory();
  history.GrantType = grant;
  history.Scope = "files.readwrite";
  history.TenantID = user.AccessList.FirstOrDefault().TenantID;
  history.Redirect = user.AccessList.FirstOrDefault().Redirect;
  history.ClientId = user.AccessList.FirstOrDefault().ClientId;
  history.Secret = user.AccessList.FirstOrDefault().Secret;
  user.AccessList.Add(history);
  if (new AccessGraph().GetToken(user))
  {
    var webLink = new AccessGraph().GetLink("01N7LZHZCQ2D4PKWJ4OJAKWEOBBJWTCOWG", user);
  }
}

・Create GetLink Method

Create the ‘GetLink’ method in the ‘AccessGraph’ class as below.

public class AccessGraph
{
  public bool GetToken(ApplicationUser user)
  {
    ...
  }
  public string GetToken(string clientid, string secret, string redirect, string refreshtoken, string authCode, string tenant, string resource = "user.read")
  {
    ...
  }
  public string GetUser(string token)
  {
    ...
  }
  public void SetUserInfo(ApplicationUser account)
  {
    ...
  }
  public string GetLink(string id, ApplicationUser account)
  {
    string result = string.Empty;
    var token = account.AccessList.Where(t => Regex.IsMatch(t.Scope, @"files\.readwrite", RegexOptions.IgnoreCase)).FirstOrDefault();
    if (token == null) return result;
    using (var httpClient = new HttpClient())
    {
      httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token.AuthTokens.access_token);
      var postBody = "{\"type\": \"edit\", \"scope\": \"anonymous\"}";
      var content = new StringContent(postBody, Encoding.UTF8, "application/json");
      var responseMessage = httpClient.PostAsync(string.Format("https://graph.microsoft.com/v1.0/me/drive/items/{0}/createLink", id), content).Result;
      var response = responseMessage.Content.ReadAsStringAsync().Result;
      if (responseMessage.IsSuccessStatusCode)
      {
        var resLink = JsonConvert.DeserializeObject(response);
        result = resLink.link.webUrl;
      }
    }
    return result;
  }
}

・Create MSGraphLink Type

Create the ‘MSGraphLink’ class to accept the response of Microsoft Graph API. Then go to the ‘Index’ action of the ‘Home’ controller, set the breakpoint after calling the ‘GetLink’ method of the ‘AccessGraph’ class.

public class MSGraphLink
{
  public string id { get; set; }
  public List roles { get; set; }
  public LinkType link { get; set; }
}
public class LinkType
{
  public string type { get; set; }
  public string scope { get; set; }
  public string webUrl { get; set; }
  public ApplicationType application { get; set; }
}
public class ApplicationType
{
  public string id { get; set; }
  public string displayName { get; set; }
}

Execute the app with [F5] press, and confirm the method can acquire the web link.

>>The code sample of this article

About takao

I'm Microsoft MVP since June 2010.