繁体   English   中英

使用无人值守的用户/密码创建 Microsoft Graph GraphServiceClient

[英]Create Microsoft Graph GraphServiceClient with user/password unattended

我正在创建一个使用 Microsoft Graph API 连接到 Microsoft Graph 的控制台应用程序(如https://github.com/microsoftgraph/console-csharp-connect-sample所示)。 一切正常,但我想知道是否有一种方法可以对用户进行身份验证(当我已经知道他们的用户/密码时),而无需他们在“登录到您的帐户”窗口中手动输入他们的凭据桌面。 这个想法基本上是在无人看管的情况下运行应用程序,因此用户无需在应用程序启动时输入他们的凭据。 我找不到有关该主题的任何相关信息。 这甚至可能吗?

编辑

按照@DanSilver 发布的关于无需用户即可访问的链接后,我尝试了该链接中建议的示例( https://github.com/Azure-Samples/active-directory-dotnet-daemon-v2 )。 虽然这是一个强制用户进行身份验证的 MVC 应用程序(正是我想要避免的),但我已经设法在我的控制台应用程序中使用了该示例中的部分身份验证代码。 通过对https://login.microsoftonline.com/myTenantId/adminconsent的请求手动授予应用程序授权后,我可以在我的控制台应用程序中创建一个 GraphServiceClient,该应用程序无需用户交互即可连接到 Graph。 所以我将答案标记为有效。 以防万一有人处于相同的情况,GraphServiceclient 被创建为:

GraphServiceClient graphServiceClientApplication = new GraphServiceClient("https://graph.microsoft.com/v1.0", new DelegateAuthenticationProvider(
    async (requestMessage) =>
    {
        string clientId = "yourClientApplicationId";
        string authorityFormat = "https://login.microsoftonline.com/{0}/v2.0";
        string tenantId = "yourTenantId";
        string msGraphScope = "https://graph.microsoft.com/.default";
        string redirectUri = "msalXXXXXX://auth"; // Custom Redirect URI asigned in the Application Registration Portal in the native Application Platform
        string clientSecret = "passwordGenerated"; 
        ConfidentialClientApplication daemonClient = new ConfidentialClientApplication(clientId, String.Format(authorityFormat, tenantId), redirectUri, new ClientCredential(clientSecret), null, new TokenCache());
        AuthenticationResult authResult = await daemonClient.AcquireTokenForClientAsync(new string[] { msGraphScope });
        string token = authResult.AccessToken;
        requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", token);                            
    }                
));

一种想法是使用“仅应用”授权流程。 这个想法是让长时间运行的应用程序无需用户身份验证即可访问 Microsoft Graph。 主要区别在于,它不是授予特定用户访问权限的访问令牌,而是授予您的应用程序访问您事先同意的资源的权限。 将没有用户登录对话框,您可以通过编程方式获取访问令牌以调用 Graph API。

为了重申这些令牌不是针对特定用户的,请考虑向“ https://graph.microsoft.com/v1.0/me ”发出 GET 请求。 这将返回一个错误,因为访问令牌不是针对特定用户的,“我”没有任何意义。 请求应使用完整的用户 ID“如 graph.microsoft.com/users/someuser@contosos.com”发送。

可以在没有用户文档的情况下获取访问权限页面上找到有关这方面的更多信息。

另一个想法是让用户在他们第一次使用您的应用程序时进行身份验证,然后存储刷新令牌。 这些令牌的寿命更长(几个月 IIRC),然后您不需要在每次应用程序运行时提示用户同意。 刷新令牌可以交换为有效期为 60 分钟的访问令牌,这些令牌可用于代表用户调用图谱 API。

有关刷新令牌的更多信息: https : //developer.microsoft.com/en-us/graph/docs/concepts/auth_v2_user#5-use-the-refresh-token-to-get-a-new-access-token

我确实想回来分享一下,因为我昨天遇到了这个问题,并且为我的应用程序授予读/写邮箱访问权限的想法......到整个组织中每个人的邮箱......满足我的需求。 (这正是当您开始谈论授予应用程序级别权限而不是委派权限给您注册的应用程序时发生的情况)。

这是一个简单的用例:我有一个夜间流程,需要使用传统的 AD 服务帐户从共享邮箱自动发送电子邮件。

值得庆幸的是...即使他们正在努力消除密码(lol)... Microsoft 的某个人仍然认识到我的用例,并且 Azure AD 中缺乏一对一的替代方案。 我们仍然可以依靠一种扩展方法来完成工作:

private AuthenticationContext authContext = null;
authContext = new AuthenticationContext("https://login.microsoftonline.com/ourmail.onmicrosoft.com", 
                new TokenCache());
result = authContext.AcquireTokenAsync("https://graph.microsoft.com/", 
                "12345678-1234-1234-1234-1234567890", 
                new UserPasswordCredential( 
                    Environment.GetEnvironmentVariable("UID", EnvironmentVariableTarget.User), 
                    Environment.GetEnvironmentVariable("UPD", EnvironmentVariableTarget.User) 
                )).Result;    

您可以用您的用户名 (UID) 和密码 (UPD) 替换这些 GetEnvironmentVariable 调用。 我只是将它们塞入服务帐户的环境变量中,因此我不必在源代码管理中检查任何内容。

AcquireTokenAsync 是 Microsoft.IdentityModel.Clients.ActiveDirectory 命名空间中提供的扩展方法。 从那里,启动 GraphClient 是一项简单的业务。

        string sToken = result.AccessToken;
        Microsoft.Graph.GraphServiceClient oGraphClient = new GraphServiceClient(
                    new DelegateAuthenticationProvider((requestMessage) => {
                        requestMessage
                            .Headers
                            .Authorization = new AuthenticationHeaderValue("bearer", sToken);
            return Task.FromResult(0);
        }));

最后一点魔法是将这些权限添加到我在 Azure AD 中创建的应用程序注册(该 GUID 的来源)。 该应用程序已被定义为公共客户端(在身份验证选项卡的底部有一个单选按钮)。 我添加了以下 5 个委托权限(不是应用程序权限):

微软图形
1. 邮件.读写.共享
2. 邮件.发送.共享
3. 用户读取
4. 电子邮件
5.openid

由于用户同意在我们的组织中实际上被阻止,另一个权限管理员必须审查我的应用程序定义,然后对这些权限进行管理员级别的授予,但是一旦他这样做了,一切都像我需要的那样工作:服务帐户的访问权限有限到单个共享邮箱,该访问的实际安全性在 Office 365 而不是 Azure AD 中管理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM