GoogleOAuth2 始终 return 拒绝访问回调 url
GoogleOAuth2 always return access denied to callback url
我正在尝试使用来自 Microsoft.Owin.Security.Google
的 GoogleAuthenticationExtensions
MVC5 程序中的包。这是我的 StartUp.cs :
var googlePlusOptions = new GoogleOAuth2AuthenticationOptions {};
googlePlusOptions.ClientId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.apps.googleusercontent.com";
googlePlusOptions.AuthorizationEndpoint = "https://accounts.google.com/o/oauth2/auth";
googlePlusOptions.TokenEndpoint = "https://oauth2.googleapis.com/token";
googlePlusOptions.ClientSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
googlePlusOptions.CallbackPath = new PathString("/GoogleLoginCallback");
app.UseGoogleAuthentication(googlePlusOptions);
以及 LoginController 中的 SignInMethod 方法:
[HttpGet]
[AllowAnonymous]
public void SignInGoogle(string ReturnUrl = "/", string type = "")
{
if (!Request.IsAuthenticated)
{
if (type == "Google")
{
var owinContext = HttpContext.GetOwinContext();
owinContext.Authentication.Challenge(new AuthenticationProperties { RedirectUri = "Login/GoogleLoginCallback" }, "Google");
Response.StatusCode = 401;
Response.End();
}
}
}
和 CallBack Url 在同一控制器中:
[AllowAnonymous]
public ActionResult GoogleLoginCallback()
{
var claimsPrincipal = HttpContext.User.Identity as ClaimsIdentity;
var loginInfo = GoogleLoginViewModel.GetLoginInfo(claimsPrincipal);
if (loginInfo == null)
{
return RedirectToAction("Index");
}
var user = db.UserAccounts.FirstOrDefault(x => x.Email == loginInfo.emailaddress);
if (user == null)
{
user = new UserAccount
{
Email = loginInfo.emailaddress,
GivenName = loginInfo.givenname,
Identifier = loginInfo.nameidentifier,
Name = loginInfo.name,
SurName = loginInfo.surname,
IsActive = true
};
db.UserAccounts.Add(user);
db.SaveChanges();
}
var ident = new ClaimsIdentity(
new[] {
// adding following 2 claim just for supporting default antiforgery provider
new Claim(ClaimTypes.NameIdentifier, user.Email),
new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string"),
new Claim(ClaimTypes.Name, user.Name),
new Claim(ClaimTypes.Email, user.Email),
// optionally you could add roles if any
new Claim(ClaimTypes.Role, "User")
},
CookieAuthenticationDefaults.AuthenticationType);
HttpContext.GetOwinContext().Authentication.SignIn(
new AuthenticationProperties { IsPersistent = false }, ident);
return Redirect("~/");
}
现在程序进入 Google 的登录屏幕,但是当它返回到回调 Url 时
loginInfo 为空。这是回调 Url 的响应:
到目前为止我所做的事情没有任何结果:
1-激活 Google+ APi
2-将 nuget 更新到最新版本 (4.2 atm)
3-将电子邮件添加到 TestUser 或将 google 控制台中的项目更改为生产
4-在 google 控制台中添加并填写同意部分
5-将 js 回调设置为空白
有点奇怪的是,如果我修改 ClientId,google 的登录屏幕将阻止我,但如果我更改 secretId,则什么也不会发生,但我仍然看到上面的错误。
我今天从 OAuth 控制台面板得到了他们两个 (ClientId,SecretId)。
对于这类问题,如果不重新创建完整的环境设置,就很难准确指出问题出在哪里。所以我只能尝试解释发生了什么,但要获得更精确的解决方案,您将不得不深入研究它。
基本上我不确定您对 OpenIDConnect 和 OAuth2.0 流程了解多少,但我可以描述您的场景中发生的情况。
- 您的应用程序正在将用户重定向到 google 登录页面
- 用户正在登录
- 成功登录后 google 使用这些查询参数将用户浏览器重定向回您的应用程序(屏幕截图的第三行)
- 现在您的应用程序应采用这些参数并将其发送到反向通道(服务器到服务器请求)中的 google,以将其从 google 交换为
access_token
。这是一个棘手的部分 - 可能你认为你正在立即执行 GoogleLoginCallback
方法 - 但你没有。真正发生的是 GoogleAuthentication Middleware 承担了这个责任。它确定该请求是 OpenIDConnect 流程的一部分,并将尝试为您获取令牌并在您的上下文中设置身份。
- 不幸的是出了点问题,因为您使用
?error=access_denied
参数进行了另一个重定向。这完全由 Katana 项目的 GoogleOAuth2AuthenticationHandler
实现完成:https://github.com/aspnet/AspNetKatana/blob/beb224c88712b08ce45f1d14bb8cf0cd9d4a8503/src/Microsoft.Owin.Security.Google/GoogleOAuth2AuthenticationHandler.cs#L259 这是执行此操作的代码。我认为您应该使用此存储库来识别流程以及可能出现的问题(出于某种原因,您的 context.Identity
似乎是 null
)。
- 现在在那个重定向上你终于执行了你的控制器方法
GoogleLoginCallback
但我猜是因为上一步失败了 - 我们在那个请求中没有正确的身份状态。
您没有分享更多 Startup.cs
但您应该使用 .UseCookieAuthentication()
,如 Katana 示例 https://github.com/aspnet/AspNetKatana/blob/beb224c88712b08ce45f1d14bb8cf0cd9d4a8503/samples/Katana.Sandbox.WebServer/Startup.cs#L83
我认为您需要更改的绝对是您需要更改或删除设置 CallbackPath
属性 用于识别 OpenID 流程步骤 https://github.com/aspnet/AspNetKatana/blob/beb224c88712b08ce45f1d14bb8cf0cd9d4a8503/src/Microsoft.Owin.Security.Google/GoogleOAuth2AuthenticationHandler.cs#L224. This callback is only for the purpose of exchanging for the access token and default value is /signin-google
https://github.com/aspnet/AspNetKatana/blob/dbe159e43e2eee44f315f26268943e8ab5a4f60d/src/Microsoft.Owin.Security.Google/GoogleOAuth2AuthenticationOptions.cs#L28 因此 GoogleAuthenticationHandler 每次都会启动您将尝试访问您的控制器方法。
抱歉,如果这仍然没有帮助。但我认为你应该有足够的资源来慢慢找到你的解决方案。如果您仍然无法确定问题,我的建议是将 类 从 Katana github 复制到您的项目中,重命名,然后整个流程应该是 'debbugable'.
然后回答你的最后一个问题:
- ClientId 在流程的初始步骤中使用,因此它会提前失败
- ClientSecret 在令牌交换步骤 https://github.com/aspnet/AspNetKatana/blob/beb224c88712b08ce45f1d14bb8cf0cd9d4a8503/src/Microsoft.Owin.Security.Google/GoogleOAuth2AuthenticationHandler.cs#L71 中使用,因此用户将在 google 上登录,但您的应用程序将无法从 google 的反向通道中检索令牌,因为 Secret 是无效 - 这就是行为相似的原因
我正在尝试使用来自 Microsoft.Owin.Security.Google
的 GoogleAuthenticationExtensionsMVC5 程序中的包。这是我的 StartUp.cs :
var googlePlusOptions = new GoogleOAuth2AuthenticationOptions {};
googlePlusOptions.ClientId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.apps.googleusercontent.com";
googlePlusOptions.AuthorizationEndpoint = "https://accounts.google.com/o/oauth2/auth";
googlePlusOptions.TokenEndpoint = "https://oauth2.googleapis.com/token";
googlePlusOptions.ClientSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
googlePlusOptions.CallbackPath = new PathString("/GoogleLoginCallback");
app.UseGoogleAuthentication(googlePlusOptions);
以及 LoginController 中的 SignInMethod 方法:
[HttpGet]
[AllowAnonymous]
public void SignInGoogle(string ReturnUrl = "/", string type = "")
{
if (!Request.IsAuthenticated)
{
if (type == "Google")
{
var owinContext = HttpContext.GetOwinContext();
owinContext.Authentication.Challenge(new AuthenticationProperties { RedirectUri = "Login/GoogleLoginCallback" }, "Google");
Response.StatusCode = 401;
Response.End();
}
}
}
和 CallBack Url 在同一控制器中:
[AllowAnonymous]
public ActionResult GoogleLoginCallback()
{
var claimsPrincipal = HttpContext.User.Identity as ClaimsIdentity;
var loginInfo = GoogleLoginViewModel.GetLoginInfo(claimsPrincipal);
if (loginInfo == null)
{
return RedirectToAction("Index");
}
var user = db.UserAccounts.FirstOrDefault(x => x.Email == loginInfo.emailaddress);
if (user == null)
{
user = new UserAccount
{
Email = loginInfo.emailaddress,
GivenName = loginInfo.givenname,
Identifier = loginInfo.nameidentifier,
Name = loginInfo.name,
SurName = loginInfo.surname,
IsActive = true
};
db.UserAccounts.Add(user);
db.SaveChanges();
}
var ident = new ClaimsIdentity(
new[] {
// adding following 2 claim just for supporting default antiforgery provider
new Claim(ClaimTypes.NameIdentifier, user.Email),
new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string"),
new Claim(ClaimTypes.Name, user.Name),
new Claim(ClaimTypes.Email, user.Email),
// optionally you could add roles if any
new Claim(ClaimTypes.Role, "User")
},
CookieAuthenticationDefaults.AuthenticationType);
HttpContext.GetOwinContext().Authentication.SignIn(
new AuthenticationProperties { IsPersistent = false }, ident);
return Redirect("~/");
}
现在程序进入 Google 的登录屏幕,但是当它返回到回调 Url 时
loginInfo 为空。这是回调 Url 的响应:
到目前为止我所做的事情没有任何结果: 1-激活 Google+ APi 2-将 nuget 更新到最新版本 (4.2 atm) 3-将电子邮件添加到 TestUser 或将 google 控制台中的项目更改为生产 4-在 google 控制台中添加并填写同意部分 5-将 js 回调设置为空白
有点奇怪的是,如果我修改 ClientId,google 的登录屏幕将阻止我,但如果我更改 secretId,则什么也不会发生,但我仍然看到上面的错误。 我今天从 OAuth 控制台面板得到了他们两个 (ClientId,SecretId)。
对于这类问题,如果不重新创建完整的环境设置,就很难准确指出问题出在哪里。所以我只能尝试解释发生了什么,但要获得更精确的解决方案,您将不得不深入研究它。
基本上我不确定您对 OpenIDConnect 和 OAuth2.0 流程了解多少,但我可以描述您的场景中发生的情况。
- 您的应用程序正在将用户重定向到 google 登录页面
- 用户正在登录
- 成功登录后 google 使用这些查询参数将用户浏览器重定向回您的应用程序(屏幕截图的第三行)
- 现在您的应用程序应采用这些参数并将其发送到反向通道(服务器到服务器请求)中的 google,以将其从 google 交换为
access_token
。这是一个棘手的部分 - 可能你认为你正在立即执行GoogleLoginCallback
方法 - 但你没有。真正发生的是 GoogleAuthentication Middleware 承担了这个责任。它确定该请求是 OpenIDConnect 流程的一部分,并将尝试为您获取令牌并在您的上下文中设置身份。 - 不幸的是出了点问题,因为您使用
?error=access_denied
参数进行了另一个重定向。这完全由 Katana 项目的GoogleOAuth2AuthenticationHandler
实现完成:https://github.com/aspnet/AspNetKatana/blob/beb224c88712b08ce45f1d14bb8cf0cd9d4a8503/src/Microsoft.Owin.Security.Google/GoogleOAuth2AuthenticationHandler.cs#L259 这是执行此操作的代码。我认为您应该使用此存储库来识别流程以及可能出现的问题(出于某种原因,您的context.Identity
似乎是null
)。 - 现在在那个重定向上你终于执行了你的控制器方法
GoogleLoginCallback
但我猜是因为上一步失败了 - 我们在那个请求中没有正确的身份状态。
您没有分享更多 Startup.cs
但您应该使用 .UseCookieAuthentication()
,如 Katana 示例 https://github.com/aspnet/AspNetKatana/blob/beb224c88712b08ce45f1d14bb8cf0cd9d4a8503/samples/Katana.Sandbox.WebServer/Startup.cs#L83
我认为您需要更改的绝对是您需要更改或删除设置 CallbackPath
属性 用于识别 OpenID 流程步骤 https://github.com/aspnet/AspNetKatana/blob/beb224c88712b08ce45f1d14bb8cf0cd9d4a8503/src/Microsoft.Owin.Security.Google/GoogleOAuth2AuthenticationHandler.cs#L224. This callback is only for the purpose of exchanging for the access token and default value is /signin-google
https://github.com/aspnet/AspNetKatana/blob/dbe159e43e2eee44f315f26268943e8ab5a4f60d/src/Microsoft.Owin.Security.Google/GoogleOAuth2AuthenticationOptions.cs#L28 因此 GoogleAuthenticationHandler 每次都会启动您将尝试访问您的控制器方法。
抱歉,如果这仍然没有帮助。但我认为你应该有足够的资源来慢慢找到你的解决方案。如果您仍然无法确定问题,我的建议是将 类 从 Katana github 复制到您的项目中,重命名,然后整个流程应该是 'debbugable'.
然后回答你的最后一个问题:
- ClientId 在流程的初始步骤中使用,因此它会提前失败
- ClientSecret 在令牌交换步骤 https://github.com/aspnet/AspNetKatana/blob/beb224c88712b08ce45f1d14bb8cf0cd9d4a8503/src/Microsoft.Owin.Security.Google/GoogleOAuth2AuthenticationHandler.cs#L71 中使用,因此用户将在 google 上登录,但您的应用程序将无法从 google 的反向通道中检索令牌,因为 Secret 是无效 - 这就是行为相似的原因