2013-10-24 69 views
0

我可以通過從瀏覽器獲取身份驗證令牌並稍後使用「獲取...」訪問權限。 但我想在沒有用戶干預的情況下做到這一點。 我決定使用服務帳戶。 但是,當我試圖訪問, 我總是收到「訪問被拒絕」。 我使用嘗試通過oauth進行身份驗證時訪問被拒絕

var oAuth2Provider = 
       (user.OAuthProvider as AdsOAuthProviderForServiceAccounts); 
     oAuth2Provider.GenerateAccessTokenForServiceAccount(); 

oAuth2Provider的特性是:

JwtCertificatePassword 「notasecret」
JwtCertificatePath 「d://xxxxx-privatekey.p12」
PrnEmail「jrusearchbroadtwomycc @ gmail的。 com「//這是我的mcc賬號 已批准的開發人員令牌
ServiceAccountEmail」[email protected]ccount.com「

以下是錯誤的堆棧跟蹤。

at Google.Api.Ads.Common.Lib.OAuth2ProviderForServiceAccounts.GenerateAccessTokenForServiceAccount() 
    at AdwordsStat.GetReports.DoAuth2Authorization(AdsUser user) in D:\Adwords_API\Jooble_Adwords\GetReports.cs:line 48 
    at AdwordsStat.Form1.Form1_Shown(Object sender, EventArgs e) in D:\Adwords_API\Jooble_Adwords\Form1.cs:line 87 
    at System.Windows.Forms.Form.OnShown(EventArgs e) 
    at System.Windows.Forms.Form.CallShownEvent() 
    at System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme) 
    at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj) 
    at System.Threading.ExecutionContext.runTryCode(Object userData) 
    at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData) 
    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
    at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme) 
    at System.Windows.Forms.Control.InvokeMarshaledCallbacks() 
    at System.Windows.Forms.Control.WndProc(Message& m) 
    at System.Windows.Forms.ScrollableControl.WndProc(Message& m) 
    at System.Windows.Forms.Form.WndProc(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 
    at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 
    at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) 
    at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData) 
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) 
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) 
    at System.Windows.Forms.Application.Run(Form mainForm) 
    at AdwordsStat.Program.Main() in D:\Adwords_API\Jooble_Adwords\Program.cs:line 16 
    at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 
    at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 
    at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 
    at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
    at System.Threading.ThreadHelper.ThreadStart() 

然後我已閱讀了關於谷歌應用程序帳戶的需求。 我已經註冊,加入到它的帳戶cliend ID從看起來像

2222222222222-ckvf630rcccn3j7jjuf4fmujnbiotett.apps.googleusercontent.com 範圍我的服務帳戶:https://adwords.google.com/api/adwords/

,但我得到的訪問再次否認。

然後我試圖使用其他的lib,它看起來像 `

public static Dictionary<string, string> GetAccessToken(string clientIdEMail, string keyFilePath, string scope) 
     { 
      // certificate 
      var certificate = new X509Certificate2(keyFilePath, "notasecret"); 

     // header 
     var header = new { typ = "JWT", alg = "RS256" }; 

     // claimset 
     var times = GetExpiryAndIssueDate(); 
     var claimset = new 
     { 
      iss = clientIdEMail, 
      scope = scope, 
      aud = "https://accounts.google.com/o/oauth2/token", 
      iat = times[0], 
      exp = times[1], 
     }; 

     JavaScriptSerializer ser = new JavaScriptSerializer(); 

     // encoded header 
     var headerSerialized = ser.Serialize(header); 
     var headerBytes = Encoding.UTF8.GetBytes(headerSerialized); 
     var headerEncoded = Convert.ToBase64String(headerBytes); 

     // encoded claimset 
     var claimsetSerialized = ser.Serialize(claimset); 
     var claimsetBytes = Encoding.UTF8.GetBytes(claimsetSerialized); 
     var claimsetEncoded = Convert.ToBase64String(claimsetBytes); 

     // input 
     var input = headerEncoded + "." + claimsetEncoded; 
     var inputBytes = Encoding.UTF8.GetBytes(input); 

     // signiture 
     var rsa = certificate.PrivateKey as RSACryptoServiceProvider; 
     var cspParam = new CspParameters 
     { 
      KeyContainerName = rsa.CspKeyContainerInfo.KeyContainerName, 
      KeyNumber = rsa.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2 
     }; 
     var aescsp = new RSACryptoServiceProvider(cspParam) { PersistKeyInCsp = false }; 
     var signatureBytes = aescsp.SignData(inputBytes, "SHA256"); 
     var signatureEncoded = Convert.ToBase64String(signatureBytes); 

     // jwt 
     var jwt = headerEncoded + "." + claimsetEncoded + "." + signatureEncoded; 

     var client = new WebClient(); 
     client.Encoding = Encoding.UTF8; 
     var uri = "https://accounts.google.com/o/oauth2/token"; 
     var content = new NameValueCollection(); 

     content["assertion"] = jwt; 
     content["grant_type"] = "urn:ietf:params:oauth:grant-type:jwt-bearer"; 

     string response = Encoding.UTF8.GetString(client.UploadValues(uri, "POST", content)); 

     var result = ser.Deserialize<Dictionary<string, string>>(response); 

     return result; 
    } 

    private static int[] GetExpiryAndIssueDate() 
    { 
     var utc0 = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); 
     var issueTime = DateTime.UtcNow; 

     var iat = (int)issueTime.Subtract(utc0).TotalSeconds; 
     var exp = (int)issueTime.AddMinutes(55).Subtract(utc0).TotalSeconds; 

     return new[] { iat, exp }; 
    }` 

這 - 我收到後訪問令牌和到期時間。

var result = GetAccessToken(SERVICE_ACCOUNT_EMAIL, SERVICE_ACCOUNT_PKCS12_FILE_PATH, SCOPE_ANALYTICS_READONLY); 
      string access_token; 
      result.TryGetValue("access_token", out access_token); 

然後我試圖

oAuth2Provider.AccessToken = access_token; 

但再次接受訪問被拒絕

我一直在試圖解決這個問題的一個星期。

+0

有人可以幫我解決我的問題嗎? – Aidanpraid

+0

您是否找到了解決方案? – Hnatt

+0

我解決了它。 我現在正在使用谷歌應用帳戶來檢索對API的訪問。 而且我已將此帳戶註冊爲我的客戶中心。 – Aidanpraid

回答

0

這並不是100%顯而易見的,但是如果您需要代表用戶進行離線訪問,您可能需要的是「刷新令牌」,因此您可以獲得新的訪問權限當您的第一個到期時,您會收到代幣信息是在https://developers.google.com/accounts/docs/OAuth2WebServer

+0

我試圖在沒有用戶干預的情況下訪問。它每天晚上都會在我們的服務器上啓動。 所以我不會有機會獲得訪問令牌手動 – Aidanpraid

相關問題