9

我正在使用 MSAL,并且有一个用户收到以下错误:

{  
   "error":{  
      "code":"ResourceNotFound",
      "message":"Resource could not be discovered.",
      "innerError":{  
         "request-id":"99b44a33-e5cd-4b69-9730-32d72e1f4ebf",
         "date":"2016-12-11T03:51:37"
      }
   }
}

该代码是默认的 MSAL 演示代码:

    public async Task<ActionResult> ReadMail()
    {            
        try
        {
            string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
            ConfidentialClientApplication cca = new ConfidentialClientApplication(clientId, null,
                new ClientCredential(appKey), new MSALSessionCache(signedInUserID, this.HttpContext));                
            string[] scopes = { "Mail.Read" };
            AuthenticationResult result = await cca.AcquireTokenSilentAsync(scopes);

            HttpClient hc = new HttpClient();
            hc.DefaultRequestHeaders.Authorization =
                new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", result.Token);                
            HttpResponseMessage hrm = await hc.GetAsync("https://graph.microsoft.com/v1.0/me/messages");
            string rez = await hrm.Content.ReadAsStringAsync();
            ViewBag.Message = rez;

            return View();
        }
        catch (MsalSilentTokenAcquisitionException)
        {
            ViewBag.Relogin = "true";
            return View();
        }
        catch (Exception eee)
        {
            ViewBag.Error = "An error has occurred. Details: " + eee.Message;
            return View();
        }
    }

原来集成是这样的:

  1. 这是一个混合交换系统
  2. 某些邮箱位于 Office 365 上。
  3. 一些邮箱位于本地。
  4. 其他邮箱位于第 3 方邮件系统(Intermedia)上(目录通过自定义脚本同步到 AD Connect)

问题

我应该如何针对上述情况进行防御性编码?(或类似的混合情况)?

4

1 回答 1

1

老问题,但似乎其他人也遇到了这个问题。

这并不是真正的 MSAL 问题,因为令牌本身不是这里的问题。异常源于https://graph.microsoft.com/v1.0/me/messages用户没有可访问邮箱时的调用。

user您通常可以通过查看该用户的provisionedPlans集合来确定哪些资源已分配给 a :

 https://graph.microsoft.com/v1.0/me?$select=provisionedPlans

这将返回已为用户提供的集合资源。例如,此用户未配置 Exchange:

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users(provisionedPlans)/$entity",
    "provisionedPlans": [
        {
            "capabilityStatus": "Enabled",
            "provisioningStatus": "Success",
            "service": "SharePoint"
        },
        {
            "capabilityStatus": "Enabled",
            "provisioningStatus": "Success",
            "service": "SharePoint"
        }
    ]
}

将此与已配置 Excange 的此用户进行比较:

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users(provisionedPlans)/$entity",
    "provisionedPlans": [
        {
            "capabilityStatus": "Enabled",
            "provisioningStatus": "Success",
            "service": "MicrosoftOffice"
        },
        {
            "capabilityStatus": "Enabled",
            "provisioningStatus": "Success",
            "service": "exchange"
        },
        {
            "capabilityStatus": "Enabled",
            "provisioningStatus": "Success",
            "service": "MicrosoftCommunicationsOnline"
        },
        {
            "capabilityStatus": "Enabled",
            "provisioningStatus": "Success",
            "service": "SharePoint"
        },
        {
            "capabilityStatus": "Enabled",
            "provisioningStatus": "Success",
            "service": "SharePoint"
        }
    ]
}

一个类似的可能也有用的属性是assignedPlans. 这将返回已分配给 的资源,user并且对于确定是否还没有进行预配或对于未正式“预配”的资源(例如 Microsoft Teams)很有用。

也就是说,您应该始终针对用户对您请求的资源没有或缺乏权限的可能性进行防御性编码。在几种情况下,资源可能由于中断或用户权限而无法访问,而处理这些情况的唯一可靠方法是通过可靠的异常处理来支持。

于 2017-12-06T17:49:36.877 回答