asp.net-core - 如何在 ASP.NET Core 中从 AWS Cognito 注销
问题描述
我正在尝试在 ASP.NET Core 5 Web 应用程序中使用 AWS Cognito 实施身份验证。
我可以通过身份验证,但现在我想实现注销功能。
我可以让注销工作,因为 ASP.NET 认为我没有经过身份验证。
在我的 Startup.cs 中,我有:
options.SignedOutRedirectUri = Configuration["Authentication:Cognito:SignedOutRedirectUri"];
options.Events = new OpenIdConnectEvents()
{
OnRedirectToIdentityProviderForSignOut = context =>
{
var logoutUri = options.SignedOutRedirectUri;
context.Response.Redirect(logoutUri);
context.HandleResponse();
return Task.CompletedTask;
}
};
在我的 appsettings.json 我有:
"SignedOutRedirectUri": "https://mydomain.auth.us-east-2.amazoncognito.com/logout?client_id=<<clientid>>&response_type=code&redirect_uri=https://localhost:44306/Home/LoggedOut"
在我的注销控制器中,我有:
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);
return Redirect("/Home/LoggedOut");
因此,当我单击注销链接时,我被重定向到 /Home/LoggedOut 并且不再经过身份验证(在那个 User.Identity.IsAuthenticated = false 中)。
但是,当我转到任何带有 [Authorize] 的页面时,它会自动将我重新验证给我登录时使用的同一用户 - 它永远不会让我有机会以其他用户身份登录。我希望它带我进入 Cognito 登录对话框并要求我再次进行身份验证。因此,我想在 AWS Cognito 方面,某些地方似乎没有得到清除。
为什么这不让我回到登录对话框重新进行身份验证?我认为对 AWS /logout 端点的 GET 应该是这样的。
解决方案
我认为问题在于您为 AWS Logout 端点构建的 URL 的参数。(你还没有设置 logout_uri)
https://docs.aws.amazon.com/cognito/latest/developerguide/logout-endpoint.html示例 1 显示了注销和重定向回客户端所需的参数。
这是我的做法。
options.Events = new OpenIdConnectEvents()
{
OnRedirectToIdentityProviderForSignOut = context =>
{
context.ProtocolMessage.IssuerAddress =
GetAbsoluteUri(Configuration["Authentication:Cognito:EndSessionEndPoint"], Configuration["Authentication:Cognito:Authority"]);
context.ProtocolMessage.SetParameter("client_id", Configuration["Authentication:Cognito:ClientId"]);
context.ProtocolMessage.SetParameter("logout_uri", "https://localhost:5001");
return Task.CompletedTask;
}
};
logout_uri 必须与 AWS 应用程序客户端设置中配置的注销 url 完全匹配。
辅助方法
private string GetAbsoluteUri(string signoutUri, string authority)
{
var signOutUri = new Uri(signoutUri, UriKind.RelativeOrAbsolute);
var authorityUri = new Uri(authority, UriKind.Absolute);
var uri = signOutUri.IsAbsoluteUri ? signOutUri : new Uri(authorityUri, signOutUri);
return uri.AbsoluteUri;
}
注销是通过以下两行完成的。如您所见,第一行是通过清除本地身份验证 cookie 在本地注销您,第二行通常会调用您的 IDP 上的 end_session 端点以注销您的 IDP,但是由于 cognito 没有并且end_session 端点,当您通过 OnRedirectToIdentityProviderForSignOut 事件配置中间件时,您会覆盖它,指示它改为调用 cognito 确实具有的注销端点,这就是使用此 URL 的地方。由于您没有正确构建它,因此它永远不会退出 cognito。
public async Task Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);
}
和配置值
...
"EndSessionEndPoint": "logout",
"ClientId": "<your client id>",
"Authority": "https://<your domain>.auth.<your region>.amazoncognito.com"
...
希望这会有所帮助。
推荐阅读
- php - 如何在 PHP 的关联数组中使用复杂对象作为键?
- javascript - 在 slickgrid 上混合可点击行和不可点击行
- c++ - 关于静态全局 lambda 变量的错误警告?
- spring - 将 apache tomcat 服务器从 7.0 升级到 8.5.5 时出错,请检查您是否有多个 ContextLoader*
- javascript - 带有音色控制的 JS 音高变换
- java - 如何为标准对话框 PreferenceFragmentCompat 设置可取消(假)
- spring-boot - Spring Cloud Stream 2.0 和 startOffset 最新
- weather - aeris 天气框架中的温度模块
- use-case - 用例 Plantuml - 垂直堆叠组件
- typescript - 如何在打字稿中使用带有矩阵参数的svg.js转换?