正在尝试使用Javascript获取Outlook日历事件,但收到401未经授权的错误?

正在尝试使用Javascript获取Outlook日历事件,但收到401未经授权的错误?,javascript,outlook,azure-active-directory,fetch,Javascript,Outlook,Azure Active Directory,Fetch,因此,我有一个带有纯JS/jQuery(因此没有角度)的自定义.aspx页面,可以上传到Sharepoint Online,并可以作为Web部件或iFrame添加到Sharepoint Online中的站点。我想显示Outlook日历事件,我还使用FullCalendar.io作为显示部分 这还包括ADAL(Azure AD)安全性,因为Outlook API需要它 因此,首先我使用Azure AD进行身份验证,获取获取的令牌,然后将该令牌传递给在页面上构建FullCalendar.io日历的函

因此,我有一个带有纯JS/jQuery(因此没有角度)的自定义.aspx页面,可以上传到Sharepoint Online,并可以作为Web部件或iFrame添加到Sharepoint Online中的站点。我想显示Outlook日历事件,我还使用FullCalendar.io作为显示部分

这还包括ADAL(Azure AD)安全性,因为Outlook API需要它

因此,首先我使用Azure AD进行身份验证,获取获取的令牌,然后将该令牌传递给在页面上构建FullCalendar.io日历的函数。这将尝试获取Outlook日历事件,并在完整日历上很好地显示它们

以下是我遵循的示例:


我还将链接1中的权限添加到Azure门户中我的Azure广告注册应用程序中

这是我的密码:

<script>

  var $this = this;

  $(document).ready(function() {
    window.config = {
          tenantId: '{tenant}',
          clientId: '{clientId}',
          popUp: true,
          redirectUri: '{redirectURI}',
          endpoints: {
            "https://outlook.office.com/api/v2.0/me/events":"https://outlook.office.com/",
          }
    };

    var authenticationContext = new AuthenticationContext(config);
    authenticationContext.handleWindowCallback();

    if (authenticationContext.getCachedUser()) {
      authenticationContext.acquireToken(config.clientId, function (errorDesc, token, error) {
        if (error) { //acquire token failure
          if (config.popUp) {
              // If using popup flows
              authenticationContext.acquireTokenPopup(config.clientId, null, null,  function (errorDesc, token, error) {});
          }
          else {
          // In this case the callback passed in the Authentication request constructor will be called.
              authenticationContext.acquireTokenRedirect(config.clientId, null, null);
          }
        }
        else {
          //acquired token successfully
          $this.DisplayEvents(token);
        }
      });
    }
    else {
        // Initiate login
        authenticationContext.login();
    }
  });

  function DisplayEvents(adalToken) {
    $('#calendar').fullCalendar({
      header: {
        left: 'prev,next today',
        center: 'title',
        right: 'month,agendaWeek,agendaDay,listWeek'
      },
      navLinks: true, // can click day/week names to navigate views
      editable: true,
      eventLimit: true, // allow "more" link when too many events
      events: function(start, end, timezone, callback) {
        var headers = new Headers();
        var bearerToken = "Bearer " + adalToken;
        headers.append('Authorization', bearerToken);
        var options = {
          method: 'GET',
          headers: headers,
          mode: 'no-cors'
        };
        var outlookEndpoint = 'https://outlook.office.com/api/v2.0/me/events?$select=Subject,Organizer,Start,End';

        fetch(outlookEndpoint, options)
          .then(function (response) {
            console.log(response);
          });
      }
    });
  }

</script>  

