我最终尝试使用Graph API将数据添加到OneDrive中的Excel文件中,并在我的PC而非网站上运行本地node.js应用程序,而我的目标是在Windows中简单地调用“ node index.js”控制台来执行此操作,而无需授权我的登录名(也许这是不可能的?)
我从这些端点开始首先获取简单数据,但无法使它们工作(基本URL https://graph.microsoft.com):
/v1.0/me/
/v1.0/users/{My-UserID}/
/v1.0/me/drive/root:/TestFile.xlsx:/workbook/worksheets
/v1.0/users/{My-UserID}/drive/root:/TestFile.xlsx:/workbook/worksheets
/v1.0/me/
和/v1.0/users/{My-UserID}/
返回'Resource \'{My-UserID} \'不存在,或者其查询的参考属性对象之一不存在。'
/v1.0/me/drive/root:/TestFile.xlsx:/workbook/worksheets
和/v1.0/users/{My-UserID}/drive/root:/TestFile.xlsx:/workbook/worksheets
返回“ Tenant没有SPO许可证。”
我如何获得令牌
我使用adal-node库(https://www.npmjs.com/package/adal-node),并使用“通过客户端凭据进行服务器到服务器”流程获得了访问令牌。
我如何调用图形API
我正在使用axios在没有Microsoft Graph SDK的情况下手动调用API。
我如何在Azure门户中注册我的应用
a)选择一个应用名称。
b)在“支持的帐户类型”中选择了“仅此组织目录中的帐户(仅默认目录-单租户)”。
c)左侧“重定向URI(可选)”为空
a)将“说明”留空。
b)在“过期”下选择“从不”。
c)点击“添加”。
我还尝试添加委派权限,以检查“ Directory.Read.All”和“ Group.Read.All”的所有可用权限和应用程序权限。
我尝试过的事情
我尝试使用Graph Explorer(https://developer.microsoft.com/en-us/graph/graph-explorer),可以看到两者 /v1.0/me/和/v1.0/me/drive/root:/TestFile.xlsx:/workbook/worksheets返回正确的数据。
我还尝试用/ users / {My-UserID} /替换/ me /,并且Graph Explorer返回相同的正确数据,但是我的node.js应用仍然返回相同的错误。
我用JWT解码器检查了检索到的令牌,看起来像
oid
正确等于{My-UserID}。
roles
包括“ Files.Read.All”和“ User.Read.All”,这与我在Azure门户中的应用程序注册中设置的一样。
appid
正确等于{My-ApplicationID}。
tid
正确等于{My-TenantID}。
aud
等于'https://graph.microsoft.com'
我还尝试了通过向标头中的https://login.microsoftonline.com/{My-TenantID}/oauth2/v2.0/token调用POST来手动获取令牌的方法:
'Content-Type': 'application/x-www-form-urlencoded'
和数据:
client_id=${My-ClientID}&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&client_secret={My-ClientSecret}&grant_type=client_credentials
,并显示以下错误:“ AADSTS7000215:提供了无效的客户端密码”。 <-编辑:我发现了为什么出现此错误。我必须使用%{ascii-in-hex}来转义特殊字符,例如:/ +。
其他注意事项
我有一个Office 365家庭订阅和一个随用随付Azure帐户,使用与OneDrive相同的电子邮件地址,该电子邮件具有要向其添加数据的Excel文件。
编辑:我发现,如果您使用Graph Explorer并调用/v1.0/users/{any-number}
,您将获得自己的个人资料。这意味着{My-UserID}
可能一直都不是我正确的用户ID。
const Tenant = {My-TenantID};
const ClientID = {My-ApplicationID};
const ClientSecret = {My-ClientSecret};
function GetAccessToken()
{
const AuthenticationContext = require('adal-node').AuthenticationContext;
const authorityUrl = `https://login.microsoftonline.com/${Tenant}`;
const applicationId = ClientID;
const clientSecret = ClientSecret;
const resource = 'https://graph.microsoft.com';
const context = new AuthenticationContext(authorityUrl);
return new Promise((resolve, reject) =>
{
context.acquireTokenWithClientCredentials(resource, applicationId, clientSecret, (error, tokenResponse) =>
{
if (error)
{
console.log('Get token error:');
console.dir(error.stack, {depth: null});
reject(error);
}
else
{
console.log('Get token success:');
console.dir(tokenResponse, {depth: null});
resolve(tokenResponse.accessToken);
}
});
});
}
async function GetData()
{
const axios = require('axios');
const AccessToken = await GetAccessToken();
axios(
{
method: 'GET',
url: 'https://graph.microsoft.com/v1.0/me/', //I have also tried /v1.0/users/{My-UserID}/
headers:
{
'Authorization': `Bearer ${AccessToken}`,
}
})
.then(result =>
{
console.log('Get data success:');
console.dir(result.data, {depth: null});
})
.catch(error =>
{
console.log('Get data failed:');
if (error.response.data != undefined)
{
console.dir(error.response.data, {depth: null});
}
else
{
console.dir(error, {depth: null});
}
})
}
GetData();
更新1
我想我已经弄清楚了/v1.0/me
或/v1.0/users/{My-UserID}
都不起作用的原因。如果我们在没有用户的情况下进行身份验证(我在此处选择的流程),则该应用程序只能访问的用户是Azure Active Directory(AAD)中的用户。现在,如果您使用您的hotmail帐户登录到Azure并转到“ Azure Active Directory”,然后单击“用户”,您将在那里看到您的帐户,但是我认为该帐户实际上是与“普通” Microsoft帐户(“普通”)不同的帐户。 'Microsoft帐户是您通过hotmail注册的帐户)。是的,微软似乎创建了一个单独的“ AAD”身份,该用户与您的“普通”身份用户不同。
{My-UserID}
实际上是“公共”身份的用户ID。因此,这意味着,如果我调用/v1.0/users/{My-UserID}
,则我的应用程序将无法识别该用户ID,因为该用户ID不属于AAD。因此,我尝试的是从AAD中的用户复制“对象ID”,然后使用它:/v1.0/users/{AAD-ObjectID}
然后中提琴,我看到了我的个人资料。
编辑:{My-UserID}
实际上不是我的“公共”身份的用户ID。这是我还不知道的其他ID。
然后我尝试:
并可以确认/v1.0/me
和v1.0/users/{My-UserID}
确实有效。 编辑:无论您指定哪个ID,Graph API实际上都会返回我的个人资料,因此您可以指定v1.0/users/123
,它仍然会返回您的个人资料!
因此,我想,嗯,我不是使用Azure门户授予管理员同意,而是使用https://login.microsoftonline.com/common/adminconsent端点授予管理员同意。这样做,然后从/common/oauth2/v2.0/token
获取访问令牌
/v1.0/me
返回“当前认证的上下文对此请求无效。” /v1.0/users/{My-UserID}
返回“无法建立调用应用程序的身份”错误。/v1.0/users/{AAD-ObjectID}
返回“无法建立调用应用程序的身份”错误。如果我从/{My-TenantID}/oauth2/v2.0/token
获取访问令牌,则
/v1.0/me
和/v1.0/users/{My-UserID}
返回原始的“ Request_ResourceNotFound”错误。/v1.0/users/{AAD-ObjectID}
正确返回了我的个人资料。然后我尝试了/v1.0/users/{AAD-ObjectID}/drive/root:/TestFile.xlsx:/workbook/worksheets
,但仍然收到“ Tenant没有SPO许可证”的信息。我怀疑这是因为我的AAD身份没有操纵OneDrive项目所需的许可。
一种解决方案,它不使用我发现有效的“代表用户获取访问权限”身份验证流程而向Excel添加数据,而是使用Logic App。因此,在Logic App中,我设置了一个HTTP请求端点,该端点在被触发时会将数据添加到Excel,并让我的Node.js应用程序调用此端点,而不是直接调用Graph API。
总结
我认为这可能是Microsoft必须最终解决的问题-AAD身份不应是一个单独的身份,而应与我的“公共”身份相同,以便我可以使用{{1 }},并使用/v1.0/users/{My-UserID}
处理我的OneDrive文件。
更新2
我找到了一种无需使用Logic App即可直接调用Graph API的方法!
对于那些关注我的问题的人,有两种方法可以调用Graph API:
我发现的关键点是“代表用户调用”,就像说,您(用户)想要通过您的应用程序使用Graph API,这实际上是我想要的,因为我想调用Graph API来编辑我的Excel文件。 “无需用户调用”就像是说,应用程序本身正在调用Graph API-不是使用该应用程序来调用Graph API的用户,因此,除非该用户位于活动目录中,否则它将无法访问用户数据。重要的是要注意(根据我先前的回答),您在AAD中看到的与您同名的用户实际上不是'you',而是您的'AAD'版本。因此,即使您在AAD中看到您的名字,“没有用户拨打电话”也将无法访问您的OneDrive项目。为此,您需要“代表用户致电”。
现在,如果我们需要执行“代表用户呼叫”,我想我每次都要访问“获取授权码->获取访问令牌”来访问我的OneDrive文件,但是我发现还可以刷新令牌,以便可以继续访问OneDrive文件而无需获取新的授权码。此步骤最重要的是,在获取授权码和令牌时,请确保在范围参数中包含/v1.0/users/{My-UserID}/drive
,否则,当您要求令牌并且您返回offline_access
时,将不会返回refreshToken
将无法刷新令牌。您还需要在应用注册中添加offline_access
委派权限。
因此,我可以让我的节点应用程序保存refreshToken
并在每次运行时刷新令牌,并且中提琴,我可以随时编辑Excel文件!
答案 0 :(得分:0)
您不能将/me
与客户端凭据一起使用。由于您不对用户进行身份验证,因此Graph无法确定应映射到哪个用户“我”。
在使用仅应用程序令牌(即客户端凭据)时,您需要指定所需地址的用户:
/v1.0/users/{id or userPrincipalName}
/v1.0/{id or userPrincipalName}/drive/root:/TestFile.xlsx:/workbook/worksheets