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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…