var$this=这个;
$(文档).ready(函数(){
window.config={
租户ID:“{tenant}”,
clientId:“{clientId}”,
是的,
重定向URI:“{redirectUri}”,
端点:{
"https://outlook.office.com/api/v2.0/me/events":"https://outlook.office.com/",
}
};
var authenticationContext=新的authenticationContext(配置);
authenticationContext.HandleIndowCallback();
if(authenticationContext.getCachedUser()){
authenticationContext.acquireToken(config.clientId,函数(errorDesc,token,error){
if(error){//获取令牌失败
if(config.popUp){
//如果使用弹出流
acquireTokenPopup(config.clientId,null,null,function(errorDesc,token,error){});
}
否则{
//在这种情况下,将调用在身份验证请求构造函数中传递的回调。
authenticationContext.acquireTokenRedirect(config.clientId,null,null);
}
}
否则{
//已成功获取令牌
$this.DisplayEvents(令牌);
}
});
}
否则{
//启动登录
authenticationContext.login();
}
});
函数DisplayEvents(adalToken){
$(“#日历”).fullCalendar({
标题:{
左:“上一个,下一个今天”,
中心:'标题',
右图:“月、agendaWeek、agendaDay、listWeek”
},
navLinks:true,//可以单击日/周名称来导航视图
是的,
eventLimit:true,//当事件太多时允许“更多”链接
事件:函数(开始、结束、时区、回调){
var headers=新的headers();
var bearerToken=“Bearer”+adalToken;
headers.append('Authorization',bearerToken);
变量选项={
方法:“GET”,
标题:标题,
模式:“无cors”
};
var-outlookEndpointhttps://outlook.office.com/api/v2.0/me/events?$select=主题、组织者、开始、结束';
获取(outlookEndpoint,选项)
.然后(功能(响应){
控制台日志(响应);
});
}
});
}
如您所见,令牌被传递给fullCalendar()函数的events函数中的“fetch”调用。我尝试过做一个普通的ajax'GET'调用,但是我遇到了CORS错误。当我在选项中省略“模式:'无cors'时也是如此。由于我在上面链接的github示例,正在进行获取

现在我收到一个401未经授权的错误和响应,其中包含状态:0和主体:null等


其他任何人都有此问题,或者可以看到我做错了什么导致身份验证失败?

您需要修改acquireToken方法,如下所示。只需将“config.clientId”替换为“”

此外,您可以使用Rest客户端或postman查找401错误详细信息。例如,这是Rest客户端中的响应。

Mhm确实。。。我收到了一些新的信息,但最终401仍然存在。我可以更详细地看到你给我的错误,谢谢!然而,这意味着什么?因为我已尝试向Exchange API连接中的所有内容添加权限,但仍然不起作用。我应该改用Microsoft Graph吗?添加权限后,您是否单击了“授予权限”按钮?您可以解码您的令牌以查看您是否有足够的权限。是的,我单击了“授予权限”,它将(管理员?)权限添加到所有人&我相信租户中的每个人。但我在测试后把它关掉了。解码你的令牌,你的意思是这样的?那我下一步就试试这个,随时通知你!我已经解码了我的访问令牌,可以看到以下内容(我假设我的权限是什么?):“scp”:“Calendars.Read Calendars.Read.All Calendars.Read.Shared Calendars.ReadWrite.All Calendars.ReadWrite.Shared Contacts.Read Contacts.Read.All Contacts.Read.Shared等…”。。。看来我有很多权限?Scp代表委托权限,“角色”似乎代表应用程序权限()。我在某个地方出错了吗?这个问题有更新吗?
if (authContext.getCachedUser()) {
        authContext.acquireToken("https://outlook.office.com/", function (error, token) {
            if (error) { //acquire token failure
                if (config.popUp) {
                    // If using popup flows
                    authContext.acquireTokenPopup("https://outlook.office.com/", null, null, function (errorDesc, token, error) { });
                }
                else {
                    // In this case the callback passed in the Authentication request constructor will be called.
                    authContext.acquireTokenRedirect("https://outlook.office.com/", null, null);
                }
            }
            else {
                //acquired token successfully
                // alert('token success');
                DisplayEvents(token);
            }
        });
    }
    else {
        // Initiate login
        authContext.login();
    }