使用无人参与的用户/密码创建Microsoft Graph GraphServiceClient

时间:2018-01-15 17:37:09

标签: c# microsoft-graph

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

修改

在关注@DanSilver关于没有用户的geting访问的链接之后,我尝试了该链接中建议的示例(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);                            
    }                
));

2 个答案:

答案 0 :(得分:3)

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

要重申这些令牌不适合特定用户,请考虑向https://graph.microsoft.com/v1.0/me'发出GET请求。这将返回错误,因为访问令牌对于特定用户来说并不是" me"什么都没有意义。请求应与完整的用户ID一起发送,例如graph.microsoft.com/users/someuser@contosos.com"。

有关此内容的更多信息,请访问Get access without a user文档页面。

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

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

答案 1 :(得分:0)

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

这是一个简单的用例:我有一个每晚执行的过程,需要使用传统的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个DELEGATED权限(不是应用程序权限):

Microsoft Graph
 1. Mail.ReadWrite.Shared
 2. Mail.Send.Shared
 3. User.Read
 4.电子邮件
 5. openid

由于实际上在我们组织中阻止了用户同意,因此另一位权限管理员必须查看我的应用程序定义,然后对这些权限进行管理员级别的授予,但是一旦获得批准,一切都会如我所愿地工作起来:一个服务帐户访问单个共享邮箱,并在Office 365中管理该访问的实际安全性,而不是Azure AD。