You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cognito:pre_authentication触发器中使用admin_user_global_sign_out因异步特性偶发失败

关于Cognito全局注销与登录会话冲突的问题

问题背景

我需要实现:用户用同一邮箱+密码启动新会话时,注销该用户在Cognito的所有旧会话(吊销刷新令牌),避免同一账号多端同时登录。注:我知道旧会话的ID和访问令牌在过期前仍能使用。

我采用的方案是通过Cognito的pre-authentication Lambda触发,测试代码如下:

import json
import boto3
from time import sleep

client = boto3.client('cognito-idp')


def lambda_handler(event, context):
    user_pool_id = event['userPoolId']
    email = event['request']['userAttributes']['email']
    # 注销所有当前活跃会话,只保留本次创建的会话
    client.admin_user_global_sign_out(
        Username=email,
        UserPoolId=user_pool_id)
    sleep(1)
    return event

最初没加sleep(1)时,授权操作偶发失败。我猜测admin_user_global_sign_out是异步操作,可能出现旧会话注销延迟,导致新会话创建后才执行注销,最终所有会话(包括新的)都被吊销。加了1秒休眠后,登录失败次数大幅减少,但担心分布式系统延迟超过1秒时问题复现。

我的问题:

  1. admin_user_global_sign_out是否为异步操作?我的假设是否正确?
  2. 能否让该全局注销操作同步?比如通过调用Cognito API等待状态变更?

解答

1. admin_user_global_sign_out的异步属性

你的假设完全正确,admin_user_global_sign_out是异步操作。AWS官方文档明确说明,这个API调用会立即返回成功响应,但实际的会话吊销逻辑是在后台异步执行的,不会等待所有会话处理完成再返回结果。这就是为什么不加休眠时会偶发新会话被误吊销的原因——新会话的创建流程可能比后台注销旧会话的速度更快,导致新生成的刷新令牌也被纳入了注销范围。

2. 实现可靠全局注销的替代方案

目前Cognito没有提供直接等待admin_user_global_sign_out执行完成的API,但可以通过以下两种方式规避异步延迟带来的问题:

  • 改用admin_revoke_token配合会话追踪:
    如果你的系统可以追踪用户当前有效的刷新令牌(比如将令牌存储在数据库或缓存中),可以在pre-authentication触发时,调用admin_revoke_token逐个吊销已知的旧令牌。这个API是同步执行的,调用成功后对应的令牌立即失效,不会有延迟问题。但这种方案需要额外维护用户的令牌列表,增加了系统复杂度。

  • 调整Lambda触发时机,避免新会话被误杀:
    不需要依赖固定时长的sleep,可以在pre-authentication阶段先执行全局注销,然后在post-authentication触发的Lambda中,验证当前新生成的会话是否有效。如果发现新会话被误吊销,可以重新生成令牌(不过这种方式需要额外处理令牌生成逻辑,实现起来比较复杂)。

另外,还可以利用Cognito的Device Tracking功能,强制用户每次登录都使用新设备,同时在pre-authentication阶段注销所有旧设备。不过这需要开启用户池的设备跟踪配置,且同样依赖异步操作,但可以通过设备ID来更精准地控制会话。


内容的提问来源于stack exchange,提问作者João Pedro Schmitt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 13:35:22