1
- import jwt from "jsonwebtoken" ;
1
+ import jwt , { decode } from "jsonwebtoken" ;
2
2
import { jwtConfig } from "../config/authConfig.js" ;
3
3
import { v4 as uuidv4 } from "uuid" ;
4
4
import redisService from "./redisService.js" ;
@@ -14,11 +14,6 @@ class TokenService {
14
14
return accessToken ;
15
15
}
16
16
17
- static generateEmailToken ( email ) {
18
- const emailToken = jwt . sign ( { email, jti : uuidv4 ( ) } , jwtConfig . accessTokenSecret , { expiresIn : "5m" } ) ; // TODO: change
19
- return emailToken ;
20
- }
21
-
22
17
static generateRefreshToken ( user ) {
23
18
const refreshToken = jwt . sign (
24
19
{ id : user . id , jti : uuidv4 ( ) } ,
@@ -28,6 +23,13 @@ class TokenService {
28
23
return refreshToken ;
29
24
}
30
25
26
+ static async generateResetToken ( email ) {
27
+ const jti = uuidv4 ( ) ;
28
+ const resetToken = jwt . sign ( { email, jti } , jwtConfig . resetTokenSecret , jwtConfig . resetTokenOptions ) ;
29
+ await redisService . setKeyWithExpiration ( this . generateResetTokenKey ( email ) , jti , 900 ) ;
30
+ return resetToken ;
31
+ }
32
+
31
33
static async verifyToken ( token , secret ) {
32
34
return new Promise ( ( resolve , reject ) => {
33
35
jwt . verify ( token , secret , ( err , decoded ) => {
@@ -39,26 +41,60 @@ class TokenService {
39
41
} ) ;
40
42
}
41
43
42
- static async blacklistToken ( decodedRefreshToken ) {
44
+ static async verifyResetToken ( token ) {
45
+ const decoded = await this . verifyToken ( token , jwtConfig . resetTokenSecret ) ;
46
+ const { email, jti } = decoded ;
47
+ const expectedResetToken = await redisService . get ( this . generateResetTokenKey ( email ) ) ;
48
+ if ( expectedResetToken !== jti ) {
49
+ throw new UnauthorisedError ( "Reset token is invalid or has expired" ) ;
50
+ }
51
+ return decoded ;
52
+ }
53
+
54
+ static async blacklistRefreshToken ( decodedRefreshToken ) {
43
55
const { id, jti, exp } = decodedRefreshToken ;
56
+ const blacklistTokenKey = this . generateBlacklistedRefreshTokenKey ( id , jti ) ;
57
+ this . blacklistToken ( exp , blacklistTokenKey ) ;
58
+ }
59
+
60
+ static async blacklistResetToken ( decodedResetToken ) {
61
+ const { email, jti, exp } = decodedResetToken ;
62
+ const blacklistTokenKey = this . generateBlacklistedResetTokenKey ( email , jti ) ;
63
+ this . blacklistToken ( exp , blacklistTokenKey ) ;
64
+ }
65
+
66
+ static async blacklistToken ( exp , key ) {
44
67
const currentTime = Math . floor ( Date . now ( ) / 1000 ) ;
45
68
const remainingTime = exp - currentTime ;
46
- const blacklistTokenKey = this . generateBlacklistedTokenKey ( id , jti ) ;
47
69
if ( remainingTime > 0 ) {
48
- await redisService . setKeyWithExpiration ( blacklistTokenKey , "blacklisted" , remainingTime ) ;
49
- console . log ( `Blacklisted token: ${ jti } ` ) ;
70
+ await redisService . setKeyWithExpiration ( key , "blacklisted" , remainingTime ) ;
71
+ console . log ( `Blacklisted token: ${ key } ` ) ;
50
72
}
51
73
}
52
74
53
75
static async isRefreshTokenBlacklisted ( decodedRefreshToken ) {
54
76
const { id, jti } = decodedRefreshToken ;
55
- const blacklistTokenKey = this . generateBlacklistedTokenKey ( id , jti ) ;
77
+ const blacklistTokenKey = this . generateBlacklistedRefreshTokenKey ( id , jti ) ;
78
+ return await redisService . exists ( blacklistTokenKey ) ;
79
+ }
80
+
81
+ static async isResetTokenBlacklisted ( decodedResetToken ) {
82
+ const { email, jti } = decodedResetToken ;
83
+ const blacklistTokenKey = this . generateBlacklistedResetTokenKey ( email , jti ) ;
56
84
return await redisService . exists ( blacklistTokenKey ) ;
57
85
}
58
86
59
- static generateBlacklistedTokenKey ( userId , jti ) {
87
+ static generateBlacklistedRefreshTokenKey ( userId , jti ) {
60
88
return `${ userId } :${ jti } ` ;
61
89
}
90
+
91
+ static generateBlacklistedResetTokenKey ( email , jti ) {
92
+ return `${ email } :${ jti } ` ;
93
+ }
94
+
95
+ static generateResetTokenKey ( email ) {
96
+ return `resetToken:${ email } ` ;
97
+ }
62
98
}
63
99
64
100
export default TokenService ;
0 commit comments