Within my web application I have registered Google as a single sign-on provider:
app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions {
ClientId = "8765.......apps.googleusercontent.com",
ClientSecret = "Secret"
})
My app doesn't allow users to sign-up/register (instead their accounts are created by an administrator, but they can later link their account up with Google).
In my "Sign in with Google" controller, I am trying to issue a Challenge()
to redirect to Google. This might not be thecorrect approach:
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");
This correctly sends the user to Google, but Google then presents Error: redirect_uri_mismatch, saying that:
The redirect URI in the request: http://localhost:55262/signin-google did not match a registered redirect URI.
I've seen this error before when the return URI collection in the Google control panel does not contain the redirect_uri
specified.
If I debug in VS2015, I can see the redirect_uri
property being set correctly in the AuthenticationProperties
, but it seems that OWIN/Katana is not passing it to Google. Instead, when I hit Google, the return_uri is the default one used by OWIN/Katana. The one I set is being ignored.
The Google request details seem to confirm this:
scope=openid profile email
response_type=code
redirect_uri=http://localhost:55262/signin-google
What am I doing wrong here please? Should I not be using Challenge()
to allow users to link up their local application account with Google?
To provide additional information on the accepted answer...
/signin-google
It emerges that the /signin-google
URI is internally-managed by OWIN/Katana. You, as a developer, do not need to be concerned by it, but you do need to add it in the Google developer console as an Authorized redirect URI.
In the Google request, note that OWIN always passes the redirect URI to Google as /signin-google
, regardless of what custom URI you set in the AuthenticationProperties.RedirectUri
property. Although at first this may seem like a bug/problem, it has a major advantage in that OWIN can manage all callbacks via a single callback URI. Your callback URI is not forgotten about either (see below)!.
Well, that's where the AuthenticationProperties()
come into play. By specifying your own callback URL like so...
AuthenticationProperties properties = new AuthenticationProperties { RedirectUri = "https://my.app.com/custom/callback/uri" };
...after OWIN has examined the Google token and extracted the necessary details, the user is then redirected to your specified URL.
This was where I was getting confused, as I didn't understand what to do with /signin-google
, when in actual fact no action was taken. This applies to both MVC and webforms - you do not need to concern yourself with what gets passed to Google. However, if using webforms, or specifying authorization rules in web.config, you will need this to prevent returning users hitting the logging page again:
<location path="signin-google">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
Here is all the code you need to send the user to Google, and return the token containing their details:
Send the user to Google from a controller, button click event, page load, anything (regardless of your ASP/hosting stack):
// 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();
The user is returned from Google after validating their identity
Microsoft.AspNet.Identity.Owin.ExternalLoginInfo loginInfo = Context.GetOwinContext().Authentication.GetExternalLoginInfo();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With