Search code examples
identityserver4google-signin.net-core-3.1

.net core 3.1 Google SSO Callback url not hit


I followed a link to achieve google SSO github.com/aspnet/Security/issues/1370. But even after successful login it is taking me to redirect uri mentioned in authentication property. It is not taking to the callback url. Could someone help on this? Our application is a .net core 3.1 with IdentityServer4. Am expecting signinoauth2 API to be hit after google login, but thats not happening.

I could see a network call from browser with below format and getting correlation error. https://localhost:44368/signinoauth2?state=&code=&scope=***&prompt=none

Exception: Correlation failed. Show raw exception details Exception: An error was encountered while handling the remote login. Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler.HandleRequestAsync() Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) Soulbook.Api.Startup+<>c+<b__5_1>d.MoveNext() in Startup.cs await next.Invoke(); Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context) PFB my code for reference,

        [HttpGet]
        [Authorize(AuthenticationSchemes = GoogleDefaults.AuthenticationScheme)]
        [Route("/Feed")]
        public ActionResult Feed() 
        {
            return Ok();
        }
        [HttpGet]
        [Route("/signin")]
        public ActionResult SignIn()
        {
            var authProperties = new AuthenticationProperties
            {
                RedirectUri = "/"
            };
            return new ChallengeResult(GoogleDefaults.AuthenticationScheme, authProperties);
        }
        [HttpPost]
        [Route("/signinoauth2")]
        public ActionResult<LoginResponse> signinoauth2Async([FromForm]object data)
        {

            return Ok();
        }

Startup.cs

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authentication.Google;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Authorization;


services.AddAuthentication(options =>
                    {
                        options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                        options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
                    })
                      .AddCookie(o => {
                          o.LoginPath = "/signin";
                          o.LogoutPath = "/signout";
                          o.ExpireTimeSpan = TimeSpan.FromDays(7);
                      })
                      .AddGoogle(o => {
                          o.ClientId = "***";
                          o.ClientSecret = "**";
                          o.SaveTokens = true;
                          o.CallbackPath = "/signinoauth2";
                      });

services.AddMvc(config =>
            {
                var policy = new AuthorizationPolicyBuilder()
                                .RequireAuthenticatedUser()
                                .AddAuthenticationSchemes(GoogleDefaults.AuthenticationScheme)
                                .Build();
                config.Filters.Add(new AuthorizeFilter(policy));
            }).AddNewtonsoftJson();



EDIT: Having signinoauth2 in any one of the below formats also doesnt help.
        [HttpGet]
        [Route("/signinoauth2")]
        public ActionResult<LoginResponse> signinoauth2Async(string state, string code, string scope, string prompt)
        {

            return Ok();
        }

        [HttpPost]
        [Route("/signinoauth2")]
        public ActionResult<LoginResponse> signinoauth2Async(string state, string code, string scope, string prompt)
        {

            return Ok();
        }

Solution

  • I assume that you want to get Google user information in your enpoint? Then what you have to do is configure the external authentication properties. And thanks to this you are going to be able to get the user on your redirect endpoint.

        [HttpGet("login/google/")]
        [AllowAnonymous]
        public async Task<IActionResult> LoginGoogle()
        {
            var properties = _signInManager.ConfigureExternalAuthenticationProperties(GoogleDefaults.AuthenticationScheme, "/api/identity/google-redirect");
            return Challenge(properties, GoogleDefaults.AuthenticationScheme);
        }
    

    What you configured on startup is a callback route which gets handled by Middleware and never hits the endpoint in your controller. What you want to achive is get user on redirect route like this

        [HttpGet("google-redirect")]
        [AllowAnonymous]
        public async Task<IActionResult> CallbackGoogle()
        {
            var info = await _signInManager.GetExternalLoginInfoAsync();
            return Ok();
        }