For me, I was an old but working .NET 4.6.1 MVC website prior to kernel 1.1. Work stopped before I could get it to work, when I lifted it back, I then switched to 2.x.
My problem was that the callback from Google was received from 404 from my site. I thought this should have hit AccountController.ExternalLoginCallback so I added [Route(...)] to it and, of course, the Google callback got into action.
It then hits the null returned in this line (which maniac returns null ?)
var externalLoginInfo = await this.SignInManager.GetExternalLoginInfoAsync();
I reverse engineer this to find under the hood it will eventually get a handler for ExternalScheme which for me was a cookie handler!
Everything seemed wrong, and somehow I felt that the middleware was just to catch the callback URI, so I deleted my [Route(...)] and the 404 problem returned.
Then I discovered that I needed to add this during startup.
applicationBuilder.UseAuthentication();
This solves 404 but gives another problem.
No authenticationScheme scheme was specified, and DefaultSignInScheme was not found.
By adding a default schema here, I am fixing the error above.
serviceCollection.AddAuthentication(IdentityConstants.ExternalScheme) .AddGoogle(googleOptions => Configuration.Bind("OAuth2:Providers:Google", googleOptions)) .AddExternalCookie();
Now AccountController.ExternalLoginCallback again called by some kind of magic, but I returned to the null return value.
I added this code above the offensive line, which, in fact, happens under the hood (looking at the Microsoft code on GitHub). Interestingly, h is of type CookieAuthenticationHandler and has all my requirements and information from Google inside! a
var authHandler = this.HttpContext.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>(); var h = await authHandler.GetHandlerAsync(this.HttpContext, IdentityConstants.ExternalScheme); var a = await h.AuthenticateAsync(); var externalLoginInfo = await this.SignInManager.GetExternalLoginInfoAsync();
By digging into GitHub and copying the pasted internal code that it runs into my controller, I see that it was unable to find ClaimTypes.NameIdentifier in my statements, this is the ProviderKey used later.
Hmm ...
Worried that I used the old 1.x AccountController code with the new 2.x identification bits, I found some examples that still use this stuff, and some examples that also use Razor Pages for all of this. I will continue with what I have.
Next, I’m going to explore the mapping of additional elements of a Google user JSON payload to claims. I think that if my Google Account ID (I think numeric) were matched, then everything would work.
https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/additional-claims?view=aspnetcore-2.2
Final fix
I finally resolved the issue by adding a “sue action” to pull my Google id from the JSON returned from Google!
serviceCollection.AddAuthentication(IdentityConstants.ExternalScheme) .AddGoogle(googleOptions => { Configuration.Bind("OAuth2:Providers:Google", googleOptions); googleOptions.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub", "string"); }) .AddExternalCookie();
The sub field contains what ends up in the nameidentifier claim, and then in the ProviderKey , what the AccountController wants.