@@ -39,23 +39,51 @@ export async function gscGoogleCallback(
3939 }
4040
4141 const { code, state } = query . data ;
42- const storedState = req . cookies . gsc_oauth_state ?? null ;
43- const codeVerifier = req . cookies . gsc_code_verifier ?? null ;
44- const projectId = req . cookies . gsc_project_id ?? null ;
45-
46- const hasStoredState = storedState !== null ;
47- const hasCodeVerifier = codeVerifier !== null ;
48- const hasProjectId = projectId !== null ;
49- const hasAllCookies = hasStoredState && hasCodeVerifier && hasProjectId ;
50- if ( ! hasAllCookies ) {
42+
43+ const rawStoredState = req . cookies . gsc_oauth_state ?? null ;
44+ const rawCodeVerifier = req . cookies . gsc_code_verifier ?? null ;
45+ const rawProjectId = req . cookies . gsc_project_id ?? null ;
46+
47+ const storedStateResult =
48+ rawStoredState !== null ? req . unsignCookie ( rawStoredState ) : null ;
49+ const codeVerifierResult =
50+ rawCodeVerifier !== null ? req . unsignCookie ( rawCodeVerifier ) : null ;
51+ const projectIdResult =
52+ rawProjectId !== null ? req . unsignCookie ( rawProjectId ) : null ;
53+
54+ if (
55+ ! (
56+ storedStateResult ?. value &&
57+ codeVerifierResult ?. value &&
58+ projectIdResult ?. value
59+ )
60+ ) {
5161 throw new LogError ( 'Missing GSC OAuth cookies' , {
52- storedState : ! hasStoredState ,
53- codeVerifier : ! hasCodeVerifier ,
54- projectId : ! hasProjectId ,
62+ storedState : ! storedStateResult ?. value ,
63+ codeVerifier : ! codeVerifierResult ?. value ,
64+ projectId : ! projectIdResult ?. value ,
65+ } ) ;
66+ }
67+
68+ if (
69+ ! (
70+ storedStateResult ?. valid &&
71+ codeVerifierResult ?. valid &&
72+ projectIdResult ?. valid
73+ )
74+ ) {
75+ throw new LogError ( 'Invalid GSC OAuth cookies' , {
76+ storedState : ! storedStateResult ?. value ,
77+ codeVerifier : ! codeVerifierResult ?. value ,
78+ projectId : ! projectIdResult ?. value ,
5579 } ) ;
5680 }
5781
58- if ( state !== storedState ) {
82+ const stateStr = storedStateResult ?. value ;
83+ const codeVerifierStr = codeVerifierResult ?. value ;
84+ const projectIdStr = projectIdResult ?. value ;
85+
86+ if ( state !== stateStr ) {
5987 throw new LogError ( 'GSC OAuth state mismatch' , {
6088 hasState : true ,
6189 hasStoredState : true ,
@@ -65,7 +93,7 @@ export async function gscGoogleCallback(
6593
6694 const tokens = await googleGsc . validateAuthorizationCode (
6795 code ,
68- codeVerifier
96+ codeVerifierStr
6997 ) ;
7098
7199 const accessToken = tokens . accessToken ( ) ;
@@ -79,18 +107,20 @@ export async function gscGoogleCallback(
79107 }
80108
81109 const project = await db . project . findUnique ( {
82- where : { id : projectId } ,
110+ where : { id : projectIdStr } ,
83111 select : { id : true , organizationId : true } ,
84112 } ) ;
85113
86114 if ( ! project ) {
87- throw new LogError ( 'Project not found for GSC connection' , { projectId } ) ;
115+ throw new LogError ( 'Project not found for GSC connection' , {
116+ projectId : projectIdStr ,
117+ } ) ;
88118 }
89119
90120 await db . gscConnection . upsert ( {
91- where : { projectId } ,
121+ where : { projectId : projectIdStr } ,
92122 create : {
93- projectId,
123+ projectId : projectIdStr ,
94124 accessToken : encrypt ( accessToken ) ,
95125 refreshToken : encrypt ( refreshToken ) ,
96126 accessTokenExpiresAt,
@@ -111,7 +141,7 @@ export async function gscGoogleCallback(
111141
112142 const dashboardUrl =
113143 process . env . DASHBOARD_URL || process . env . NEXT_PUBLIC_DASHBOARD_URL ! ;
114- const redirectUrl = `${ dashboardUrl } /${ project . organizationId } /${ projectId } /settings/gsc` ;
144+ const redirectUrl = `${ dashboardUrl } /${ project . organizationId } /${ projectIdStr } /settings/gsc` ;
115145 return reply . redirect ( redirectUrl ) ;
116146 } catch ( error ) {
117147 req . log . error ( error ) ;
0 commit comments