尝试通过 oauth 进行身份验证时访问被拒绝
Posted
技术标签:
【中文标题】尝试通过 oauth 进行身份验证时访问被拒绝【英文标题】:Access denied when trying to authenticate through oauth 【发布时间】:2013-10-24 07:14:24 【问题描述】:我可以通过从浏览器获取身份验证令牌并稍后使用“获取...”来获得访问权限。 但我想在没有用户干预的情况下做到这一点。 我决定使用服务帐户。 但是当我试图访问时, 我总是收到“拒绝访问”。 我正在使用
var oAuth2Provider =
(user.OAuthProvider as AdsOAuthProviderForServiceAccounts);
oAuth2Provider.GenerateAccessTokenForServiceAccount();
oAuth2Provider的属性有:
JwtCertificatePassword "notasecret" JwtCertificatePath "D://xxxxx-privatekey.p12" PrnEmail "jrusearchbroadtwomycc@gmail.com" //这是我的 mcc 帐户 批准的开发令牌 ServiceAccountEmail "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()
然后我读到了关于谷歌应用程序帐户的需求。 我已经注册,从我的服务帐户添加到它的帐户客户 ID,看起来像
2222222222222-ckvf630rcccn3j7jjuf4fmujnbiotett.apps.googleusercontent.com 范围:https://adwords.google.com/api/adwords/
但我再次被拒绝访问。
然后我尝试使用另一个看起来像的库 `
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;
但再次接收访问被拒绝
我已经尝试解决这个问题一周了。
【问题讨论】:
有人可以帮我解决我的问题吗??? 您找到解决方案了吗? 我解决了。我现在正在使用谷歌应用程序帐户来检索对 api 的访问。我已将此帐户注册为我的客户中心。 我也是,但有一个不同的问题:将范围设置为https://adwords.google.com/api/adwords
,不带斜杠,就像它说的here。事实证明,尾部斜线很重要。
【参考方案1】:
您真正想要完成的并不是 100% 明显,但如果您需要代表用户进行离线访问,您可能想要的是“刷新令牌”,这样您就可以获得新的访问令牌当您的第一个过期时。信息在https://developers.google.com/accounts/docs/OAuth2WebServer
【讨论】:
我正在尝试在没有用户干预的情况下获得访问权限。它每晚都会在我们的服务器上启动。所以我没有机会手动获取访问令牌以上是关于尝试通过 oauth 进行身份验证时访问被拒绝的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot:Oauth2:访问被拒绝(用户是匿名的);重定向到身份验证入口点
RestSharp OAuth2 承载身份验证失败,访问被拒绝
在 Spring OAuth2 中配置安全性:身份验证请求的访问被拒绝
通过 Lambda 到 GetObject 的 Cognito 身份验证角色 - 调用 GetObject 操作时发生错误 (AccessDenied):访问被拒绝