可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I decided to give the new Google Oauth2 middleware a try and it has pretty much broken everything. Here is my provider config from startup.auth.cs.. When turned on, all of the providers including the google provider get a 500 internal server on Challenge. However the details of the internal server error are not available and I cant figure out how to turn on any debugging or tracing for the Katana middleware. Seems to me like they were in a rush to get the google Oauth middleware out the door.
//// GOOGLE
var googleOptions = new GoogleOAuth2AuthenticationOptions
{
ClientId = "228",
ClientSecret = "k",
CallbackPath = new PathString("/users/epsignin")
SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie,
Provider = new GoogleOAuth2AuthenticationProvider
{
OnAuthenticated = context =>
{
foreach (var x in context.User)
{
string claimType = string.Format("urn:google:{0}", x.Key);
string claimValue = x.Value.ToString();
if (!context.Identity.HasClaim(claimType, claimValue))
context.Identity.AddClaim(new Claim(claimType, claimValue, XmlSchemaString, "Google"));
}
return Task.FromResult(0);
}
}
};
app.UseGoogleAuthentication(googleOptions);
ActionMethod Code:
[AllowAnonymous]
public ActionResult ExternalProviderSignIn(string provider, string returnUrl)
{
var ctx = Request.GetOwinContext();
ctx.Authentication.Challenge(
new AuthenticationProperties
{
RedirectUri = Url.Action("EPSignIn", new { provider })
},
provider);
return new HttpUnauthorizedResult();
}
回答1:
This took me hours to figure out, but the issue is the CallbackPath
as mentioned by @CrazyCoder. I realised that the CallbackPath
in public void ConfigureAuth(IAppBuilder app)
MUST be different to when it is being set in the ChallengeResult
. If they are the same a 500 error is thrown in OWIN.
My code is for ConfigureAuth(IAppBuilder app)
is
var googleOptions = new Microsoft.Owin.Security.Google.GoogleOAuth2AuthenticationOptions
{
ClientId = "xxx",
ClientSecret = "yyy",
CallbackPath = new PathString("/callbacks/google"), //this is never called by MVC, but needs to be registered at your oAuth provider
Provider = new GoogleOAuth2AuthenticationProvider
{
OnAuthenticated = (context) =>
{
context.Identity.AddClaim(new Claim("picture", context.User.GetValue("picture").ToString()));
context.Identity.AddClaim(new Claim("profile", context.User.GetValue("profile").ToString()));
return Task.FromResult(0);
}
}
};
googleOptions.Scope.Add("email");
app.UseGoogleAuthentication(googleOptions);
My 'callbacks' Controller code is:
// GET: /callbacks/googlereturn - callback Action
[AllowAnonymous]
public async Task<ActionResult> googlereturn()
{
return View();
}
//POST: /Account/GooglePlus
public ActionResult GooglePlus()
{
return new ChallengeResult("Google", Request.Url.GetLeftPart(UriPartial.Authority) + "/callbacks/googlereturn", null);
//Needs to be a path to an Action that will handle the oAuth Provider callback
}
private class ChallengeResult : HttpUnauthorizedResult
{
public ChallengeResult(string provider, string redirectUri)
: this(provider, redirectUri, null)
{
}
public ChallengeResult(string provider, string redirectUri, string userId)
{
LoginProvider = provider;
RedirectUri = redirectUri;
UserId = userId;
}
public string LoginProvider { get; set; }
public string RedirectUri { get; set; }
public string UserId { get; set; }
public override void ExecuteResult(ControllerContext context)
{
var properties = new AuthenticationProperties() { RedirectUri = RedirectUri };
if (UserId != null)
{
properties.Dictionary[XsrfKey] = UserId;
}
context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
}
}
- callbacks/google seems to handled by OWIN
- callbacks/googlereturn seems to handled by MVC
It is all working now, although would love to know exactly what is happening 'under the bonnet'
My advice, unless you have another requirement, is to let OWIN use default redirect paths and make sure you don't use them yourself.
回答2:
There is no need to specify CallbackPath
in UseGoogleAuthentication
:
CallbackPath = new PathString("/Account/ExternalLoginCallback")
Just keep the Google setting for Authorized redirect URIs
as:
http(s)://yoururl:orPort/signin-google
Owin handles signin-google internally and redirects to the redirectUri as mentioned in your code for ChallengeResult class. Which is Account/ExternalLoginCallback.
回答3:
Got it working vanilla from the tutorial with ONE simple change - just posting this for any nubes to this approach. I think the problems related to oauth2 in this instance are largely fleshed out in the latest templates/apis - what I mean is, if you are starting from scratch, you may be in luck - read on:
I JUST did this tutorial
https://azure.microsoft.com/en-us/documentation/articles/web-sites-dotnet-deploy-aspnet-mvc-app-membership-oauth-sql-database/
and referenced this also
http://blogs.msdn.com/b/webdev/archive/2014/07/02/changes-to-google-oauth-2-0-and-updates-in-google-middleware-for-3-0-0-rc-release.aspx
The one change:
it worked but ONLY after enabling google+ apis in the newest version of the google developer site.
(Just go to google api lib manager, sign in and search the apis directory for the google+ api).
Note: for me the Google+ api was disabled by default.
I did nothing else unique.
Cheers
回答4:
The answers given so far led me down a really dark path that I wish I had not traveled... the solution is simple make sure that the following 3 things match:
1) In the Google OATH Credentials (https://console.developers.google.com/):
- REDIRECT URIS has https://localhost:44300/Account/ExternalLoginCallback
(Fix your port to whatever you're using)
2) In your AccountController
:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
return new ChallengeResult(provider,
Url.Action("ExternalLoginCallback", "Account",
new { ReturnUrl = returnUrl }));
}
Notice the Action is "ExternalLoginCallback"
3) In your App_Start\Startup.Auth.cs
app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
{
ClientId = "yourclientid.apps.googleusercontent.com",
ClientSecret = "yoursecret",
Provider = new GoogleOAuth2AuthenticationProvider(),
CallbackPath = new PathString("/Account/ExternalLoginCallback")
});
Notice the CallbackPath
again has the same PathString
as the other 2
Finally, if you're still not getting it, set your authentication mode to None in your app Web.config
<authentication mode="None" />
to get some more details about the issue.
回答5:
I'm using the default ASP.NET MVC 5 template with Identity Authentication for simplicity, but hopefully this can be modified for different use cases.
StartupAuth.cs
Do not customize the redirect path. It gets replaced by /signin-google anyways and my attempts at getting around that caused "silent" (not in the debugger) Internal Server 500 errors.
app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
{
ClientId = "whatevs.apps.googleusercontent.com",
ClientSecret = "whatevs_secrut",
Provider = new GoogleOAuth2AuthenticationProvider()
});
Make sure to add http://whatever.com/signin-google to https://console.developers.google.com/ in your APIs & auth
> Credentials
> Redirect URIs
section.
RouteConfig.cs
Add a route to a permanent redirect controller action to your routes. Permanent redirects are the only thing that will suffice here. It is not enough to simply direct directly to the Callback URL.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Google API Sign-in",
url: "signin-google",
defaults: new { controller = "Account", action = "ExternalLoginCallbackRedirect" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
AccountController.cs
Permanent redirect to the built-in callback method and you should be fine.
[AllowAnonymous]
public ActionResult ExternalLoginCallbackRedirect(string returnUrl)
{
return RedirectPermanent("/Account/ExternalLoginCallback");
}
A template project has been posted on GitHub for reference: https://github.com/Pritchard/Test-AspNetGoogleOAuth2Authentication