1+ import crypto from 'crypto'
12import type {
23 GoogleCodeSchema ,
34 RefreshTokenSchema ,
@@ -15,7 +16,7 @@ import { Conflict, Forbidden, Unauthorized } from 'http-errors'
1516import { jwtVerify , SignJWT } from 'jose'
1617import { JWTExpired } from 'jose/errors'
1718
18- import { env } from '@/config'
19+ import { env , redis } from '@/config'
1920
2021const {
2122 ACCESS_JWT_EXPIRES_IN ,
@@ -93,7 +94,12 @@ class AuthController {
9394 }
9495
9596 getGoogleRedirectUrl = async ( _ : Request , res : Response ) => {
97+ const state = crypto . randomBytes ( 32 ) . toString ( 'hex' )
98+
99+ await redis . set ( `oauth_state:${ state } ` , 'true' , 'EX' , 5 * 60 )
100+
96101 const url = this . googleClient . generateAuthUrl ( {
102+ state,
97103 access_type : 'offline' ,
98104 scope : [ 'profile' , 'email' ]
99105 } )
@@ -106,7 +112,17 @@ class AuthController {
106112 res : Response ,
107113 next : NextFunction
108114 ) => {
109- const { tokens } = await this . googleClient . getToken ( req . body . code )
115+ const { code, state : receivedState } = req . body
116+
117+ const redisStateKey = `oauth_state:${ receivedState } `
118+
119+ const storedState = await redis . get ( redisStateKey )
120+
121+ if ( storedState ) {
122+ await redis . del ( redisStateKey )
123+ }
124+
125+ const { tokens } = await this . googleClient . getToken ( code )
110126
111127 if ( ! tokens . id_token ) return next ( Forbidden ( ) )
112128
0 commit comments