Authentication fails from mobile browser

Hi! I have this site:

https://lenceria-7yeyjec4xa-de.a.run.app/

If login in from the web, authentication works fine, but authentication fails if login from a mobile device (mobile browser).

Please, if you can explain the difference, it would be very important for me.

Thanks in advance.

Hi @sarmientodiego1979,

Are you seeing any errors? What is happening, what is failing?

Thanks for answering.
I was making changes to replay.

The throwing error is:

An unhandled exception occurred while processing the request.
Exception: OpenIdConnectAuthenticationHandler: message.State is null or empty.
Unknown location

Exception: An error was encountered while handling the remote login.
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler.HandleRequestAsync()

Stack Query Cookies Headers Routing
Exception: OpenIdConnectAuthenticationHandler: message.State is null or empty.

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)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Show raw exception details

Remember that from the web it works fine, and from mobile phones it does not .
In case you want to enter: http://lenceria-7yeyjec4xa-de.a.run.app/

Could you post your code for the auth0 implementation? Please omit sensitive data.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using LenceriaMagicas.Data;

using System.Net.Http;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Authentication.OAuth;
using System.Net.Http.Headers;
using System.Text.Json;
using System.Security.Claims;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.IdentityModel.Tokens;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;

using LenceriaMagicas.Util;

namespace LenceriaMagicas
{
    public class Startup
    {
        public static List<Business.Category> memCategories;
        public static List<Business.Subcategory> memSubcategories;
        //public static UserWrapper userWrapper;
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
            memCategories = Business.Category.GetAll().Where(c => c.Enabled = true).ToList();
            memSubcategories = Business.Subcategory.GetAll().Where(c => c.Enabled = true).ToList();
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {


            services.AddRazorPages();
            services.AddServerSideBlazor();

            if (!services.Any(x => x.ServiceType == typeof(HttpClient)))
            {
                services.AddScoped<HttpClient>(s =>
                {
                    var uriHelper = s.GetRequiredService<NavigationManager>();
                    return new HttpClient
                    {
                        BaseAddress = new Uri(uriHelper.BaseUri)
                    };
                });
            }

            //----------------------------------------------------------------------------------------
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            // Add authentication services
            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
               
            })
            .AddCookie()
            .AddOpenIdConnect("Auth0", options =>
            {
                // Set the authority to your Auth0 domain
                options.Authority = $"https://{Configuration["Auth0:Domain"]}";

                // Configure the Auth0 Client ID and Client Secret
                options.ClientId = Configuration["Auth0:ClientId"];
                options.ClientSecret = Configuration["Auth0:ClientSecret"];

                // Set response type to code
                options.ResponseType = "code";

                // Configure the scope
                options.Scope.Clear();
                options.Scope.Add("openid");
                options.Scope.Add("profile");
                options.Scope.Add("email");

                // Set the callback path, so Auth0 will call back to http://localhost:3000/callback
                //Also ensure that you have added the URL as an Allowed Callback URL in your Auth0 dashboard
                //options.CallbackPath = new PathString("/account/callback");
                options.CallbackPath = new PathString("/callback");
                // Configure the Claims Issuer to be Auth0
                options.ClaimsIssuer = "Auth0";

                // Saves tokens to the AuthenticationProperties
                options.SaveTokens = true;

                // Set the correct name claim type
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = "name",
                    RoleClaimType = $"https://{Configuration["Auth0:Domain"]}/v2/roles?client_id={Configuration["Auth0:ClientId"]}"
                    //RoleClaimType = "https://schemas.quickstarts.com/roles"
                    //https://{Configuration["Auth0:Domain"]}/v2/logout
                };

                options.Events = new OpenIdConnectEvents
                {
                    // handle the logout redirection
                    OnRedirectToIdentityProviderForSignOut = (context) =>
                    {
                        var logoutUri = $"https://{Configuration["Auth0:Domain"]}/v2/logout?client_id={Configuration["Auth0:ClientId"]}";

                        var postLogoutUri = context.Properties.RedirectUri;
                        if (!string.IsNullOrEmpty(postLogoutUri))
                        {
                            if (postLogoutUri.StartsWith("/"))
                            {
                                // transform to absolute
                                var request = context.Request;
                                postLogoutUri = request.Scheme + "://" + request.Host + request.PathBase + postLogoutUri;
                            }
                            logoutUri += $"&returnTo={ Uri.EscapeDataString(postLogoutUri)}";
                        }

                        context.Response.Redirect(logoutUri);
                        context.HandleResponse();

                        return Task.CompletedTask;
                    }
                };
            });

            // Add framework services.
            services.AddControllersWithViews();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (true)
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/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();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();
            //---------------------------------------------------------------------
            app.UseAuthorization();
            app.UseAuthentication();
            //---------------------------------------------------------------------

            app.UseEndpoints(endpoints =>
            {

                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");
            });
        }
    }
}

I made it work. If anyone needs it, write me.

Thanks

Feel free to share in this thread, even if it’s just a brief description of your solution it may help someone in the future. Thanks!

It was a code problem. I am deploying Blazor in Google Cloud Run, so there were not many examples about it.

Specifically, the problem was in the http / https callback (I suppose that related to load balancing). To solve it I had to put the following code in the Configure method of Startup.cs:

app.UseForwardedHeaders (new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedProto
});

Regards.

1 Like

Thanks for the reply!

1 Like

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.