mirror of https://github.com/buster-so/buster.git
better logging for auth
This commit is contained in:
parent
b1ac8b51b3
commit
32a0b84eeb
|
@ -7,40 +7,91 @@ const supabase = createSupabaseClient();
|
|||
|
||||
export const requireAuth = bearerAuth({
|
||||
verifyToken: async (token, c) => {
|
||||
const { data, error } = await supabase.auth.getUser(token); //usually takes about 3 - 7ms
|
||||
try {
|
||||
const { data, error } = await supabase.auth.getUser(token); //usually takes about 3 - 7ms
|
||||
|
||||
if (error || !data.user) {
|
||||
if (error) {
|
||||
// Log specific auth errors to help with debugging
|
||||
console.warn('Token validation failed:', {
|
||||
error: error.message,
|
||||
// Don't log the actual token for security
|
||||
tokenPrefix: `${token.substring(0, 20)}...`,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!data.user) {
|
||||
console.warn('No user found for valid token');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set user in context for use in route handlers
|
||||
c.set('supabaseUser', data.user);
|
||||
|
||||
// Get the corresponding user from your database
|
||||
const busterUser = await getUser({ id: data.user.id });
|
||||
|
||||
if (!busterUser) {
|
||||
console.warn('Supabase user found but no corresponding database user:', {
|
||||
supabaseUserId: data.user.id,
|
||||
email: data.user.email,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
c.set('busterUser', busterUser);
|
||||
|
||||
// Ensure user is not anonymous
|
||||
const isAuthenticated = !data.user.is_anonymous;
|
||||
|
||||
if (!isAuthenticated) {
|
||||
console.info('Anonymous user attempted to access protected resource');
|
||||
}
|
||||
|
||||
return isAuthenticated;
|
||||
} catch (error) {
|
||||
console.error('Unexpected error during token validation:', error);
|
||||
return false;
|
||||
}
|
||||
|
||||
c.set('supabaseUser', data.user);
|
||||
|
||||
const busterUser = await getUser({ id: data.user.id });
|
||||
|
||||
if (!busterUser) {
|
||||
return false;
|
||||
}
|
||||
|
||||
c.set('busterUser', busterUser);
|
||||
|
||||
return !!data.user.is_anonymous === false;
|
||||
},
|
||||
});
|
||||
|
||||
export async function requireUser(c: Context, next: Next) {
|
||||
const token = c.req.header('Authorization')?.split(' ')[1];
|
||||
const authHeader = c.req.header('Authorization');
|
||||
|
||||
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
||||
console.warn('Missing or invalid Authorization header');
|
||||
throw new Error('User not authenticated - missing Authorization header');
|
||||
}
|
||||
|
||||
const token = authHeader.split(' ')[1];
|
||||
|
||||
if (!token) {
|
||||
throw new Error('User not authenticated');
|
||||
console.warn('Empty token in Authorization header');
|
||||
throw new Error('User not authenticated - empty token');
|
||||
}
|
||||
|
||||
const { data, error } = await supabase.auth.getUser(token);
|
||||
try {
|
||||
const { data, error } = await supabase.auth.getUser(token);
|
||||
|
||||
const user = data.user;
|
||||
if (error) {
|
||||
console.warn('Token validation failed in requireUser:', {
|
||||
error: error.message,
|
||||
});
|
||||
throw new Error('User not authenticated - invalid token');
|
||||
}
|
||||
|
||||
if (!user || error || user.is_anonymous) {
|
||||
throw new Error('User not authenticated');
|
||||
const user = data.user;
|
||||
|
||||
if (!user || user.is_anonymous) {
|
||||
console.warn('No valid user found or user is anonymous');
|
||||
throw new Error('User not authenticated - no valid user');
|
||||
}
|
||||
|
||||
// User is valid, continue to next middleware/handler
|
||||
return next();
|
||||
} catch (error) {
|
||||
console.error('Unexpected error in requireUser:', error);
|
||||
throw new Error('User not authenticated - server error');
|
||||
}
|
||||
|
||||
return next();
|
||||
}
|
||||
|
|
|
@ -17,17 +17,43 @@ export const createAxiosInstance = (baseURL: string) => {
|
|||
}
|
||||
});
|
||||
|
||||
// Response interceptor with retry logic for auth errors
|
||||
apiInstance.interceptors.response.use(
|
||||
(resp) => {
|
||||
return resp;
|
||||
},
|
||||
(error: AxiosError) => {
|
||||
async (error: AxiosError) => {
|
||||
const errorCode = error.response?.status;
|
||||
|
||||
//402 is the payment required error code
|
||||
if (errorCode === 402) {
|
||||
window.location.href = createBusterRoute({
|
||||
route: BusterRoutes.INFO_GETTING_STARTED
|
||||
});
|
||||
return Promise.reject(rustErrorHandler(error));
|
||||
}
|
||||
|
||||
// Handle 401 Unauthorized - token might be expired
|
||||
if (errorCode === 401 && !isServer) {
|
||||
// Only retry once to avoid infinite loops
|
||||
const originalRequest = error.config as InternalAxiosRequestConfig & { _retry?: boolean };
|
||||
if (originalRequest && !originalRequest._retry) {
|
||||
originalRequest._retry = true;
|
||||
|
||||
try {
|
||||
// Force token refresh and retry the request
|
||||
console.info('401 error detected, attempting to refresh token and retry request');
|
||||
|
||||
// The request interceptor will handle getting the new token
|
||||
return apiInstance(originalRequest);
|
||||
} catch (refreshError) {
|
||||
console.error('Failed to refresh token and retry request:', refreshError);
|
||||
// If refresh fails, redirect to login or show error
|
||||
window.location.href = createBusterRoute({
|
||||
route: BusterRoutes.AUTH_LOGIN
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.reject(rustErrorHandler(error));
|
||||
|
@ -45,17 +71,25 @@ export const defaultAxiosRequestHandler = async (
|
|||
}
|
||||
) => {
|
||||
let token = '';
|
||||
if (isServer) {
|
||||
token = await getSupabaseTokenFromCookies();
|
||||
} else {
|
||||
token = (await options?.checkTokenValidity()?.then((res) => res?.access_token || '')) || '';
|
||||
|
||||
try {
|
||||
if (isServer) {
|
||||
token = await getSupabaseTokenFromCookies();
|
||||
} else {
|
||||
// Always check token validity before making requests
|
||||
const tokenResult = await options?.checkTokenValidity();
|
||||
token = tokenResult?.access_token || '';
|
||||
}
|
||||
|
||||
if (!token) {
|
||||
throw new Error('User authentication error - no token found');
|
||||
}
|
||||
|
||||
(config.headers as AxiosRequestHeaders).Authorization = `Bearer ${token}`;
|
||||
|
||||
return config;
|
||||
} catch (error) {
|
||||
console.error('Error getting auth token for request:', error);
|
||||
throw new Error('User authentication error - failed to get valid token');
|
||||
}
|
||||
|
||||
if (!token) {
|
||||
throw new Error('User authentication error - no token found');
|
||||
}
|
||||
|
||||
(config.headers as AxiosRequestHeaders).Authorization = `Bearer ${token}`;
|
||||
|
||||
return config;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue