.NET OpenIdConnectHandler - message.State 为 null 或为空

问题描述 投票:0回答:1

我正在尝试在 .NET 8 Web API 中启用 OpenIdConnect 和 Cookie:

builder.Services
    .AddAuthentication(options =>
    {
        options.DefaultChallengeScheme = "MyPolicy";
        options.DefaultAuthenticateScheme = "MyPolicy";
    })
    .AddCookie(options =>
    {
        // add an instance of the patched manager to the options:
        options.CookieManager = new ChunkingCookieManager();
        options.Cookie.HttpOnly = true;
        options.Cookie.SameSite = SameSiteMode.None;
        options.Cookie.SecurePolicy = CookieSecurePolicy.None;
    })
    .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
    {
        options.Authority = "";
        options.ClientId = "";
        options.ClientSecret = "";
        options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.ResponseType = "code";
        options.Prompt = "login";
        options.GetClaimsFromUserInfoEndpoint = true;
        options.SaveTokens = true;
        options.RequireHttpsMetadata = false;
    })
    .AddJwtBearer(options =>
    {
        // some configuration
    })
    .AddPolicyScheme("MyPolicy", "My test Policy", options =>
    {
        options.ForwardDefaultSelector = context =>
        {
            // Decide which Authentication schema to use for each request
            string authorization = context.Request.Headers[HeaderNames.Authorization];
            if (authorization != null && authorization.StartsWith("Bearer", StringComparison.OrdinalIgnoreCase))
            {
                return BearerAuthenticationSchemeName;
            }

            if (context.Request.Path.StartsWithSegments("/swagger"))
            {
                return OpenIdConnectDefaults.AuthenticationScheme;
            }

            return CookieAuthenticationDefaults.AuthenticationScheme;
        };
    });

var app = builder.Build();
app.UseCookiePolicy(new CookiePolicyOptions
{
    MinimumSameSitePolicy = SameSiteMode.None,
    Secure = CookieSecurePolicy.Always,
});
app.UseAuthentication();
app.UseAuthorization();
app.UseSwagger();
app.UseSwaggerUI();
// more middleware

当我打开

/swagger
端点时,它会将我重定向到登录页面。我成功登录,然后将我重定向到
/signin-oidc
,这是预期的。然而,
OpenIdConnectAuthenticationHandler
抛出了一个异常,指出
message.State is null or empty

System.Exception: An error was encountered while handling the remote login.
 ---> System.Exception: OpenIdConnectAuthenticationHandler: message.State is null or empty.
   --- End of inner exception stack trace ---
   at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.HandleRequestAsync()
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at MyApp.Middlewares.LoggingMiddleware.InvokeAsync(HttpContext httpContext)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

当我在本地运行它时(例如在

http://localhost:5000/swagger
上),它工作得很好,但是当我在
https://myexampleurl.whatever/swagger/
上打开它时,我得到了异常。我不知道为什么这不起作用,也不知道我在这里做错了什么。我看到 cookie 是以以下格式发送的:
.AspNetCore.OpenIdConnect.Nonce.<somehugestring>; .AspNetCore.Correlation.<correlation>; <anotherbigstring>
,值得注意的是
Authority
和我的
myexampleurl
是不同的域。

还值得注意的是,当我在本地运行此程序并重定向到

/signin-oidc
时,浏览器确实会发送 4 个 cookie:2 个
AspNetCore.Correlation
和 2 个
AspNetCore.OpenIdConnect.Nonce
cookie,它们都具有不同的值。对于另一个,它根本不发送任何 cookie。

c# asp.net-core cookies openid-connect .net-8.0
1个回答
0
投票

首先是我的 cookie 策略设置。当在

SameSite
中间件中将
None
属性设置为
app.UseCookiePolicy()
时,必须将 cookie 标记为安全(
CookieSecurePolicy.Always
),否则浏览器将不会在后续请求中存储或发送它,这会导致
HTTP 500
就我而言。然而,即使在引入了上述更改之后,我仍然遇到了麻烦。因此,在深入挖掘之后,我在 Auth0 上发现了一篇题为“ASP.NET Core 错误重定向 url”的论坛帖子,该帖子内部链接/导致 StackOverflow 上的另一篇帖子“AspNetCore Azure AD Connect 回调 URL 是 http,而不是 https” ”。最终,答案建议在应用程序的中间件中调用
app.UseForwardedHeaders()
之前添加
app.UseAuthentication()
。这样做之后(基本上遵循与帖子答案相同的逻辑),一切都开始正常工作。

所以,在一切都改变之后,这就是我的

Program.cs

builder.Services.AddAuthentication().AddCookie(options =>
{
    options.Cookie.HttpOnly = true;
    options.Cookie.SameSite = SameSiteMode.None;
    options.Cookie.SecurePolicy = CookieSecurePolicy.None;
}).AddOpenIdConnect(...).AddJwtBearer(...).AddPolicyScheme(...);

var app = builder.Build();

ForwardedHeadersOptions forwardedHeadersOptions = new()
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
};
forwardedHeadersOptions.KnownNetworks.Clear();
forwardedHeadersOptions.KnownProxies.Clear();

app.UseCookiePolicy(new CookiePolicyOptions
{
    MinimumSameSitePolicy = SameSiteMode.None,
    Secure = CookieSecurePolicy.Always,
});
app.UseForwardedHeaders(forwardedHeadersOptions);
app.UseAuthentication();
app.UseAuthorization();
app.UseSwagger();
app.UseSwaggerUI();
// more middleware
© www.soinside.com 2019 - 2024. All rights reserved.