React调用Microsoft Graph API获取OneDrive文件时遇401未授权错误
问题:调用Microsoft Graph API的
/me/drive/root/children接口返回401未授权 我正在开发一个React应用,使用Microsoft Graph API从OneDrive获取文件。调用/me接口能成功获取账户信息:
{ "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity", "businessPhones": [], "displayName": [NAME], "givenName": null, "jobTitle": null, "mail": [EMAIL], "mobilePhone": null, "officeLocation": null, "preferredLanguage": null, "surname": null, "userPrincipalName": [USER_PRINCIPAL_NAME], "id": [ID] }
但调用/me/drive/root/children接口时出现401未授权错误:
HTTPMessageHandler.ts:29 GET https://graph.microsoft.com/v1.0/me/drive/root/children 401 (Unauthorized) (anonymous) @ HTTPMessageHandler.ts:29 (anonymous) @ tslib.es6.mjs:121 __awaiter @ tslib.es6.mjs:117 execute @ HTTPMessageHandler.ts:28 (anonymous) @ TelemetryHandler.ts:91 (anonymous) @ tslib.es6.mjs:121 __awaiter @ tslib.es6.mjs:117 execute @ TelemetryHandler.ts:66 (anonymous) @ RetryHandler.ts:173 (anonymous) @ tslib.es6.mjs:121 __awaiter @ tslib.es6.mjs:117 executeWithRetry @ RetryHandler.ts:172 (anonymous) @ RetryHandler.ts:196 (anonymous) @ tslib.es6.mjs:121 __awaiter @ tslib.es6.mjs:117 execute @ RetryHandler.ts:192 (anonymous) @ AuthenticationHandler.ts:88 fulfilled @ tslib.es6.mjs:118 Promise.then (async) step @ tslib.es6.mjs:120 (anonymous) @ tslib.es6.mjs:121 __awaiter @ tslib.es6.mjs:117 execute @ AuthenticationHandler.ts:63 (anonymous) @ HTTPClient.ts:88 (anonymous) @ tslib.es6.mjs:121 __awaiter @ tslib.es6.mjs:117 sendRequest @ HTTPClient.ts:81 (anonymous) @ GraphRequest.ts:372 (anonymous) @ tslib.es6.mjs:121 __awaiter @ tslib.es6.mjs:117 send @ GraphRequest.ts:366 (anonymous) @ GraphRequest.ts:635 (anonymous) @ tslib.es6.mjs:121 __awaiter @ tslib.es6.mjs:117 get @ GraphRequest.ts:630 getData @ initializeAuthProcess.js:26 initializeAuthProcess @ initializeAuthProcess.js:12 await in initializeAuthProcess (async) (anonymous) @ App.js:31 commitHookEffectListMount @ react-dom.development.js:23150 commitPassiveMountOnFiber @ react-dom.development.js:24926 commitPassiveMountEffects_complete @ react-dom.development.js:24891 commitPassiveMountEffects_begin @ react-dom.development.js:24878 commitPassiveMountEffects @ react-dom.development.js:24866 flushPassiveEffectsImpl @ react-dom.development.js:27039 flushPassiveEffects @ react-dom.development.js:26984 (anonymous) @ react-dom.development.js:26769 workLoop @ scheduler.development.js:266 flushWork @ scheduler.development.js:239 performWorkUntilDeadline @ scheduler.development.js:533 initializeAuthProcess.js:29 getData error Error: There has been an error authenticating the request. at GraphErrorHandler.constructErrorFromResponse (GraphErrorHandler.ts:77:1) at GraphErrorHandler.<anonymous> (GraphErrorHandler.ts:104:1) at Generator.next (<anonymous>) at tslib.es6.mjs:121:1 at new Promise (<anonymous>) at __awaiter (tslib.es6.mjs:117:1) at GraphErrorHandler.getError (GraphErrorHandler.ts:101:1) at GraphRequest.<anonymous> (GraphRequest.ts:391:1) at Generator.throw (<anonymous>) at rejected (tslib.es6.mjs:119:1)
我已在登录作用域中包含Files.ReadWrite.All等相关权限,初始化代码如下:
import { Client } from '@microsoft/microsoft-graph-client'; export const initializeAuthProcess = async (instance) => { try { await instance.initialize(); const authResponse = await instance.loginPopup({ redirectUri: 'http://localhost:3000', scopes: ["User.Read", "User.Read.All", "User.ReadBasic.All", "User.ReadWrite", "User.ReadWrite.All", "Files.Read", "Files.Read.All", "Files.Read.Selected", "Files.ReadWrite", "Files.ReadWrite.All", "Files.ReadWrite.AppFolder", "Files.ReadWrite.Selected"], prompt: "select_account" }); const accessToken = authResponse.accessToken; getData(accessToken) } catch (e) { console.error("initializeAuthProcess error", e); } }; async function getData(accessToken) { const client = Client.init({ authProvider: (done) => { done(null, accessToken); }, }); try { const data = await client.api('/me/drive/root/children').get(); console.log("data", data); } catch (error) { console.error("getData error", error); } }
App.js代码:
import { PublicClientApplication } from "@azure/msal-browser"; import { MsalProvider, useMsal } from "@azure/msal-react"; import { useEffect } from "react"; import { initializeAuthProcess } from "./functions/initializeAuthProcess"; const msalConfig = { auth: { clientId: [clientId], authority: [authority], redirectUri: 'http://localhost:3000' } }; const pca = new PublicClientApplication(msalConfig); function App() { return ( <MsalProvider instance={pca}> <OneDriveFiles /> </MsalProvider> ); } function OneDriveFiles() { const { accounts, instance } = useMsal(); useEffect(() => { if(instance){ initializeAuthProcess(instance); } }, [accounts, instance]); return null; } export default App;
我已在Azure Active Directory中为应用授予所有相关权限,且尝试了两个拥有活跃OneDrive的微软账户,但问题依然存在。
可能的原因及解决方法
1. 权限未完成管理员同意
Files.ReadWrite.All这类委托权限需要租户管理员的明确同意才能生效,普通用户登录时无法自动获取该权限。
- 登录Azure AD门户,进入应用注册→API权限页面,找到
Files.ReadWrite.All权限,点击授予管理员同意按钮,确认权限状态变为已授予。
2. Access Token未包含目标作用域
即使登录时请求了权限,实际返回的Token可能未包含所需作用域(比如用户拒绝了权限请求)。
- 用JWT解码工具解析Access Token,查看
scp字段,确认是否包含Files.Read或Files.ReadWrite.All; - 简化作用域列表,只保留必要权限(比如
User.Read和Files.Read.All),避免权限请求被部分拒绝。
3. 改用MSAL标准方式获取Token
直接使用loginPopup返回的Token可能存在受众(aud)不匹配的问题,推荐用acquireTokenSilent/acquireTokenPopup获取针对Graph API的Token:
// 修改initializeAuthProcess,传递instance而非token export const initializeAuthProcess = async (instance) => { try { await instance.initialize(); await instance.loginPopup({ redirectUri: 'http://localhost:3000', scopes: ["User.Read", "Files.Read.All"], prompt: "select_account" }); getData(instance); } catch (e) { console.error("initializeAuthProcess error", e); } }; // 修改getData函数,用MSAL获取Token async function getData(instance) { try { // 优先静默获取Token const tokenResponse = await instance.acquireTokenSilent({ scopes: ["Files.Read.All"], account: instance.getAllAccounts()[0] }); const client = Client.init({ authProvider: (done) => done(null, tokenResponse.accessToken), }); const data = await client.api('/me/drive/root/children').get(); console.log("data", data); } catch (error) { // 静默失败则弹出窗口获取 if (error.name === "InteractionRequiredAuthError") { const tokenResponse = await instance.acquireTokenPopup({ scopes: ["Files.Read.All"] }); // 重复请求逻辑 const client = Client.init({ authProvider: (done) => done(null, tokenResponse.accessToken), }); const data = await client.api('/me/drive/root/children').get(); console.log("data", data); } console.error("getData error", error); } }
4. 验证OneDrive账户状态
部分新创建的账户未首次登录OneDrive网页版时,Graph API可能无法访问其Drive资源。
- 让用户先登录
https://onedrive.live.com,确认能正常查看文件后再测试应用。
5. 检查应用注册权限配置
- 确保添加的是Microsoft Graph的权限,而非其他API;
- 删除冗余或错误的权限条目,避免权限冲突。
内容的提问来源于stack exchange,提问作者Vaibhav Verma
相关产品推荐
相关产品推荐

