问题
I'm in the process of implementing refresh tokens and I use passportjs. What I don't completely understand is where and how I should check access tokens for validity and in case if an invalid token arrives throw TokenExpiredException
.
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(
private readonly authService: AuthService,
) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: process.env.JWT_SECRET,
});
}
public async validate(payloadDto: PayloadDto): Promise<PayloadDto> {
const validUser = await this.authService.validateUser(payloadDto);
return { id: validUser.id, phone: validUser.phone };
}
}
The validateUser
method currently looks like this:
public async validateUser(payload: PayloadDto): Promise<UserEntity> {
const retrievedUser: UserEntity = await this.userService.retrieveOne(payload.phone);
if (retrievedUser) {
return retrievedUser;
} else {
throw new HttpException('Invalid User', HttpStatus.UNAUTHORIZED);
}
}
I'm wondering if it's secure to check it like this:
@Injectable()
export class RefreshAuthGuard extends AuthGuard('jwt') {
public handleRequest(err: any, user: any, info: Error): any {
if (info) {
if (info.name === 'TokenExpiredError') {
throw new HttpException('TokenExpired', HttpStatus.UNAUTHORIZED);
} else {
throw new HttpException('Unauthorized', HttpStatus.UNAUTHORIZED);
}
}
}
}
回答1:
I would suggest changing your auth flow as follows (also see thread and thread):
- The client tries to call the protected route
/secret
with an expired auth token - The server throws a
TokenExpiredError
to the client - The client now requests a new access token at the auth server with its valid refresh token
- The auth server checks the refresh token and issues a new access token to the client
- The client retries
/secret
with its new access token
The whole purpose of a refresh token is that it never gets shared with the resource server and is not send around with every request; this increases security. If the resource server makes the refresh request itself, you defeat this purpose. If the resource server and the auth server are the same, you still benefit from not sending the long-lived (➡ higher risk) tokens around so much, i.e., less chance for them to be compromised through a person-in-the-middle attack.
来源:https://stackoverflow.com/questions/61818520/where-and-how-should-i-check-an-access-token-for-validity-in-passportjs