Bing Ads OAuth Automation仅使用.NET?

Sno*_*owy 5 c# oauth bing-api oauth-2.0

如何登录Microsoft Live(使用.NET WebClient?)并自动执行OAuth流程以获取令牌以进行Bing Ads API调用?

我的问题类似于如何从live.com获取OAuth request_token?.但是,我正在构建(C#,. NET 4.5.2)无头Windows服务,使用Bing Ads超级管理员帐户的上下文链接到多个其他Bing Ads帐户.我们的想法是验证,获取auth位,然后在凌晨3:00使用位进行调用.一些帐户"竞争",例如组A不应该看到来自组B的数据,因此让应用程序获取每个人的数据并过滤它并在一夜之间分发它可以解决许多业务问题.

我担心如果Live遇到问题,或者我们的应用程序由于任何原因而长时间停机,我们将不得不手动重新进行身份验证以重新获取数据.现在,凭证的维护和管理是额外的开销(这是针对企业环境的),必须采用内部网站点/页面的形式,以便初级/不熟练的人员在需要时进行工作(不要忘记测试和文档).相比之下,Google提供了一个选项,可以为需要以完全自动化方式工作的组使用密钥对.看来Twitter的OAuth2实现可以在没有GUI登录的情况下实现自动化.似乎其他Bing服务(例如翻译)也可以使用WebClient自动化.

我已经拥有Microsoft帐户名和密码,并且在Bing Ads应用程序GUI中设置了回拨URL"local-mydomain.com"(并且local-mydomain.com有一个HOSTS条目).

Microsoft 示例似乎可以工作,但它会自动执行MS Web Browser Control,期望用户在GUI中输入凭据,然后给出令牌.向用户提供超级管理员帐户不是一种选择.期望用户在凌晨3点起床以进行身份​​验证以上传/下载数据不是一种选择.期望用户获得对服务器场中的服务器的桌面访问以"运行某些东西"不是一种选择.

所有OAuth的想法都受到赞赏

谢谢.

这是启动代码:

 partial class OAuthForm : Form
    {
        private static OAuthForm _form;
        private static WebBrowser _browser;

        private static string _code;
        private static string _error;

        // When you register your application, the Client ID is provisioned.

        private const string ClientId = "000redacted000";

        // Request-related URIs that you use to get an authorization code, 
        // access token, and refresh token.

        private const string AuthorizeUri = "https://login.live.com/oauth20_authorize.srf"; 
        private const string TokenUri = "https://login.live.com/oauth20_token.srf"; 
        private const string DesktopUri = "https://login.live.com/oauth20_desktop.srf"; 
        private const string RedirectPath = "/oauth20_desktop.srf";
        private const string ConsentUriFormatter = "{0}?client_id={1}&scope=bingads.manage&response_type=code&redirect_uri={2}";
        private const string AccessUriFormatter = "{0}?client_id={1}&code={2}&grant_type=authorization_code&redirect_uri={3}";
        private const string RefreshUriFormatter = "{0}?client_id={1}&grant_type=refresh_token&redirect_uri={2}&refresh_token={3}";

        // Constructor

        public OAuthForm(string uri)
        {
            InitializeForm(uri);
        }

        [STAThread]
        static void Main()
        {
            // Create the URI to get user consent. Returns the authorization
            // code that is used to get an access token and refresh token.

            var uri = string.Format(ConsentUriFormatter, AuthorizeUri, ClientId, DesktopUri);

            _form = new OAuthForm(uri);

            // The value for "uri" is 
            // https://login.live.com/oauth20_authorize.srf?client_id=000redacted000&scope=bingads.manage&response_type=code&redirect_uri=https://login.live.com/oauth20_desktop.srf



            _form.FormClosing += form_FormClosing;
            _form.Size = new Size(420, 580);

            Application.EnableVisualStyles();

            // Launch the form and make an initial request for user consent.
            // For example POST /oauth20_authorize.srf?
            //                 client_id=<ClientId>
            //                 &scope=bingads.manage
            //                 &response_type=code
            //                 &redirect_uri=https://login.live.com/oauth20_desktop.srf HTTP/1.1

            Application.Run(_form);  // <!---------- Problem is here. 
                                     //  I do not want a web browser window to show,
                                     // I need to automate the part of the process where
                                     // a user enters their name/password and are
                                     // redirected.

            // While the application is running, browser_Navigated filters traffic to identify
            // the redirect URI. The redirect's query string will contain either the authorization  
            // code if the user consented or an error if the user declined.
            // For example https://login.live.com/oauth20_desktop.srf?code=<code>



            // If the user did not give consent or the application was 
            // not registered, the authorization code will be null.

            if (string.IsNullOrEmpty(_code))
            {
                Console.WriteLine(_error);
                return;
            }
Run Code Online (Sandbox Code Playgroud)

Kri*_*ten 5

无论你做什么,"超级管理员"都必须使用浏览器至少登录一次.您可以通过在服务中托管一个简单的网页来实现,或者您可以在设置过程中执行此操作.实时样本向您展示如何做到这一点.

一旦"超级管理员"使用代码授权登录,您将收到访问令牌和刷新令牌.我不确定Live访问令牌的有效期是多长,但它可能足以记录每晚运行一次.将刷新令牌保存在安全的地方.第二天晚上,您将通过新的访问令牌和新的刷新令牌交换该刷新令牌.同样,您将在下一个晚上保存此新刷新令牌.

只要"超级管理员"没有撤销他给你的应用授权,你就可以让这个过程永远运行.

更新:

某些OAuth 2.0服务器支持"资源所有者密码凭据授权",请参阅http://tools.ietf.org/html/rfc6749上的RFC .如果Live服务器支持,它将是不需要浏览器的代码授予的替代方案.但是,即使服务器支持它,我也会出于安全原因建议不要使用它,因为它需要在服务器上存储"超级管理员"密码.如果有人抓取密码,他们可以完全访问该帐户,并拥有受其保护的所有资源.如果更改密码,它也会崩溃.代码授予没有这些问题.

您的问题表明您希望或需要以"超级管理员"身份运行.另一种选择可能是使用"客户端凭证授权".但是,这还需要将客户机密钥存储在服务器上(与密码凭证授权一样).此外,它仍然需要超级管理员授权客户端,并且本身需要使用浏览器的代码授权.

您问为什么代码授权需要浏览器,为什么您不能使用某种屏幕抓取来模拟浏览器交互.首先,您无法预测将向用户显示的屏幕.这些屏幕在没有通知的情 更重要的是,根据用户选项和历史记录,服务器会显示不同的屏幕.例如,用户可能已启用双因素身份验证.最后但同样重要的是,您为什么反对打开浏览器?它可能比试图模仿它更容易.

最后,这些"超级管理员"用户可能会反对将密码提供给您的应用程序,因为他们并不真正知道您正在使用它做什么(就您所知,您可能会发送到您自己的服务器).通过浏览器使用代码授权,他们知道您的应用程序永远不会看到他们的密码(您可以收听浏览器事件或其他内容,除非浏览器控件在不受您控制的单独进程中运行,例如Windows 8 WebAuthenticationBroker).您的应用程序仅获取具有其授权范围的令牌.