在我的后端缓存解码的授权令牌是不好的做法还是主要的安全风险?
Is it bad practice or major security risk to cache decoded auth tokens in my backend?
我已经在 NestJS 服务器上设置了一个 firebase 通行证策略,它工作正常,但我不喜欢它会导致所有通过它的请求的加载时间过长。所以我决定缓存解码令牌直到它们过期,这大大减少了有效和未过期令牌的加载时间。
但是,我担心这可能会带来安全风险。主要是因为这对我来说似乎是一个简单的添加,之前一定有人考虑过。我假设制作 firebase sdk 的人一定考虑过将其添加为一项功能,但为什么不呢?
作为参考,这是我的护照策略代码:
@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.
* See here for reference:
*/
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;
}
}
只要您在令牌过期后不使用解码作为授权信号,缓存解码令牌是绝对安全的。缓存 ID 令牌是一种有效的方法,可以避免在每次调用时都必须对其进行解码。
我已经在 NestJS 服务器上设置了一个 firebase 通行证策略,它工作正常,但我不喜欢它会导致所有通过它的请求的加载时间过长。所以我决定缓存解码令牌直到它们过期,这大大减少了有效和未过期令牌的加载时间。
但是,我担心这可能会带来安全风险。主要是因为这对我来说似乎是一个简单的添加,之前一定有人考虑过。我假设制作 firebase sdk 的人一定考虑过将其添加为一项功能,但为什么不呢?
作为参考,这是我的护照策略代码:
@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.
* See here for reference:
*/
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;
}
}
只要您在令牌过期后不使用解码作为授权信号,缓存解码令牌是绝对安全的。缓存 ID 令牌是一种有效的方法,可以避免在每次调用时都必须对其进行解码。