ASP.NET 核心 Microsoft 身份注销 "The scheme field is required."
ASP.NET Core Microsoft Identity sign out "The scheme field is required."
我正在使用 ASP.NET Core 5 和 Azure AD 身份验证。
我创建了一个新的模板 Web 应用程序并使用 Azure AD 登录和注销,效果很好。
但是,当我将 Startup.cs
和 appsettings.json
中的相关代码从模板 Web 应用程序复制到另一个 Web 应用程序时,单击“注销”时收到 400 错误响应 link 到 /MicrosoftIdentity/Account/SignOut
["The scheme field is required."]
在 Startup.cs
中,我添加了:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"));
和
services.AddRazorPages()
.AddMicrosoftIdentityUI();
我比较了模板 Web 应用程序中有效的请求和其他无效的 Web 应用程序中的请求,我看不出请求 headers 与 /MicrosoftIdentity/Account/SignOut 有任何区别.
我错过了什么“方案”?
我查看了 Microsoft.Identity.Web
的源代码(see here) and MVC, and I think the only reasonable explanation is that you have the nullable reference types 在您的第二个项目中启用了 C# 8 功能。
启用 nullable 后我能够重现错误。
发生的事情是 SignOut
操作具有以下属性和签名:
// From Microsoft.Identity.Web.UI/AccountController.cs
// See: https://github.com/AzureAD/microsoft-identity-web/blob/master/src/Microsoft.Identity.Web.UI/Areas/MicrosoftIdentity/Controllers/AccountController.cs
/// <summary>
/// Handles the user sign-out.
/// </summary>
/// <param name="scheme">Authentication scheme.</param>
/// <returns>Sign out result.</returns>
[HttpGet("{scheme?}")]
public IActionResult SignOut([FromRoute] string scheme)
{
...
}
启用可空值后,这会产生您观察到的错误,因为方法签名中的 scheme
不再是可选的。该问题类似于 this GitHub issue.
我怀疑虽然在 2020 年向 ASP.NET 核心和(我想)它的大部分组件添加了可空支持,但 Microsoft.Identity.Web
没有得到相同的处理(它实际上完全独立于ASP.NET 核心;它是 AzureAD 的一部分。
也许更有趣的是,为什么其他帐户操作(具有相似的签名)不会导致相同的错误。我既不使用可空值,也不使用 Microsoft.Identity.Web,所以我没有与此相关的信息。
当然,如果我错了请告诉我,而且您没有启用可空值。 :)
在 @Leaky 关于查看 Microsoft.Identity.Web
SignOut()
source code 的指针之后,我更改了 Sign Out URL 结构以明确包含 scheme
参数像这样:
@if (User.Identity.IsAuthenticated)
{
var parms = new Dictionary<string, string>
{
{ "scheme", OpenIdConnectDefaults.AuthenticationScheme }
};
<a asp-area="MicrosoftIdentity" asp-controller="Account" asp-action="SignOut"
asp-all-route-data="parms">
Sign out
</a>
}
现在,当我将鼠标悬停在 link 上时,而不是:
https://localhost:44350/MicrosoftIdentity/Account/SignOut
注销 link 看起来像这样:
https://localhost:44350/MicrosoftIdentity/Account/SignOut/OpenIdConnect
并且完全注销没有错误。
我正在使用 ASP.NET Core 5 和 Azure AD 身份验证。
我创建了一个新的模板 Web 应用程序并使用 Azure AD 登录和注销,效果很好。
但是,当我将 Startup.cs
和 appsettings.json
中的相关代码从模板 Web 应用程序复制到另一个 Web 应用程序时,单击“注销”时收到 400 错误响应 link 到 /MicrosoftIdentity/Account/SignOut
["The scheme field is required."]
在 Startup.cs
中,我添加了:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"));
和
services.AddRazorPages()
.AddMicrosoftIdentityUI();
我比较了模板 Web 应用程序中有效的请求和其他无效的 Web 应用程序中的请求,我看不出请求 headers 与 /MicrosoftIdentity/Account/SignOut 有任何区别.
我错过了什么“方案”?
我查看了 Microsoft.Identity.Web
的源代码(see here) and MVC, and I think the only reasonable explanation is that you have the nullable reference types 在您的第二个项目中启用了 C# 8 功能。
启用 nullable 后我能够重现错误。
发生的事情是 SignOut
操作具有以下属性和签名:
// From Microsoft.Identity.Web.UI/AccountController.cs
// See: https://github.com/AzureAD/microsoft-identity-web/blob/master/src/Microsoft.Identity.Web.UI/Areas/MicrosoftIdentity/Controllers/AccountController.cs
/// <summary>
/// Handles the user sign-out.
/// </summary>
/// <param name="scheme">Authentication scheme.</param>
/// <returns>Sign out result.</returns>
[HttpGet("{scheme?}")]
public IActionResult SignOut([FromRoute] string scheme)
{
...
}
启用可空值后,这会产生您观察到的错误,因为方法签名中的 scheme
不再是可选的。该问题类似于 this GitHub issue.
我怀疑虽然在 2020 年向 ASP.NET 核心和(我想)它的大部分组件添加了可空支持,但 Microsoft.Identity.Web
没有得到相同的处理(它实际上完全独立于ASP.NET 核心;它是 AzureAD 的一部分。
也许更有趣的是,为什么其他帐户操作(具有相似的签名)不会导致相同的错误。我既不使用可空值,也不使用 Microsoft.Identity.Web,所以我没有与此相关的信息。
当然,如果我错了请告诉我,而且您没有启用可空值。 :)
在 @Leaky 关于查看 Microsoft.Identity.Web
SignOut()
source code 的指针之后,我更改了 Sign Out URL 结构以明确包含 scheme
参数像这样:
@if (User.Identity.IsAuthenticated)
{
var parms = new Dictionary<string, string>
{
{ "scheme", OpenIdConnectDefaults.AuthenticationScheme }
};
<a asp-area="MicrosoftIdentity" asp-controller="Account" asp-action="SignOut"
asp-all-route-data="parms">
Sign out
</a>
}
现在,当我将鼠标悬停在 link 上时,而不是:
https://localhost:44350/MicrosoftIdentity/Account/SignOut
注销 link 看起来像这样:
https://localhost:44350/MicrosoftIdentity/Account/SignOut/OpenIdConnect
并且完全注销没有错误。