skip to Main Content

I have a problem with implementation of google oauth2.
I get a redirection missmatch.

I have in google console https://localhost:4200/signin-google.

My confusion is this. If I do https://localhost:4200/api/google/response in google console and in options.CallbackPath. Then I get succesfuly redirect of the challenge but the /api/google/response never gets trigger during the google’s middleware authentication.(I have various consoles that will not print). It also is succesful cause I get a cookie with my google infos like name , email etc.

A lot of tutorials just set google console to https://localhost:4200/signin-google. They never set the options.CallbackPath or any http:localhost/signin-google route and they play succesfully while I’m getting
Error 400: redirect_uri_mismatch (which is correct because my application does not have https://localhost:4200/signin-google).

Should I go back to https://localhost:4200/api/google/response on both google console and set CallbackPath to /api/google/response and see why it does not trigger?

Should I add route to /singin-google on my application?

Why in many tutorials without routing and CallbackPath work while in my case just do not?

Thank you in advance.

The startup.cs

 public void ConfigureServices(IServiceCollection services)
 {
   // configurations
   services.Configure<EnvironmentVariables>(Configuration.GetSection(EnvironmentVariables.EnvironmentVariable));
   services.Configure<RabbitMQSettingsOptions>(Configuration.
    GetSection(RabbitMQSettingsOptions.RabbitMQSettings));

   services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
   .AddCookie(options =>
   {
     this.SetUpCookieAuthentication(options);
   });

   services.AddAuthentication().AddGoogle(options =>
   {
     this.SetUpGoogleAuthentication(options);
   });

   services.AddCors(options =>
   {
     this.SetUpCorsPolicy(options);
   });

  ...
 }
private void SetUpGoogleAuthentication(GoogleOptions options)
{
  ...
  // set GoogleOptions
  //options.CallbackPath = new PathString(path);
  options.ClientSecret = googleAuthentication.ClientSecret;
  options.ClientId = googleAuthentication.ClientId;
  
}

  public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  {
    if (env.IsDevelopment())
    {
      app.UseDeveloperExceptionPage();
    }
    //app.UseHttpsRedirection();

    app.UseRouting();

    app.UseCors("CorsPolicy");
    // app.UseSession();
    app.UseAuthentication();
    app.UseAuthorization();
    app.UseCookiePolicy();

    app.UseEndpoints(endpoints =>
    {
      endpoints.MapControllers();
    });
  }

GoogleController.cs

using AutoMapper.Internal;
using Domain.DDtos.Users;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.Google;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using ServiceLayer.Dtos.Users;
using ServiceLayer.Interfaces;
using ServiceLayer.Services;
using ServiceLayer.Types;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace Eshop.Controllers
{
  [Route("api/google")]
  [ApiController]
  public class GoogleController : ControllerBase
  {
    private IOptions<EnvironmentVariables> _envOptions;
    private readonly IEnvironmentVariableService _envService;
    private readonly IUserService _userService;

    public GoogleController(IOptions<EnvironmentVariables> envOptions,
      IEnvironmentVariableService envService, IUserService userService)
    {
      _envOptions = envOptions;
      _envService = envService;
      _userService = userService;
    }

    [HttpGet("signin")]
    public async Task<ActionResult> GetGoogleSignInAsync()
    {
      var googleAuthenticationFile = await _envService.GetEnvironmentVariableValueAsync(_envOptions.Value.GoogleAuthentication);
      if (googleAuthenticationFile == null)
        throw new Exception("Could not find the actual google authentication file.");

      var googleAuthentication = JsonConvert.DeserializeObject<OAuth2Credentials>(googleAuthenticationFile);
      var redirectUri = googleAuthentication.RedirectUris.FirstOrDefault();
      var properties = new AuthenticationProperties
      {
        RedirectUri = Url.Action("GoogleResponseAsync")
      };
      return Challenge(properties, GoogleDefaults.AuthenticationScheme);
    }

    [HttpGet("response")]
    public async Task<ActionResult> GoogleResponseAsync()
    {
      Console.WriteLine("in response");
      var result = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
      if (!result.Succeeded)
        return Unauthorized();
      Debug.WriteLine(JsonConvert.SerializeObject(result));
      var userLinkDto = new UserLinkDto();
      var claims = result.Principal.Identities.FirstOrDefault().Claims.Select(claim => new
      {
        claim.Issuer,
        claim.OriginalIssuer,
        claim.Type,
        claim.Value,
      });
      claims.ForAll(claim =>
      {
        var claimType = Constants.GoogleClaimsDict.GetValueOrDefault(claim.Type);
        var dtoProp = claimType != null ? userLinkDto.GetType().GetProperty(claimType) : null;
        if (dtoProp != null)
          dtoProp.SetValue(userLinkDto, claim.Value);
      });
      return Ok();
    }

2

Answers


  1. Chosen as BEST ANSWER

    Okay the problem was splited into 2 parts. The first one is that I needed to wait hours before google console accept changes of authorized redirect urls to https://localhost:4200/signin-google. That's why I was getting redirection missmatch.

    The second problem that appeared after the above fix, which it was an infinite times of /api/google/signin requesting to google was because of this part

    RedirectUri = Url.Action("GoogleResponseAsync")

    In actions which ends in Async I needed to give the action without the Async part, otherwise I dont get a valid url.

    Fix:

    RedirectUri = Url.Action("GoogleResponse")

    link of the bug: https://github.com/dotnet/aspnetcore/issues/14606

    That's why I had many problems following the tutorials without CallbackPath and I was getting weird infinity requests. Also the final url that you want to run after access token is created, must be set in the challenge and not in your google console -> authorized_redirect_url or your CallbackPath because CallbackPath is for internal use.


  2. Error 400: redirect_uri_mismatch (which is correct because my application does not have https://localhost:4200/signin-google).

    redirect_uri_mismatch does not mean that your application doesnt have https://localhost:4200/signin-google it means that you have not configured that redirect uri in Google developer console for your application as a valid redirect uri.

    How the fix redirect_uri_mismatch error.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search