0

This is one of the trickiest issues I ever had.

I have a .net5 app running in a docker container, in an Azure Web App. This is my Startup.cs file:

public class Startup
{
    public Startup(
        IConfiguration configuration,
        IWebHostEnvironment hostingEnvironment)
    {
        this.Configuration = configuration;
        this.HostingEnvironment = hostingEnvironment;
    }

    public IConfiguration Configuration { get; }
    public IWebHostEnvironment HostingEnvironment { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(
        IServiceCollection services)
    {
        services.AddRepositories(this.Configuration);
        services.AddSettings(this.Configuration);
        services.AddServices();
        services.AddIdentity<ApplicationUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddControllersWithViews();

        services.AddRazorPages(options =>
        {
            options.Conventions.AuthorizeAreaFolder("Identity", "/Account/Manage");
            options.Conventions.AuthorizeAreaPage("Identity", "/Account/Logout");
        });

        services.Configure<ForwardedHeadersOptions>(options =>
        {

            options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
         });

         services.ConfigureApplicationCookie(options =>
         {
             options.LoginPath = $"/Identity/Account/Login";
             options.LogoutPath = $"/Identity/Account/Logout";
             options.AccessDeniedPath = $"/Identity/Account/AccessDenied";

         }); 


        services.AddAuthentication().AddGoogle(options =>
        {
            var googleAuthNSection =
                this.Configuration.GetSection("AppSettings:Authentication:Google");

            options.ClientId = googleAuthNSection["ClientId"];
            options.ClientSecret = googleAuthNSection["ClientSecret"];
            options.CorrelationCookie.SameSite = SameSiteMode.Lax;
        })
        ;
            
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(
        IApplicationBuilder app,
        IWebHostEnvironment env,
        ILogger<Startup> logger)
    {
        app.UseForwardedHeaders();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
        {
            logger.LogInformation("Starting Migration");
            using var context = serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
            context.Database.Migrate();
            logger.LogInformation("Finished Migration");
        }

        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                "default",
                "{controller=Home}/{action=Index}/{id?}");

            endpoints.MapRazorPages();
        });
    }
}

The issue: During most days the app runs smoothly. However, sometimes it fails unexpectedly with the following error:

System.Exception: An error was encountered while handling the remote login.
 ---> System.Exception: The oauth state was missing or invalid.
   --- End of inner exception stack trace ---
   at 
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.HandleRequestAsync()
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext 
context) at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)

I say sometimes, because the app will be running for days at time without an issue, only to then return this error randomly for a few hours. Then it goes back to working normally.

If I start a local app server for debug purposes, the app works as expected every single time.

Can this be an azure resources issue? Or am I hitting the max calls allowed to the Google API? Only me and another person are accessing the app at a time, and we don't use it that much.

Thank you

manuel mourato
  • 771
  • 1
  • 7
  • 33

1 Answers1

0

From beginning, you can use Identity Framework with or without ASP.NET external identity provider/social login. It should be set up like this authentication without identity

public void ConfigureServices(IServiceCollection services)  
{  
// requires  
// using Microsoft.AspNetCore.Authentication.Cookies;  
// using Microsoft.AspNetCore.Authentication.Google;  
// NuGet package Microsoft.AspNetCore.Authentication.Google  
services  
.AddAuthentication(options =>  
{  
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;  
options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;  
})  
.AddCookie()  
.AddGoogle(options =>  
{  
options.ClientId = Configuration["Authentication:Google:ClientId"];  
options.ClientSecret = Configuration["Authentication:Google:ClientSecret"];  
}); 

services.AddRazorPages();  
}

The controller's second flaw was this:

return Challenge(new AuthenticationProperties { RedirectUri = "[https://myhost.com/signin-gitlab"](https://myhost.com/signin-gitlab%22 "https://myhost.com/signin-gitlab%22") }, "Gitlab");  

As with the aspnet-contrib team's MVC Sample app it should actually be:

return Challenge(new AuthenticationProperties { RedirectUri = "/" }, "Gitlab");  

Users were actually being authenticated; the issue was that they were forwarded to the OAuth middleware's internal route /signin-gitlab without state or code arguments, rather than the home route/index action, resulting in the error.

To put it another way, I mixed up:

  • RedirectUri (where user is redirected after authentication)
  • Callback URL (where the OAuth application redirects the user with state and code to the OAuth middleware internal route, which by default is /signin-gitlab, /signin-google, /signin-facebook but can also be overridden with the options.CallbackPath).

Perhaps my confusion stemmed from the fact that the callback url in the GitLab docs is referred to as REDIRECT URI.

Thanks to Nan Yu for SO Link for their illuminating posts.

Ex: Facebook, Google, and external provider authentication without ASP.NET Core Identity