后端缓存已解码的身份验证令牌是不良实践或存在重大安全风险吗?
问题描述
我在NestJS服务器上搭建了可正常运行的Firebase Passport策略,但所有经过该策略的请求都会产生较长加载耗时,这一点我并不满意。因此我决定将已解码的令牌缓存至其过期,该改动大幅降低了有效未过期令牌的请求加载耗时。
但我担心这一操作可能存在相关安全风险。主要是因为这个优化实现起来非常简单,肯定之前就有人想到过。我认为Firebase SDK的开发人员肯定考虑过将其作为内置功能加入,那他们为什么没有这么做呢?
以下是我的Passport策略代码供参考:
@Injectable() export class FirebaseAuthStrategy extends PassportStrategy(Strategy, 'firebase-auth') { private defaultApp: any; constructor( private configService: ConfigService, @Inject(CACHE_MANAGER) private cacheManager: Cache ) { super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken() }); const config = this.configService.get<string>('FIREBASE_CONFIG'); if (!config) { throw new Error('FIREBASE_CONFIG not available. Please ensure the variable is supplied in the `.env` file.'); } const firebase_params = JSON.parse(config); this.defaultApp = firebase.initializeApp({ credential: firebase.credential.cert(firebase_params) }); } async validate(token: string) { const cachedFirebaseUser = await this.cacheManager.get(token); if (cachedFirebaseUser) return cachedFirebaseUser; const firebaseUser: any = await this.defaultApp .auth() .verifyIdToken(token, true) .catch((err) => { console.log(err); throw new UnauthorizedException(err.Message); }); if (!firebaseUser) { throw new UnauthorizedException(); } /** * input parameter for `Date` or `moment` constructor is in milliseconds for unix timestamps. * input * 1000 will instantiate correct Date or moment value. */ const exp = moment(+firebaseUser['exp'] * 1000); const now = moment.now(); const ttl = exp.diff(now, 'seconds'); await this.cacheManager.set(token, firebaseUser, { ttl }); return firebaseUser; } }
解答
现有缓存方案的核心安全隐患
- 令牌吊销机制失效:你调用
verifyIdToken时传入的第二个参数true就是开启令牌吊销状态检查的配置,默认每次校验都会请求Firebase官方服务确认令牌是否被用户主动登出、管理员禁用或因风险操作被吊销。缓存方案会直接跳过该检查,已失效的令牌在原本的过期时间到达前仍可正常访问你的服务,是最主要的安全风险。 - 缓存数据泄露风险:如果使用Redis等分布式缓存存储令牌与用户信息,一旦缓存服务被攻破,大量有效的用户身份数据会直接泄露,攻击者可利用泄露的令牌伪造身份访问接口。
- 时间同步误差风险:你自行计算TTL依赖的是本地服务器时间,若本地时间与Firebase官方服务器时间不同步,可能出现令牌已官方过期但缓存仍未清理、或是缓存提前失效的异常问题。
为什么Firebase SDK不内置该缓存功能
- 安全优先的默认设计:Firebase服务面向全场景的开发者,默认要保证最高等级的身份校验可靠性,不能为了性能默认牺牲安全校验的完整性,因此将是否要做性能妥协的选择权交给开发者自行判断。
- 缓存方案的场景差异极大:不同业务的缓存基础设施(本地内存/分布式缓存)、可接受的风险窗口、过期策略都完全不同,官方无法提供适配所有场景的通用缓存实现。
优化建议
如果你的业务对性能要求远高于令牌即时吊销的需求,可保留现有方案,建议额外添加缓存最大TTL限制,比如无论令牌剩余有效期多久,缓存最长仅留存5~10分钟,大幅缩小风险窗口。如果需要兼顾安全和性能,可接入Firebase的身份事件回调,在收到令牌吊销、账号禁用事件时主动清理对应缓存。
内容的提问来源于stack exchange,提问作者H.Rahimy
相关产品推荐
相关产品推荐

