11import axios , { AxiosInstance } from "axios" ;
22import { wrapper } from "axios-cookiejar-support" ;
33import { CookieJar } from "tough-cookie" ;
4- import fs from "fs" ;
5- import os from "os" ;
6- import path from "path" ;
7-
8- const logFile = path . join ( os . tmpdir ( ) , "plane-mcp-debug.log" ) ;
9- function debugLog ( message : string ) {
10- const timestamp = new Date ( ) . toISOString ( ) ;
11- const logMessage = `[${ timestamp } ] ${ message } \n` ;
12- try {
13- fs . appendFileSync ( logFile , logMessage ) ;
14- } catch ( error ) {
15- console . error ( `[AUTH] debugLog write failed: ${ error } ` ) ;
16- }
17- console . error ( message ) ;
18- }
4+ import { debugLog } from "./debug.js" ;
195
206/**
217 * Result of an authentication attempt
@@ -32,19 +18,19 @@ export interface AuthResult {
3218let axiosInstance : AxiosInstance | null = null ;
3319let isAuthenticated = false ;
3420
35- debugLog ( `[AUTH] Module loaded - PID: ${ process . pid } ` ) ;
21+ debugLog ( `[AUTH] Module loaded - PID: ${ process . pid } ` ) . catch ( ( ) => { } ) ;
3622
3723/**
3824 * Gets or creates an Axios instance with cookie jar support for session authentication
3925 * @returns Configured Axios instance with cookie persistence
4026 */
4127export function getAxiosInstance ( ) : AxiosInstance {
4228 if ( ! axiosInstance ) {
43- debugLog ( "[AUTH] Creating new axios instance with cookie jar" ) ;
29+ debugLog ( "[AUTH] Creating new axios instance with cookie jar" ) . catch ( ( ) => { } ) ;
4430 const jar = new CookieJar ( ) ;
4531 axiosInstance = wrapper ( axios . create ( { jar, withCredentials : true } ) ) ;
4632 } else {
47- debugLog ( "[AUTH] Reusing existing axios instance" ) ;
33+ debugLog ( "[AUTH] Reusing existing axios instance" ) . catch ( ( ) => { } ) ;
4834 }
4935 return axiosInstance ;
5036}
@@ -74,29 +60,29 @@ export async function authenticateWithPassword(
7460 const instance = getAxiosInstance ( ) ;
7561 const host = hostUrl . endsWith ( "/" ) ? hostUrl : `${ hostUrl } /` ;
7662
77- debugLog ( "[AUTH] Starting authentication flow..." ) ;
78- debugLog ( `[AUTH] Host URL: ${ host } ` ) ;
63+ await debugLog ( "[AUTH] Starting authentication flow..." ) ;
64+ await debugLog ( `[AUTH] Host URL: ${ host } ` ) ;
7965
8066 // Step 1: Get CSRF token (stored in cookie jar automatically)
8167 const csrfResponse = await instance . get ( `${ host } auth/get-csrf-token/` ) ;
82- debugLog ( `[AUTH] CSRF response status: ${ csrfResponse . status } ` ) ;
83- debugLog ( `[AUTH] CSRF response headers: ${ JSON . stringify ( csrfResponse . headers ) } ` ) ;
84- debugLog ( "[AUTH] CSRF token requested" ) ;
68+ await debugLog ( `[AUTH] CSRF response status: ${ csrfResponse . status } ` ) ;
69+ await debugLog ( `[AUTH] CSRF response headers: ${ JSON . stringify ( csrfResponse . headers ) } ` ) ;
70+ await debugLog ( "[AUTH] CSRF token requested" ) ;
8571
8672 // Step 2: Extract CSRF token from cookie jar for the request header
8773 const maybeJar = ( instance . defaults as Record < string , unknown > ) . jar ;
8874 if ( ! ( maybeJar instanceof CookieJar ) ) {
89- debugLog ( "[AUTH] ERROR: Cookie jar not found on axios instance" ) ;
75+ await debugLog ( "[AUTH] ERROR: Cookie jar not found on axios instance" ) ;
9076 return { success : false , error : "cookies" , message : "Cookie jar not available for session authentication" } ;
9177 }
9278 const jar = maybeJar ;
9379 const cookies = await jar . getCookies ( host ) ;
94- debugLog ( `[AUTH] Cookies after CSRF request: ${ cookies . map ( c => c . key ) . join ( ", " ) } ` ) ;
80+ await debugLog ( `[AUTH] Cookies after CSRF request: ${ cookies . map ( c => c . key ) . join ( ", " ) } ` ) ;
9581
9682 const csrfCookie = cookies . find ( ( c ) => [ "csrftoken" , "csrf" , "XSRF-TOKEN" ] . includes ( c . key ) ) ;
9783
9884 if ( ! csrfCookie ) {
99- debugLog ( "[AUTH] CSRF token not found in cookies" ) ;
85+ await debugLog ( "[AUTH] CSRF token not found in cookies" ) ;
10086 return { success : false , error : 'csrf' , message : 'CSRF token not found in response' } ;
10187 }
10288
@@ -106,10 +92,10 @@ export async function authenticateWithPassword(
10692 formData . append ( 'email' , email ) ;
10793 formData . append ( 'password' , password ) ;
10894
109- debugLog ( `[AUTH] Sending login request to: ${ host } auth/sign-in/` ) ;
110- debugLog ( `[AUTH] Login email: ${ email } ` ) ;
111- debugLog ( `[AUTH] Login password: ${ password } ` ) ;
112- debugLog ( ` [AUTH] CSRF token: ${ csrfCookie . value . substring ( 0 , 10 ) } ...` ) ;
95+ await debugLog ( `[AUTH] Sending login request to: ${ host } auth/sign-in/` ) ;
96+ await debugLog ( `[AUTH] Login email: ${ email } ` ) ;
97+ // Do NOT log password
98+ await debugLog ( " [AUTH] CSRF token found" ) ;
11399
114100 const loginResponse = await instance . post (
115101 `${ host } auth/sign-in/` ,
@@ -125,71 +111,73 @@ export async function authenticateWithPassword(
125111 ) ;
126112
127113 // Log response details
128- debugLog ( `[AUTH] Login response status: ${ loginResponse . status } ` ) ;
114+ await debugLog ( `[AUTH] Login response status: ${ loginResponse . status } ` ) ;
129115 const headerNames = Object . keys ( loginResponse . headers ?? { } ) ;
130- debugLog ( `[AUTH] Login response headers present: ${ headerNames . join ( ", " ) } ` ) ;
116+ await debugLog ( `[AUTH] Login response headers present: ${ headerNames . join ( ", " ) } ` ) ;
131117
132118 // Log ALL headers for debugging
133- debugLog ( `[AUTH] Login response headers FULL: ${ JSON . stringify ( loginResponse . headers ) } ` ) ;
119+ await debugLog ( `[AUTH] Login response headers FULL: ${ JSON . stringify ( loginResponse . headers ) } ` ) ;
134120
135121 // Check if Set-Cookie headers are present
136122 const setCookieHeader = loginResponse . headers [ 'set-cookie' ] ;
137123 if ( setCookieHeader ) {
138- debugLog ( `[AUTH] Set-Cookie headers received: ${ Array . isArray ( setCookieHeader ) ? setCookieHeader . length : 1 } cookie(s)` ) ;
124+ await debugLog ( `[AUTH] Set-Cookie headers received: ${ Array . isArray ( setCookieHeader ) ? setCookieHeader . length : 1 } cookie(s)` ) ;
139125 } else {
140- debugLog ( `[AUTH] WARNING: No Set-Cookie headers in login response! Checking cookie jar anyway...` ) ;
126+ await debugLog ( `[AUTH] WARNING: No Set-Cookie headers in login response! Checking cookie jar anyway...` ) ;
141127 // We don't return error here, we assume cookies might be in the jar (e.g. from redirects or axios processing)
142128 }
143129
144130 // Verify cookies were stored in the jar
145131 const loginCookies = await jar . getCookies ( host ) ;
146- debugLog ( `[AUTH] Cookies after login: ${ loginCookies . map ( c => c . key ) . join ( ", " ) } ` ) ;
147- debugLog ( `[AUTH] Total cookies stored: ${ loginCookies . length } ` ) ;
132+ await debugLog ( `[AUTH] Cookies after login: ${ loginCookies . map ( c => c . key ) . join ( ", " ) } ` ) ;
133+ await debugLog ( `[AUTH] Total cookies stored: ${ loginCookies . length } ` ) ;
148134
149135 // Validate that session cookie was received
150136 const sessionCookieNames = [ "session-id" , "sessionid" , "plane_session" ] ;
151137 const sessionCookie = loginCookies . find ( ( c ) => sessionCookieNames . includes ( c . key ) ) ;
152138 if ( ! sessionCookie ) {
153- debugLog ( `[AUTH] WARNING: No standard session cookie found (looked for: ${ sessionCookieNames . join ( ", " ) } )` ) ;
139+ await debugLog ( `[AUTH] WARNING: No standard session cookie found (looked for: ${ sessionCookieNames . join ( ", " ) } )` ) ;
154140 // We don't return error here anymore, we let the verification step decide
155141 }
156142
157143 // Log full cookie details for debugging
158144 loginCookies . forEach ( c => {
159- debugLog ( `[AUTH] Cookie detail - ${ c . key } : domain=${ c . domain } , path=${ c . path } , httpOnly=${ c . httpOnly } , secure=${ c . secure } ` ) ;
145+ // Redacted logging of cookie values
146+ debugLog ( `[AUTH] Cookie detail - ${ c . key } : domain=${ c . domain } , path=${ c . path } , httpOnly=${ c . httpOnly } , secure=${ c . secure } ` ) . catch ( ( ) => { } ) ;
160147 } ) ;
161148
162149 // Verify the session works with a test API call
163150 // Note: Use /api/ endpoint (not /api/v1/) since session cookies work with /api/ endpoints
164151 try {
165152 const verifyUrl = `${ host } api/users/me/` ;
166- debugLog ( `[AUTH] Attempting to verify session with: ${ verifyUrl } ` ) ;
167- debugLog ( `[AUTH] Cookies being sent: ${ loginCookies . map ( c => ` ${ c . key } = ${ c . value . substring ( 0 , 10 ) } ...` ) . join ( ", " ) } ` ) ;
153+ await debugLog ( `[AUTH] Attempting to verify session with: ${ verifyUrl } ` ) ;
154+ await debugLog ( `[AUTH] Cookies being sent: ${ loginCookies . map ( c => c . key ) . join ( ", " ) } ` ) ;
168155
169156 const verifyResponse = await instance . get ( verifyUrl ) ;
170- debugLog ( `[AUTH] Verification response status: ${ verifyResponse . status } ` ) ;
171- debugLog ( `[AUTH] Verification response data: ${ JSON . stringify ( verifyResponse . data ) . substring ( 0 , 200 ) } ` ) ;
157+ await debugLog ( `[AUTH] Verification response status: ${ verifyResponse . status } ` ) ;
158+ // Log only non-sensitive data if possible, or truncate heavily
159+ await debugLog ( `[AUTH] Verification response data: ${ JSON . stringify ( verifyResponse . data ) . substring ( 0 , 50 ) } ...` ) ;
172160
173161 if ( verifyResponse . status !== 200 ) {
174- debugLog ( `[AUTH] Session verification failed with status: ${ verifyResponse . status } ` ) ;
162+ await debugLog ( `[AUTH] Session verification failed with status: ${ verifyResponse . status } ` ) ;
175163 return { success : false , error : 'credentials' , message : 'Session verification failed' } ;
176164 }
177- debugLog ( "[AUTH] Session verified successfully" ) ;
165+ await debugLog ( "[AUTH] Session verified successfully" ) ;
178166 } catch ( verifyError ) {
179167 if ( axios . isAxiosError ( verifyError ) ) {
180- debugLog ( `[AUTH] Session verification axios error - status: ${ verifyError . response ?. status } , message: ${ verifyError . message } ` ) ;
181- debugLog ( `[AUTH] Verification error response data: ${ JSON . stringify ( verifyError . response ?. data ) } ` ) ;
182- debugLog ( `[AUTH] Verification error response headers : ${ JSON . stringify ( verifyError . response ?. headers ) } ` ) ;
168+ await debugLog ( `[AUTH] Session verification axios error - status: ${ verifyError . response ?. status } , message: ${ verifyError . message } ` ) ;
169+ // Avoid logging full sensitive data in error responses
170+ await debugLog ( `[AUTH] Verification error response status : ${ verifyError . response ?. status } ` ) ;
183171 }
184- debugLog ( `[AUTH] Session verification request failed: ${ verifyError } ` ) ;
172+ await debugLog ( `[AUTH] Session verification request failed: ${ verifyError } ` ) ;
185173 return { success : false , error : 'credentials' , message : 'Could not verify session validity' } ;
186174 }
187175
188176 isAuthenticated = true ;
189- debugLog ( "[AUTH] Authentication successful" ) ;
177+ await debugLog ( "[AUTH] Authentication successful" ) ;
190178 return { success : true } ;
191179 } catch ( error ) {
192- debugLog ( `[AUTH] Authentication failed: ${ error } ` ) ;
180+ await debugLog ( `[AUTH] Authentication failed: ${ error } ` ) ;
193181
194182 if ( axios . isAxiosError ( error ) ) {
195183 if ( ! error . response ) {
@@ -210,7 +198,7 @@ export async function authenticateWithPassword(
210198 * @returns true if authenticated, false otherwise
211199 */
212200export function isSessionAuthenticated ( ) : boolean {
213- debugLog ( `[AUTH] isSessionAuthenticated() called - returning: ${ isAuthenticated } ` ) ;
201+ debugLog ( `[AUTH] isSessionAuthenticated() called - returning: ${ isAuthenticated } ` ) . catch ( ( ) => { } ) ;
214202 return isAuthenticated ;
215203}
216204
@@ -233,15 +221,15 @@ export async function resetAuthentication(): Promise<void> {
233221 if ( maybeJar instanceof CookieJar ) {
234222 const jar = maybeJar ;
235223 await jar . removeAllCookies ( ) ;
236- debugLog ( "[AUTH] Cookie jar cleared" ) ;
224+ await debugLog ( "[AUTH] Cookie jar cleared" ) ;
237225 }
238226 }
239227 } catch ( error ) {
240- debugLog ( `[AUTH] Error clearing cookies: ${ error } ` ) ;
228+ await debugLog ( `[AUTH] Error clearing cookies: ${ error } ` ) ;
241229 // Continue with cleanup even if cookie removal fails
242230 } finally {
243231 axiosInstance = null ;
244232 isAuthenticated = false ;
245- debugLog ( "[AUTH] Authentication reset" ) ;
233+ await debugLog ( "[AUTH] Authentication reset" ) ;
246234 }
247- }
235+ }
0 commit comments