我正在创建一个React日历,它使用客户端JavaScript SDK“ hello.js”和Microsoft Graph从“ Microsoft Outlook日历”中获取数据(对于设置,我也遵循了本指南:https://docs.microsoft.com/en-us/graph/auth-register-app-v2)
使用hello.login我的应用程序可以显示日历,没有任何问题...但是很遗憾,我必须在没有登录会话的情况下显示日历。
这是我的代码:
class CalendarView extends Component {
constructor(props) {
super(props);
hello.init({
microsoft: {
id: APP_ID,
oauth: {
version: 2,
auth: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',
},
scope_delim: ' ',
form: false,
scope: SCOPES,
},
});
const { startDate, endDate } = this.props;
this.state = {
// events: [],
startDataTime: startDate.toISOString(),
endDataTime: endDate.toISOString(),
token: hello('microsoft').getAuthResponse().access_token,
};
}
在另一个组件中,我管理Microsoft Graph查询:
class EventsList extends Component {
constructor() {
super();
this.state = {
events: [],
};
}
componentWillReceiveProps(nextProps) {
const { startDate, endDate, token } = nextProps;
// to know what is the Bearer toke
// -> https://stackoverflow.com/questions/25838183/what-is-the-oauth-2-0-bearer-token-exactly
axios.get(
`https://graph.microsoft.com/v1.0/me/calendarview?startdatetime=${startDate}&enddatetime=${endDate}&orderby=start/dateTime`,
{ headers: { Authorization: `Bearer ${token}` } },
).then(response => this.setState({ events: response.data.value }))
.catch((error) => {
console.log(error.response);
});
}
render() {
const { events } = this.state;
if (events !== null) return events.map(event => <EventList key={event.id} event={event} />);
return null;
}
}
奇怪的是,如果我创建console.log(token),应用程序会向我显示令牌,但是同时,我会收到“ GET ... 401(未经授权)”错误
console log token and error message
那是我的应用程序专有权
也许是Hello.js调用的问题? 我正在用Jest测试我的应用程序,但出现此错误,它可以链接到我的问题吗?
console.error node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/virtual-console.js:29
Error: Uncaught [TypeError: hello is not a function]
我该如何解决?
答案 0 :(得分:1)
我找到了解决方案!
我不得不打2次axios呼叫:
我必须在https://portal.azure.com/#home处注册我的应用,以便获得客户ID和机密。
我需要使用以下主体参数将POST消息发送到Azure Active Directory身份验证终结点后:
因此,我使用以下axios POST请求创建了一个组件:
componentDidMount() {
axios.post(`https://cors-anywhere.herokuapp.com/https://login.microsoftonline.com/${AZURE_ACTIVE_DIRECTORY_TENANT_NAME}/oauth2/token`,
`grant_type=${GRANT_TYPE}&client_id=${APP_ID}&client_secret=${SECRET}&resource=${RESOURCE}`).then(res => this.setAccessToken(res.data.access_token))
.catch((error) => {
console.error(error.response);
});
}
setAccessToken(token) {
if (typeof token === 'string') this.setState({ accessToken: token });
}
注意 resource 值需要稍作更改才能起作用: https%3A%2F%2Fgraph.microsoft.com%2F
我必须将字符串'https://cors-anywhere.herokuapp.com'放在micorsoftonline URL之前,因为否则应用程序会生成
“被CORS策略阻止:请求的资源上没有'Access-Control-Allow-Origin'标头。” (我不知道为什么,我仍在研究它,因为将这个字符串放在前面并不是最佳解决方案。)
在EventList组件中,我不再需要hellojs,所以我只使用生成的令牌来访问。我只需要更改一下Microsoft图形查询:
componentDidMount() {
const { accessToken } = this.props;
const { startDate, endDate } = this.state;
this.getEvents(startDate, endDate, accessToken);
}
getEvents(startDate, endDate, accessToken) {
const startDateString = startDate.toISOString();
const endDateString = endDate.toISOString();
axios.get(
`https://graph.microsoft.com/v1.0/users/${USER_PUBLIC_ID}/calendarview?startdatetime=${startDateString}&enddatetime=${endDateString}&orderby=start/dateTime`,
{
headers: {
Authorization: `Bearer ${accessToken}`,
},
},
).then(response => this.setEvents(response.data.value))
.catch((error) => {
console.error(error.response);
});
}
setEvents(events) {
const validEvent = event => typeof event.subject === 'string';
this.setState({ events: events.filter(validEvent) });
}
我希望我的解决方案也可以对其他用户有用