【问题标题】:ASP.NET Core 3.1 OpenIDConnect message.state is nullASP.NET Core 3.1 OpenIDConnect message.state 为空
【发布时间】:2021-04-14 13:54:57
【问题描述】:

因此,我目前正在尝试在我已启动的 OIDC 客户端应用程序中测试 response_type=token 的 oidc 隐式流。

我可以通过 /authorize 向我的 OIDC 提供商提出的请求。但是,当响应返回到客户端中的 signin-oidc redirect_uri 时,我收到以下错误:

Exception: OpenIdConnectAuthenticationHandler: message.State is null or empty.
Unknown location

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

这是对我的授权端点的请求的样子:

GET https://localhost:44303/oauth/oidctest/authorize?client_id=...

然后我被重定向到我的 OIDC 提供商的 /authorizelogin 端点以接受应用程序。请求如下所示:

POST https://localhost:44303/oauth/oidctest/authorizelogin HTTP/1.1

这会返回一个如下所示的 302 重定向 URL:

https://localhost:5001/signin-oidc#token_type=bearer&access_token=<access-token>&scope=openid%20profile%20address%20phone%20email&expires_in=120&state=CfDJ....JDER

如您所见,每个请求都有状态。所以我不确定发生了什么。

这是我的 OIDC 中间件设置在我的 ASP.NET Core 客户端应用程序的Startup.cs 中的样子:

.AddOpenIdConnect(options =>
            {
                options.Authority = Configuration["auth:oidc:authority"];
                options.ClientId = Configuration["auth:oidc:clientid"];
                options.ClientSecret = Configuration["auth:oidc:clientsecret"];      
                options.ResponseType = OpenIdConnectResponseType.Token;
                options.GetClaimsFromUserInfoEndpoint = true;
                options.SaveTokens = true;
                options.UseTokenLifetime = true;
                options.Scope.Add("address");
                options.Scope.Add("phone");
                options.Scope.Add("email");
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidIssuer = Configuration["auth:oidc:authority"],
                    ValidAudience = Configuration["auth:oidc:clientid"],
                    ValidateIssuerSigningKey = true,
                    ClockSkew = TimeSpan.FromSeconds(3)
                };
            });

我是否需要在中间件的某处设置此状态(尽管它看起来像是自动设置的)?

【问题讨论】:

    标签: c# asp.net-core oauth-2.0 openid-connect


    【解决方案1】:

    如您所见,每个请求都有状态。所以我不确定发生了什么。

    这有点复杂:如果您仔细观察,您会发现状态(以及其余的授权响应参数)实际上是 URL 片段的一部分,浏览器永远不会将其发送到远程服务器他们与之交流。这就是为什么你会收到一个错误,说状态为空:服务器从未收到它。

    在您的情况下,您所针对的授权服务器似乎不支持response_mode=form_post,并在 URL 片段中返回授权响应,这是隐式流 (response_type=token) 的本机响应模式。

    还值得注意的是,OIDC 客户端中间件永远不会与 response_type=token 一起使用,因为此流程中没有身份令牌。

    请考虑使用response_type=code(授权代码流)。

    【讨论】:

    • 好吧,那是有道理的。但是,如果它不兼容,他们为什么要提供它作为一个选项呢?你怎么知道它不兼容?我知道代码流是最好的,但我试图理解所有的流,我真的很想测试令牌。是否可以使用任何 ASP.NET 库来做到这一点?那么这是否意味着对于 response_type=token 或 response_type=id_token 令牌, response_mode=fragment 是必需的?
    • 仅仅因为客户端(在本例中为 OIDC 中间件)发送 response_mode=form_post 并不意味着服务器必须支持它。 response_mode=form_post 支持是可选的,并在 openid.net/specs/oauth-v2-form-post-response-mode-1_0.html 中定义。您的屏幕截图表明已发送response_mode=form_post,因此如果您收到片段响应,则可能意味着服务器根本不支持它(否则,它将拒绝处理请求并告诉您客户端不能使用它模式)。
    • 关于您的最后一个问题:您只能使用response=form_postresponse_mode=fragment 从授权端点返回访问或身份令牌:response_mode=query 被明确禁止。阅读openid.net/specs/… 了解更多信息。所以不,如果服务器不支持response_mode=form_post,你不能在服务器应用程序中使用response_type=token
    • 谢谢。但是,我怎么知道我的回复是否是一个片段?我知道我的 OIDC 提供商支持 form_post,因为我正在协助开发它,并且我能够使用此客户端将它与代码 response_type 一起使用。
    • 如果参数位于 # 之后(也就是 URL 片段),则为片段响应。
    猜你喜欢
    • 1970-01-01
    • 2020-09-22
    • 2022-08-16
    • 2017-05-13
    • 2021-02-26
    • 1970-01-01
    • 2016-10-09
    • 1970-01-01
    • 2020-09-23
    相关资源
    最近更新 更多