Reputation: 91
I get this error:
OpenIdConnectAuthenticationHandler: message.State is null or empty.
with the URL https://localhost:7208/home/index
, but the authentication works with the url https://localhost:7208/
.
Can anyone help me understand this?
This is my code:
Program.cs
:
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using System.Security.Claims;
using System.Web.Mvc;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddMvc().AddSessionStateTempDataProvider();
builder.Services.Configure<CookieAuthenticationOptions>(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
});
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
}).AddCookie(options =>
{
})
.AddOpenIdConnect(options =>
{
options.Authority = builder.Configuration["OpenIdConfigurations:Authority"];
options.MetadataAddress = builder.Configuration["OpenIdConfigurations:MetadataAddress"];
options.ResponseType = builder.Configuration["OpenIdConfigurations:ResponseType"];
options.GetClaimsFromUserInfoEndpoint = Convert.ToBoolean(builder.Configuration["OpenIdConfigurations:GetClaimsFromUserInfoEndpoint"]);
options.RequireHttpsMetadata = Convert.ToBoolean(builder.Configuration["OpenIdConfigurations:RequireHttpsMetadata"]);
options.ClientId = builder.Configuration["OpenIdConfigurations:ClientId"];
options.ClientSecret = builder.Configuration["OpenIdConfigurations:ClientSecret"];
options.CallbackPath = builder.Configuration["OpenIdConfigurations:CallbackPath"];
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}"
);
app.Run();
Controller:
namespace OIDCMVC.Controllers
{
[Authorize]
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}
Note: We use a private provide and expects the call back path. Callbackpath = "/home/index"
Upvotes: 9
Views: 26352
Reputation: 1
In my case I thought RedirectUri in the following line is the var I should give to IdentityServer, so after successful auth flow I was redirected to the same URL that IdentityServer was redirecting in Auth-Response step.
Challenge(new AuthenticationProperties { RedirectUri = "signin-oidc"}, "oidc");
So I changed it to /home and problem was fixed.
Here is why: the signin-oidc (or any other custom configured URL) is the URL that OpenID client expects IdentityServer send the auth token and state and other necessary params. However after successful login there is no parameter on redirection url by OpenID client so you get state is null or empty.
Upvotes: 0
Reputation: 1
For me, the problem was that the app was launched at https://localhost:7065
without the base path. After I added the base path specified in launchSettings.json
(e.g., https://localhost:7065/Myapp
), it worked.
Upvotes: 0
Reputation: 219
I've been integrating multiple custom policies (different flows) in a single app. Removing CallbackPath
didn't work as request were coming there from multiple sources, not just the default sign in policy. We were receiving "message.State is null or empty" page, but after navigating to the base path of the app, the user was authenticated and properly logged in.
What ultimately helped was setting SkipUnrecognizedRequests
property to true
:
.AddOpenIdConnect(options =>
{
...
options.SkipUnrecognizedRequests = true;
});
or using appsettings:
{
...
"AzureAdB2C": {
"Instance": "",
"Domain": "",
"ClientId": "",
...
"SkipUnrecognizedRequests": true
},
...
}
According to the OpenIdConnectOptions.SkipUnrecognizedRequests documentation:
Indicates if requests to the CallbackPath may also be for other components. If enabled the handler will pass requests through that do not contain OpenIdConnect authentication responses. Disabling this and setting the CallbackPath to a dedicated endpoint may provide better error handling. This is disabled by default.
Also, maybe related issue here: OIDC handler running on '/' crashes even with SkipUnrecognizedRequests set to true #10028
Upvotes: 16
Reputation: 1541
In my case I am using blazor (.net 6) and trying to protect hangfire with Microsoft oauth. To get the auth screen of microsoft login when locating to /hangfire. The solution to this error was as simple as removing CallbackPath from my settings:
// settings found under Azure AD -> App Registration -> Your registration
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "domain", // found under Branding and properties -> publisher domain like : ...outlook.onmicrosoft.com
"TenantId": "tenantid", // found under Overview Directory (tenant) ID GUID
"ClientId": "client_id" // found under Overview Application (client) ID GUID
//"CallbackPath": "/hangfire" REMOVED To get rid off message.State is null error
}
The setup from Program.cs:
services.AddAuthentication().AddMicrosoftIdentityWebApp(configuration.GetSection("AzureAd"));
services.AddAuthorization(options =>
{
options.AddPolicy("Hangfire", builder =>
{
builder
.AddAuthenticationSchemes(OpenIdConnectDefaults.AuthenticationScheme)
.RequireAuthenticatedUser();
});
});
services.AddHangfire(x =>
{
x.UseSqlServerStorage(connectionString);
x.UseConsole();
});
services.AddHangfireServer();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHangfireDashboard("/hangfire", new DashboardOptions()
{
Authorization = new List<IDashboardAuthorizationFilter> { new HangfireAuthorizeFilter() },
}).RequireAuthorization("Hangfire");
});
app.UseHangfireDashboard();
Authorization filter: public class HangfireAuthorizeFilter:
IDashboardAuthorizationFilter
{
public bool Authorize(DashboardContext context)
{
var userIdentity = context.GetHttpContext().User.Identity;
return userIdentity is { IsAuthenticated: true };
}
}
And the app registration from Azure AD:
Under your app registration click: Authentication -> Mark "ID tokens" and enter your redirect urls, like: https://localhost:52908/hangfire
Upvotes: 8