AuthenticationProperties.RedirectUri 未传递给 Challenge() 中的 Google

AuthenticationProperties.RedirectUri is not passed to Google in Challenge()

在我的 Web 应用程序中,我已将 Google 注册为单点登录提供商:

app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions {
    ClientId = "8765.......apps.googleusercontent.com",
    ClientSecret = "Secret"
})

我的应用程序不允许用户 sign-up/register(他们的帐户是由管理员创建的,但他们稍后可以 link 使用 Google 注册他们的帐户)。

在我的 "Sign in with Google" 控制器中,我试图发出 Challenge() 以重定向到 Google。这可能不是正确的方法:

string redirectUri = "http://localhost:55262/SSO/Google/ProcessToken"; // actually created in code, but shown as string for clarity
AuthenticationProperties properties = new AuthenticationProperties();
properties.RedirectUri = Server.UrlEncode(redirectUri);
Context.GetOwinContext().Authentication.Challenge(properties, "Google");

这正确地将用户发送到 Google,但是 Google 然后显示 错误:redirect_uri_mismatch,说:

The redirect URI in the request: http://localhost:55262/signin-google did not match a registered redirect URI.

我以前见过这个错误,当时 Google 控制面板中的 return URI 集合不包含指定的 redirect_uri

如果我在 VS2015 中调试,我可以看到 redirect_uri 属性 在 AuthenticationProperties 中被正确设置,但似乎 OWIN/Katana 没有将它传递给Google。相反,当我点击 Google 时,return_uri 是 OWIN/Katana 使用的默认值。我设置的那个被忽略了

Google 请求细节似乎证实了这一点:

scope=openid profile email
response_type=code
redirect_uri=http://localhost:55262/signin-google

请问我做错了什么?我不应该使用 Challenge() 来允许用户使用 Google link 升级他们的本地应用程序帐户吗?

注意 OWIN 的开放式身份验证有预定义的方法。换句话说,在 localhost:port/signin-google 中,OWIN 等待外部身份验证服务调用 signin-google(尽管您无法在项目)。 signin-google 是一个有效且有效的路径,我强烈建议您不要更改它(因为要避免将新的实现编写为控制器操作)。

我也遇到过类似的麻烦,折腾了很多天,终于发现问题出在原用户的URL上,OWIN发送的redirect_uri有效。显然:

  • 如果你输入 www.site.com → redirect_uri 等于 www.site.com/signin-google
  • 如果你输入 site.com → redirect_uri 等于 site.com/signin-google

而Google将returnredirect_uri_mismatch错误根据输入的重定向URLs中的上述情况之一安慰。我认为您的问题也来自这个现实,解决方案是在控制台中设置任何可能的 URLs。

提供有关已接受答案的更多信息...

可以忽略/signin-google

/signin-google URI 由 OWIN/Katana 内部管理。作为开发人员,您不需要关心它,但是您 do 需要将它作为 授权重定向添加到 Google 开发人员控制台中URI.

在 Google 请求中,请注意 OWIN 总是 将重定向 URI 作为 /signin-google 传递给 Google,无论自定义 URI 是什么你设置在AuthenticationProperties.RedirectUri属性。虽然一开始这可能看起来像 bug/problem,但它的主要优势在于 OWIN 可以通过单个回调 URI 管理所有回调。您的回调 URI 也不会被遗忘(见下文)!

那么您自己的重定向 URL 呢?

嗯,这就是 AuthenticationProperties() 发挥作用的地方。通过像这样指定您自己的回调 URL...

AuthenticationProperties properties = new AuthenticationProperties { RedirectUri = "https://my.app.com/custom/callback/uri" };

...在 OWIN 检查 Google 令牌并提取必要的详细信息后,用户将被重定向到您指定的 URL。

这是我感到困惑的地方,因为我不明白如何处理 /signin-google,而实际上没有采取任何行动。这适用于 MVC 和 webforms——你不需要关心传递给 Google 的内容。但是,如果使用网络表单,或在 web.config 中指定授权规则,您将需要它来防止 returning 用户再次访问日志页面:

<location path="signin-google">
    <system.web>
        <authorization>
            <allow users="*"/>
        </authorization>
    </system.web>
</location>

这是将用户发送到 Google 和 return 包含其详细信息的令牌所需的所有代码:

出站

将用户从控制器发送到 Google、按钮单击事件、页面加载,任何事情(无论您的 ASP/hosting 堆栈如何):

// set the callback, for after OWIN finishes examining what comes back from Google
AuthenticationProperties properties = new AuthenticationProperties { RedirectUri = "https://www.myapp.com/some/callback/uri" };
// send the user to Google
Context.GetOwinContext().Authentication.Challenge(properties, "Google");
// Stop execution of the current page/method - the 401 forces OWIN to kick-in and do its thing
Response.StatusCode = 401;
Response.End();

入站

用户在验证身份后从 Google return 编辑

Microsoft.AspNet.Identity.Owin.ExternalLoginInfo loginInfo = Context.GetOwinContext().Authentication.GetExternalLoginInfo();