Skip to content

Commit 39fee6b

Browse files
Merge pull request #226 from sparcs-kaist/codex/기본-access-token-만료-시-자동-로그인-문제-수정
Fix auto logout on expired tokens
2 parents 57b44f0 + e88aa05 commit 39fee6b

File tree

2 files changed

+49
-2
lines changed

2 files changed

+49
-2
lines changed

lib/dio_provider.dart

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ class DioProvider {
1414

1515
final StorageService _storageService = StorageService();
1616

17+
bool _isRefreshingToken = false;
18+
1719
static BuildContext? _navigatorContext;
1820
static BuildContext? get navigatorContext => _navigatorContext;
1921

@@ -39,8 +41,24 @@ class DioProvider {
3941
}
4042
return handler.next(options);
4143
},
44+
// 기존 구현에서는 401 상태가 오면 바로 로그아웃을 호출하여
45+
// 토큰이 만료된 경우에도 자동 로그인 상태가 해제되는 문제가 있었다.
4246
onError: (DioException e, handler) async {
4347
if (e.response?.statusCode == 401) {
48+
if (!_isRefreshingToken) {
49+
_isRefreshingToken = true;
50+
final refreshed = await _refreshToken();
51+
_isRefreshingToken = false;
52+
if (refreshed) {
53+
try {
54+
final response = await _dio.fetch(e.requestOptions);
55+
return handler.resolve(response);
56+
} catch (err) {
57+
// If retry fails, fall through to logout
58+
}
59+
}
60+
}
61+
4462
if (_navigatorContext != null) {
4563
try {
4664
Provider.of<AuthModel>(_navigatorContext!, listen: false)
@@ -60,4 +78,33 @@ class DioProvider {
6078
},
6179
));
6280
}
81+
82+
Future<bool> _refreshToken() async {
83+
final refreshToken = await _storageService.getRefreshToken();
84+
if (refreshToken == null) {
85+
return false;
86+
}
87+
88+
final refreshDio = Dio(BaseOptions(baseUrl: _dio.options.baseUrl));
89+
try {
90+
final response = await refreshDio.post(
91+
SESSION_REFRESH_URL,
92+
data: {'token': refreshToken},
93+
);
94+
95+
if (response.statusCode == 200 && response.data != null) {
96+
final newAccessToken = response.data['accessToken'];
97+
final newRefreshToken = response.data['refreshToken'];
98+
99+
if (newAccessToken != null && newRefreshToken != null) {
100+
await _storageService.saveTokens(
101+
accessToken: newAccessToken, refreshToken: newRefreshToken);
102+
return true;
103+
}
104+
}
105+
} catch (e) {
106+
print('Error refreshing token in DioProvider: $e');
107+
}
108+
return false;
109+
}
63110
}

lib/main.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,8 @@ class _OTLAppState extends State<OTLApp> {
201201
} catch (e) {
202202
print("Unexpected error refreshing token: $e");
203203
}
204-
// TODO: 토큰 갱신 실패 시 로그아웃 처리
205-
return true;
204+
// Token refresh failed
205+
return false;
206206
}
207207

208208
void _initDeepLinks() {

0 commit comments

Comments
 (0)