簡體   English   中英

嘗試通過oauth進行身份驗證時訪問被拒絕

[英]Access denied when trying to authenticate through oauth

我可以通過從瀏覽器獲取身份驗證令牌並稍后使用“提取...”來獲得訪問權限。 但是我想做到這一點而無需用戶干預。 我決定使用服務帳戶。 但是,當我嘗試獲得訪問權限時,我總是會收到“訪問被拒絕”。 我正在使用

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

oAuth2Provider的屬性是:

JwtCertificatePassword“ notasecret”
JwtCertificatePath“ D://xxxxx-privatekey.p12”
PrnEmail“ jrusearchbroadtwomycc@gmail.com” //這是我的擁有批准開發者令牌的MCC帳戶
電子郵件:“ 22222222222-ckvf630rcccn3j7jjuf4fmujnbiotett@developer.gserviceaccount.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()

然后,我讀到了有關Google Apps帳戶需求的信息。 我已經注冊,從我的服務帳戶添加到它的帳戶客戶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;

但是再次拒絕訪問

我一直在努力解決這個問題一個星期。

您真正要完成的目標並不是100%明顯,但是如果您需要代表用戶進行脫機訪問,則您可能想要的是“刷新令牌”,因此在初始時可以獲取一個新的訪問令牌。一個到期。 該信息位於https://developers.google.com/accounts/docs/OAuth2WebServer

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM