首页 > 解决方案 > 如何在 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 应该是这样的。

标签: asp.net-coreamazon-cognito

解决方案


我认为问题在于您为 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"
...

希望这会有所帮助。


推荐阅读