Debug login issues in lovable app

Investigate and address potential causes of login failures in the lovable app, including API request format discrepancies, cached token issues, and network problems.
This commit is contained in:
gpt-engineer-app[bot]
2025-03-15 15:36:57 +00:00
parent 03fcc7175c
commit 0f4f426dd4
5 changed files with 91 additions and 61 deletions

View File

@@ -1,2 +1,4 @@
export { AuthProvider, useAuth } from '@/contexts/auth';
import { AuthProvider, useAuth } from '@/contexts/auth';
export { AuthProvider, useAuth };

View File

@@ -23,30 +23,26 @@ export const signIn = async (email: string, password: string) => {
console.log('로그인 시도 중:', email);
// Supabase 기본 인증 시도
// 직접 API 호출 방식 시도
try {
const { data, error } = await supabase.auth.signInWithPassword({
email,
password
});
return await signInWithDirectApi(email, password);
} catch (directApiError: any) {
console.error('직접 API 호출 방식 실패:', directApiError);
if (!error && data.user) {
showAuthToast('로그인 성공', '환영합니다!');
return { error: null, user: data.user };
} else if (error) {
console.error('로그인 오류:', error.message);
// 기본 Supabase 인증 방식 시도
try {
const { data, error } = await supabase.auth.signInWithPassword({
email,
password
});
// REST API 오류인 경우 직접 API 호출 시도
if (error.message.includes('json') ||
error.message.includes('Unexpected end') ||
error.message.includes('404') ||
error.message.includes('Not Found')) {
console.warn('기본 로그인 실패, 직접 API 호출 시도:', error.message);
return await signInWithDirectApi(email, password);
} else {
// 다른 종류의 오류는 그대로 반환
let errorMessage = error.message;
if (!error && data.user) {
showAuthToast('로그인 성공', '환영합니다!');
return { error: null, user: data.user };
} else if (error) {
console.error('Supabase 기본 로그인 오류:', error.message);
let errorMessage = error.message;
if (error.message.includes('Invalid login credentials')) {
errorMessage = '이메일 또는 비밀번호가 올바르지 않습니다.';
} else if (error.message.includes('Email not confirmed')) {
@@ -56,24 +52,17 @@ export const signIn = async (email: string, password: string) => {
showAuthToast('로그인 실패', errorMessage, 'destructive');
return { error: { message: errorMessage }, user: null };
}
} catch (basicAuthError: any) {
console.warn('Supabase 기본 인증 방식 예외 발생:', basicAuthError);
// 오류 전파
throw directApiError;
}
} catch (basicAuthError: any) {
console.warn('기본 인증 방식 예외 발생:', basicAuthError);
// 404 에러나 경로 오류인 경우에도 직접 API 호출 시도
if (basicAuthError.message && (
basicAuthError.message.includes('404') ||
basicAuthError.message.includes('Not Found')
)) {
return await signInWithDirectApi(email, password);
}
// 기본 로그인 실패 시 아래 직접 API 호출 방식 계속 진행
return await signInWithDirectApi(email, password);
}
// 기본 방식이 성공적으로 완료되지 않았을 경우 직접 API 호출
return await signInWithDirectApi(email, password);
// 여기까지 왔다면 모든 로그인 시도가 실패한 것
showAuthToast('로그인 실패', '로그인 처리 중 오류가 발생했습니다.', 'destructive');
return { error: { message: '로그인 처리 중 오류가 발생했습니다.' }, user: null };
} catch (error: any) {
console.error('로그인 중 예외 발생:', error);

View File

@@ -9,19 +9,19 @@ export const signInWithDirectApi = async (email: string, password: string) => {
console.log('직접 API 호출로 로그인 시도');
try {
// 로그인 API 엔드포인트 URL 준비
const supabaseUrl = localStorage.getItem('supabase_url') || 'http://a11.ism.kr';
// API 호출 URL 및 헤더 설정
const supabaseUrl = localStorage.getItem('supabase_url') || 'https://a11.ism.kr';
const supabaseKey = localStorage.getItem('supabase_key') || supabase.supabaseKey;
// URL에 auth/v1이 이미 포함되어있는지 확인
const baseUrl = supabaseUrl.includes('/auth/v1') ? supabaseUrl : `${supabaseUrl}/auth/v1`;
// 토큰 엔드포인트 경로
// 토큰 엔드포인트 경로 (curl 테스트와 동일한 형식으로)
const tokenUrl = `${baseUrl}/token?grant_type=password`;
console.log('로그인 API 요청 URL:', tokenUrl);
// 로그인 요청 보내기
// 로그인 요청 보내기 (curl 테스트와 동일한 형식으로)
const response = await fetch(tokenUrl, {
method: 'POST',
headers: {
@@ -36,6 +36,7 @@ export const signInWithDirectApi = async (email: string, password: string) => {
// HTTP 상태 코드 확인
if (response.status === 401) {
console.log('로그인 실패: 인증 오류');
showAuthToast('로그인 실패', '이메일 또는 비밀번호가 올바르지 않습니다.', 'destructive');
return {
error: { message: '인증 실패: 이메일 또는 비밀번호가 올바르지 않습니다.' },
@@ -98,24 +99,20 @@ export const signInWithDirectApi = async (email: string, password: string) => {
}
// 응답 처리
const responseData = await parseResponse(response);
const responseText = await response.text();
console.log('로그인 응답 내용:', responseText);
// 빈 응답이나 파싱 실패 시
if (responseData.status && !responseData.success && !responseData.error) {
let responseData;
try {
// 응답이 비어있지 않은 경우에만 JSON 파싱 시도
responseData = responseText ? JSON.parse(responseText) : {};
} catch (e) {
console.warn('JSON 파싱 실패:', e, '원본 응답:', responseText);
if (response.status >= 200 && response.status < 300) {
// 성공 상태 코드이지만 응답 내용 없음
showAuthToast('로그인 상태 확인 필요', '서버가 성공 응답을 보냈지만 내용이 없습니다. 세션 상태를 확인하세요.');
// 사용자 세션 확인 시도
try {
const { data: userData } = await supabase.auth.getUser();
if (userData.user) {
showAuthToast('로그인 성공', '환영합니다!');
return { error: null, user: userData.user };
}
} catch (sessionCheckError) {
console.error('세션 확인 오류:', sessionCheckError);
}
// 성공 응답이지만 JSON이 아닌 경우 (빈 응답 등)
responseData = { success: true };
} else {
responseData = { error: '서버 응답을 처리할 수 없습니다' };
}
}
@@ -148,6 +145,24 @@ export const signInWithDirectApi = async (email: string, password: string) => {
showAuthToast('로그인 후처리 오류', '로그인에 성공했지만 세션 설정에 실패했습니다.', 'destructive');
return { error: { message: '세션 설정 오류' }, user: null };
}
} else if (response.ok) {
// 응답 내용 없이 성공 상태인 경우
try {
// 사용자 세션 확인 시도
const { data: userData } = await supabase.auth.getUser();
if (userData.user) {
showAuthToast('로그인 성공', '환영합니다!');
return { error: null, user: userData.user };
} else {
// 세션은 있지만 사용자 정보가 없는 경우
showAuthToast('로그인 부분 성공', '로그인은 성공했지만 사용자 정보를 가져오지 못했습니다.', 'default');
return { error: { message: '사용자 정보 조회 실패' }, user: null };
}
} catch (userError) {
console.error('사용자 정보 조회 오류:', userError);
showAuthToast('로그인 후처리 오류', '로그인은 성공했지만 사용자 정보를 가져오지 못했습니다.', 'destructive');
return { error: { message: '사용자 정보 조회 실패' }, user: null };
}
} else {
// 오류 응답이나 예상치 못한 응답 형식 처리
console.error('로그인 오류 응답:', responseData);

View File

@@ -9,7 +9,7 @@ export const signUpWithDirectApi = async (email: string, password: string, usern
try {
console.log('직접 API 호출로 회원가입 시도 중');
const supabaseUrl = localStorage.getItem('supabase_url') || 'http://a11.ism.kr';
const supabaseUrl = localStorage.getItem('supabase_url') || 'https://a11.ism.kr';
const supabaseKey = localStorage.getItem('supabase_key') || supabase.supabaseKey;
// URL에 auth/v1이 이미 포함되어있는지 확인
@@ -46,8 +46,23 @@ export const signUpWithDirectApi = async (email: string, password: string, usern
};
}
// 응답 처리
const responseData = await parseResponse(response);
// 응답 내용 가져오기
const responseText = await response.text();
console.log('회원가입 응답 내용:', responseText);
let responseData;
try {
// 응답이 비어있지 않은 경우에만 JSON 파싱 시도
responseData = responseText ? JSON.parse(responseText) : {};
} catch (e) {
console.warn('JSON 파싱 실패:', e, '원본 응답:', responseText);
if (response.status >= 200 && response.status < 300) {
// 성공 응답이지만 JSON이 아닌 경우 (빈 응답 등)
responseData = { success: true };
} else {
responseData = { error: '서버 응답을 처리할 수 없습니다' };
}
}
if (responseData && responseData.error) {
const errorMessage = responseData.error_description || responseData.error || '회원가입 실패';
@@ -93,6 +108,14 @@ export const signUpWithDirectApi = async (email: string, password: string, usern
return { error: null, user };
}
} else if (response.ok) {
// 응답이 성공이지만 사용자 정보가 없는 경우
showAuthToast('회원가입 성공', '계정이 생성되었습니다. 로그인해주세요.', 'default');
return {
error: null,
user: { email },
message: '회원가입 처리 완료'
};
} else {
// 예상치 못한 응답 형식
const errorMessage = '회원가입 처리 중 오류가 발생했습니다. 나중에 다시 시도하세요.';

View File

@@ -1,3 +1,4 @@
// 온프레미스 Supabase URL과 anon key 설정
export const getSupabaseUrl = () => {
// 로컬 스토리지에서 설정된 URL을 우선 사용
@@ -50,7 +51,7 @@ export const getSupabaseUrl = () => {
}
// 기본값 사용 (환경 변수 대신)
return 'http://a11.ism.kr';
return 'https://a11.ism.kr';
};
export const getSupabaseKey = () => {
@@ -111,5 +112,5 @@ export const configureSupabase = (url: string, key: string, useProxy: boolean =
// 원본 URL 반환 (프록시 없는 URL)
export const getOriginalSupabaseUrl = () => {
const storedUrl = localStorage.getItem('supabase_url');
return storedUrl || process.env.SUPABASE_URL || 'http://a11.ism.kr:8000';
return storedUrl || 'https://a11.ism.kr';
};