@@ -140,11 +140,43 @@ const asgardeoMiddleware = (
140140 return async ( request : NextRequest ) : Promise < NextResponse > => {
141141 const resolvedOptions = typeof options === 'function' ? options ( request ) : options || { } ;
142142
143+ const url : URL = new URL ( request . url ) ;
144+ const hasCallbackParams : boolean = url . searchParams . has ( 'code' ) && url . searchParams . has ( 'state' ) ;
145+
146+ let isValidOAuthCallback : boolean = false ;
147+ if ( hasCallbackParams ) {
148+ // OAuth callbacks should not contain error parameters that indicate failed auth
149+ const hasError : boolean = url . searchParams . has ( 'error' ) ;
150+
151+ if ( ! hasError ) {
152+ // Validate that there's a temporary session that initiated this OAuth flow
153+ const tempSessionToken : string | undefined = request . cookies . get (
154+ SessionManager . getTempSessionCookieName ( ) ,
155+ ) ?. value ;
156+ if ( tempSessionToken ) {
157+ try {
158+ // Verify the temporary session exists and is valid
159+ await SessionManager . verifyTempSession ( tempSessionToken ) ;
160+ isValidOAuthCallback = true ;
161+ } catch {
162+ // Invalid temp session - this is not a legitimate OAuth callback
163+ isValidOAuthCallback = false ;
164+ }
165+ }
166+ }
167+ }
168+
143169 const sessionId = await getSessionIdFromRequestMiddleware ( request ) ;
144170 const isAuthenticated = await hasValidSession ( request ) ;
145171
146172 const asgardeo : AsgardeoMiddlewareContext = {
147173 protectRoute : async ( options ?: { redirect ?: string } ) : Promise < NextResponse | void > => {
174+ // Skip protection if this is a validated OAuth callback - let the callback handler process it first
175+ // This prevents race conditions where middleware redirects before OAuth callback completes
176+ if ( isValidOAuthCallback ) {
177+ return ;
178+ }
179+
148180 if ( ! isAuthenticated ) {
149181 const referer = request . headers . get ( 'referer' ) ;
150182 // TODO: Make this configurable or call the signIn() from here.
0 commit comments