切换至Cognito后,用Identity Token做REST API授权是否存重大安全风险?
直接把ID Token用作Bearer令牌,或者通过自定义HTTP Header传递它来做API授权,确实存在几个关键的安全风险:
混淆令牌用途,违反规范设计
OAuth 2.0和OpenID Connect的核心逻辑里,ID Token是给客户端用来验证用户身份、获取用户基本信息的,而Access Token才是专门给后端API做授权凭证用的。混用这两种令牌的职责,会打破规范的安全边界,后续维护或扩展系统时很容易出现逻辑混乱,甚至引入意想不到的漏洞。受众校验逻辑不匹配API场景
ID Token的aud(受众)声明指向的是你的客户端应用(比如移动端、Web应用),而非后端API。如果后端用ID Token做授权,要么跳过aud校验——这会导致任何拿到这个令牌的非法客户端都能访问你的API;要么把API加入aud列表,但Cognito默认不会这么配置,强行修改会增加复杂度,还可能让其他客户端的ID Token也能访问你的API,扩大攻击面。缺乏细粒度权限控制能力
Access Token可以携带scope或自定义权限声明,用来控制用户对API的具体操作(比如只读、修改数据)。但ID Token里只有用户身份相关的信息(比如用户ID、邮箱),根本没设计用来承载权限信息。用它做授权的话,后端只能验证用户是谁,没法限制用户能做什么操作,权限控制会变得非常薄弱。令牌泄露后的危害被放大
ID Token包含完整的用户身份信息,一旦泄露,攻击者不仅能冒充用户访问API,还能拿到用户的敏感个人数据;而Access Token通常是不透明的(或只含必要权限信息),泄露后的危害相对可控。把ID Token用作授权凭证,相当于把用户身份信息和授权权限绑定在一起,大大增加了泄露后的影响范围。
更合规的替代方案
通过Lambda触发器给Access Token加自定义声明
其实Cognito支持在Access Token中注入自定义信息,你可以配置Pre Token Generation Lambda触发器,在生成Access Token时把用户的自定义属性或权限信息加进去。这样后端直接解析Access Token就能拿到所需的用户信息,完全符合OAuth规范,也不需要强制使用Hosted UI——只要客户端请求令牌时带上必要的scope即可。用Cognito自定义授权器处理用户信息
如果后端部署在AWS生态(比如API Gateway),可以配置自定义授权器:后端收到Access Token后,调用Cognito的验证接口,同时从用户池拉取用户的自定义属性,再把这些信息注入请求上下文供API使用。这样既不用传递ID Token,也能获取到用户的自定义信息。移动端和遗留Web适配openid scope
不是只有Hosted UI才能拿到openid scope。移动端可以用Cognito SDK发起OAuth授权请求(比如Authorization Code Flow with PKCE),带上openidscope就能同时拿到Access Token和ID Token——后端用Access Token做授权,ID Token存在客户端用来获取用户信息就行,不用传给后端。遗留Web应用如果是自定义登录页,也可以手动构造Cognito的OAuth请求,带上openid scope,同样能拿到两种令牌。
内容的提问来源于stack exchange,提问作者Dogukan Zengin

