forked from baron/baron-sso
모바일 승인 완료 화면에서 verify_failed 오류 노출 개선
This commit is contained in:
@@ -726,6 +726,7 @@ body = "We could not find an account for that information.\\\\\\\\\\\\\\\\nPleas
|
|||||||
[msg.userfront.login.verification]
|
[msg.userfront.login.verification]
|
||||||
approved = "Approved. Complete sign-in in the original window."
|
approved = "Approved. Complete sign-in in the original window."
|
||||||
approved_local = "Approved. This device is already signed in, and the remote window will be signed in shortly."
|
approved_local = "Approved. This device is already signed in, and the remote window will be signed in shortly."
|
||||||
|
approved_remote = "Approved. Please return to your original browser or PC screen."
|
||||||
success = "Sign-in approval completed."
|
success = "Sign-in approval completed."
|
||||||
|
|
||||||
[msg.userfront.login_success]
|
[msg.userfront.login_success]
|
||||||
@@ -2287,8 +2288,10 @@ title = "Account not found"
|
|||||||
|
|
||||||
[ui.userfront.login.verification]
|
[ui.userfront.login.verification]
|
||||||
action_label = "Done"
|
action_label = "Done"
|
||||||
|
action_label_close = "Close Window"
|
||||||
page_title = "Sign-in approval"
|
page_title = "Sign-in approval"
|
||||||
title = "Approval complete"
|
title = "Approval complete"
|
||||||
|
title_remote = "Sign-in approval complete"
|
||||||
|
|
||||||
[ui.userfront.login_success]
|
[ui.userfront.login_success]
|
||||||
later = "Do this later (go to dashboard)"
|
later = "Do this later (go to dashboard)"
|
||||||
|
|||||||
@@ -1164,6 +1164,7 @@ body = "가입되지 않은 정보입니다.\\\\n회원가입 후 이용해 주
|
|||||||
[msg.userfront.login.verification]
|
[msg.userfront.login.verification]
|
||||||
approved = "승인되었습니다. 로그인은 요청하신 창에서 완료됩니다."
|
approved = "승인되었습니다. 로그인은 요청하신 창에서 완료됩니다."
|
||||||
approved_local = "승인 되었습니다. 이 기기는 로그인되어 있는 상태입니다. 원격 창도 로그인이 될 예정입니다"
|
approved_local = "승인 되었습니다. 이 기기는 로그인되어 있는 상태입니다. 원격 창도 로그인이 될 예정입니다"
|
||||||
|
approved_remote = "승인되었습니다. 요청하신 브라우저 또는 PC 화면으로 돌아가 주세요."
|
||||||
success = "로그인 승인에 성공했습니다."
|
success = "로그인 승인에 성공했습니다."
|
||||||
|
|
||||||
[msg.userfront.login_success]
|
[msg.userfront.login_success]
|
||||||
@@ -2686,8 +2687,10 @@ title = "미등록 회원"
|
|||||||
|
|
||||||
[ui.userfront.login.verification]
|
[ui.userfront.login.verification]
|
||||||
action_label = "확인"
|
action_label = "확인"
|
||||||
|
action_label_close = "창 닫기"
|
||||||
page_title = "로그인 승인"
|
page_title = "로그인 승인"
|
||||||
title = "승인 완료"
|
title = "승인 완료"
|
||||||
|
title_remote = "로그인 승인 완료"
|
||||||
|
|
||||||
[ui.userfront.login_success]
|
[ui.userfront.login_success]
|
||||||
later = "나중에 하기 (대시보드로 이동)"
|
later = "나중에 하기 (대시보드로 이동)"
|
||||||
|
|||||||
@@ -1039,6 +1039,7 @@ body = ""
|
|||||||
[msg.userfront.login.verification]
|
[msg.userfront.login.verification]
|
||||||
approved = ""
|
approved = ""
|
||||||
approved_local = ""
|
approved_local = ""
|
||||||
|
approved_remote = ""
|
||||||
success = ""
|
success = ""
|
||||||
|
|
||||||
[msg.userfront.login_success]
|
[msg.userfront.login_success]
|
||||||
@@ -2561,8 +2562,10 @@ title = ""
|
|||||||
|
|
||||||
[ui.userfront.login.verification]
|
[ui.userfront.login.verification]
|
||||||
action_label = ""
|
action_label = ""
|
||||||
|
action_label_close = ""
|
||||||
page_title = ""
|
page_title = ""
|
||||||
title = ""
|
title = ""
|
||||||
|
title_remote = ""
|
||||||
|
|
||||||
[ui.userfront.login_success]
|
[ui.userfront.login_success]
|
||||||
later = ""
|
later = ""
|
||||||
|
|||||||
@@ -213,6 +213,7 @@ body = "We could not find an account for that information.\\\\\\\\\\\\\\\\nPleas
|
|||||||
[msg.userfront.login.verification]
|
[msg.userfront.login.verification]
|
||||||
approved = "Approved. Complete sign-in in the original window."
|
approved = "Approved. Complete sign-in in the original window."
|
||||||
approved_local = "Approved. This device is already signed in, and the remote window will be signed in shortly."
|
approved_local = "Approved. This device is already signed in, and the remote window will be signed in shortly."
|
||||||
|
approved_remote = "Approved. Please return to your original browser or PC screen."
|
||||||
success = "Sign-in approval completed."
|
success = "Sign-in approval completed."
|
||||||
|
|
||||||
[msg.userfront.login_success]
|
[msg.userfront.login_success]
|
||||||
@@ -554,8 +555,10 @@ title = "Account not found"
|
|||||||
|
|
||||||
[ui.userfront.login.verification]
|
[ui.userfront.login.verification]
|
||||||
action_label = "Done"
|
action_label = "Done"
|
||||||
|
action_label_close = "Close Window"
|
||||||
page_title = "Sign-in approval"
|
page_title = "Sign-in approval"
|
||||||
title = "Approval complete"
|
title = "Approval complete"
|
||||||
|
title_remote = "Sign-in approval complete"
|
||||||
|
|
||||||
[ui.userfront.login_success]
|
[ui.userfront.login_success]
|
||||||
later = "Do this later (go to dashboard)"
|
later = "Do this later (go to dashboard)"
|
||||||
|
|||||||
@@ -420,6 +420,7 @@ body = "가입되지 않은 정보입니다.\\\\n회원가입 후 이용해 주
|
|||||||
[msg.userfront.login.verification]
|
[msg.userfront.login.verification]
|
||||||
approved = "승인되었습니다. 로그인은 요청하신 창에서 완료됩니다."
|
approved = "승인되었습니다. 로그인은 요청하신 창에서 완료됩니다."
|
||||||
approved_local = "승인 되었습니다. 이 기기는 로그인되어 있는 상태입니다. 원격 창도 로그인이 될 예정입니다"
|
approved_local = "승인 되었습니다. 이 기기는 로그인되어 있는 상태입니다. 원격 창도 로그인이 될 예정입니다"
|
||||||
|
approved_remote = "승인되었습니다. 요청하신 브라우저 또는 PC 화면으로 돌아가 주세요."
|
||||||
success = "로그인 승인에 성공했습니다."
|
success = "로그인 승인에 성공했습니다."
|
||||||
|
|
||||||
[msg.userfront.login_success]
|
[msg.userfront.login_success]
|
||||||
@@ -759,8 +760,10 @@ title = "미등록 회원"
|
|||||||
|
|
||||||
[ui.userfront.login.verification]
|
[ui.userfront.login.verification]
|
||||||
action_label = "확인"
|
action_label = "확인"
|
||||||
|
action_label_close = "창 닫기"
|
||||||
page_title = "로그인 승인"
|
page_title = "로그인 승인"
|
||||||
title = "승인 완료"
|
title = "승인 완료"
|
||||||
|
title_remote = "로그인 승인 완료"
|
||||||
|
|
||||||
[ui.userfront.login_success]
|
[ui.userfront.login_success]
|
||||||
later = "나중에 하기 (대시보드로 이동)"
|
later = "나중에 하기 (대시보드로 이동)"
|
||||||
|
|||||||
@@ -392,6 +392,7 @@ body = ""
|
|||||||
[msg.userfront.login.verification]
|
[msg.userfront.login.verification]
|
||||||
approved = ""
|
approved = ""
|
||||||
approved_local = ""
|
approved_local = ""
|
||||||
|
approved_remote = ""
|
||||||
success = ""
|
success = ""
|
||||||
|
|
||||||
[msg.userfront.login_success]
|
[msg.userfront.login_success]
|
||||||
@@ -731,8 +732,10 @@ title = ""
|
|||||||
|
|
||||||
[ui.userfront.login.verification]
|
[ui.userfront.login.verification]
|
||||||
action_label = ""
|
action_label = ""
|
||||||
|
action_label_close = ""
|
||||||
page_title = ""
|
page_title = ""
|
||||||
title = ""
|
title = ""
|
||||||
|
title_remote = ""
|
||||||
|
|
||||||
[ui.userfront.login_success]
|
[ui.userfront.login_success]
|
||||||
later = ""
|
later = ""
|
||||||
|
|||||||
@@ -722,6 +722,14 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _isAlreadyVerifiedError(Object e) {
|
||||||
|
final msg = e.toString().toLowerCase();
|
||||||
|
return msg.contains('already_used') ||
|
||||||
|
msg.contains('already_verified') ||
|
||||||
|
msg.contains('session_active') ||
|
||||||
|
msg.contains('verify_failed');
|
||||||
|
}
|
||||||
|
|
||||||
void _markVerificationApproved(
|
void _markVerificationApproved(
|
||||||
String message, {
|
String message, {
|
||||||
String? title,
|
String? title,
|
||||||
@@ -730,13 +738,19 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
String actionPath = '/',
|
String actionPath = '/',
|
||||||
bool autoRedirect = false,
|
bool autoRedirect = false,
|
||||||
Duration redirectDelay = const Duration(seconds: 2),
|
Duration redirectDelay = const Duration(seconds: 2),
|
||||||
|
bool isRemote = false,
|
||||||
}) {
|
}) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
final resolvedTitle = title ?? tr('ui.userfront.login.verification.title');
|
final resolvedTitle = title ??
|
||||||
|
(isRemote
|
||||||
|
? tr('ui.userfront.login.verification.title_remote')
|
||||||
|
: tr('ui.userfront.login.verification.title'));
|
||||||
final resolvedPageTitle =
|
final resolvedPageTitle =
|
||||||
pageTitle ?? tr('ui.userfront.login.verification.page_title');
|
pageTitle ?? tr('ui.userfront.login.verification.page_title');
|
||||||
final resolvedActionLabel =
|
final resolvedActionLabel = actionLabel ??
|
||||||
actionLabel ?? tr('ui.userfront.login.verification.action_label');
|
(isRemote
|
||||||
|
? tr('ui.userfront.login.verification.action_label_close')
|
||||||
|
: tr('ui.userfront.login.verification.action_label'));
|
||||||
setState(() {
|
setState(() {
|
||||||
_verificationApproved = true;
|
_verificationApproved = true;
|
||||||
_verificationMessage = message;
|
_verificationMessage = message;
|
||||||
@@ -744,6 +758,10 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
_verificationPageTitle = resolvedPageTitle;
|
_verificationPageTitle = resolvedPageTitle;
|
||||||
_verificationActionLabel = resolvedActionLabel;
|
_verificationActionLabel = resolvedActionLabel;
|
||||||
});
|
});
|
||||||
|
if (isRemote) {
|
||||||
|
_verificationRedirectTimer?.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
_verificationRedirectTimer?.cancel();
|
_verificationRedirectTimer?.cancel();
|
||||||
if (autoRedirect) {
|
if (autoRedirect) {
|
||||||
_verificationRedirectTimer = Timer(redirectDelay, () {
|
_verificationRedirectTimer = Timer(redirectDelay, () {
|
||||||
@@ -785,6 +803,11 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
FilledButton(
|
FilledButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
if (_verificationActionLabel ==
|
||||||
|
tr('ui.userfront.login.verification.action_label_close')) {
|
||||||
|
webWindow.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
final hasLocalSession =
|
final hasLocalSession =
|
||||||
(AuthTokenStore.getToken()?.isNotEmpty ?? false) ||
|
(AuthTokenStore.getToken()?.isNotEmpty ?? false) ||
|
||||||
AuthTokenStore.usesCookie();
|
AuthTokenStore.usesCookie();
|
||||||
@@ -813,6 +836,9 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
final localSessionMessage = tr(
|
final localSessionMessage = tr(
|
||||||
'msg.userfront.login.verification.approved_local',
|
'msg.userfront.login.verification.approved_local',
|
||||||
);
|
);
|
||||||
|
final remoteApprovedMessage =
|
||||||
|
tr('msg.userfront.login.verification.approved_remote');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Use Backend to verify the token (Backend-Driven Flow)
|
// Use Backend to verify the token (Backend-Driven Flow)
|
||||||
final res = await AuthProxyService.verifyMagicLink(
|
final res = await AuthProxyService.verifyMagicLink(
|
||||||
@@ -829,7 +855,11 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
|
|
||||||
if (status == 'approved' || (jwt == null && _verificationOnly)) {
|
if (status == 'approved' || (jwt == null && _verificationOnly)) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
if (_verificationOnly && !hasLocalSession) {
|
||||||
|
_markVerificationApproved(remoteApprovedMessage, isRemote: true);
|
||||||
|
} else {
|
||||||
|
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -847,15 +877,23 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
if (_verificationOnly && !hasLocalSession) {
|
||||||
|
_markVerificationApproved(remoteApprovedMessage, isRemote: true);
|
||||||
|
} else {
|
||||||
|
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint("[Auth] Verification FAILED for token: $token. Error: $e");
|
debugPrint("[Auth] Verification FAILED for token: $token. Error: $e");
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
|
if (_verificationOnly && _isAlreadyVerifiedError(e)) {
|
||||||
|
_markVerificationApproved(remoteApprovedMessage, isRemote: true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
_showError(
|
_showError(
|
||||||
tr(
|
tr(
|
||||||
'msg.userfront.login.verification_failed',
|
'msg.userfront.login.verification_failed',
|
||||||
params: {'error': e.toString()},
|
params: {'error': e.toString().replaceFirst('Exception: ', '')},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -875,6 +913,9 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
final localSessionMessage = tr(
|
final localSessionMessage = tr(
|
||||||
'msg.userfront.login.verification.approved_local',
|
'msg.userfront.login.verification.approved_local',
|
||||||
);
|
);
|
||||||
|
final remoteApprovedMessage =
|
||||||
|
tr('msg.userfront.login.verification.approved_remote');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final res = await AuthProxyService.verifyLoginCode(
|
final res = await AuthProxyService.verifyLoginCode(
|
||||||
sanitizedLoginId,
|
sanitizedLoginId,
|
||||||
@@ -894,7 +935,11 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
|
|
||||||
if (jwt == null && status == 'approved') {
|
if (jwt == null && status == 'approved') {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
if (_verificationOnly && !hasLocalSession) {
|
||||||
|
_markVerificationApproved(remoteApprovedMessage, isRemote: true);
|
||||||
|
} else {
|
||||||
|
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -908,7 +953,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_verificationOnly) {
|
if (_verificationOnly) {
|
||||||
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
_markVerificationApproved(remoteApprovedMessage, isRemote: true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_onLoginSuccess(jwt, provider: res['provider'] as String?);
|
_onLoginSuccess(jwt, provider: res['provider'] as String?);
|
||||||
@@ -916,17 +961,25 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_verificationOnly && mounted) {
|
if (_verificationOnly && mounted) {
|
||||||
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
if (!hasLocalSession) {
|
||||||
|
_markVerificationApproved(remoteApprovedMessage, isRemote: true);
|
||||||
|
} else {
|
||||||
|
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint(
|
debugPrint(
|
||||||
"[Auth] Code verification FAILED for loginId: $sanitizedLoginId. Error: $e",
|
"[Auth] Code verification FAILED for loginId: $sanitizedLoginId. Error: $e",
|
||||||
);
|
);
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
|
if (_verificationOnly && _isAlreadyVerifiedError(e)) {
|
||||||
|
_markVerificationApproved(remoteApprovedMessage, isRemote: true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
_showError(
|
_showError(
|
||||||
tr(
|
tr(
|
||||||
'msg.userfront.login.verification_failed',
|
'msg.userfront.login.verification_failed',
|
||||||
params: {'error': e.toString()},
|
params: {'error': e.toString().replaceFirst('Exception: ', '')},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -941,6 +994,9 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
final localSessionMessage = tr(
|
final localSessionMessage = tr(
|
||||||
'msg.userfront.login.verification.approved_local',
|
'msg.userfront.login.verification.approved_local',
|
||||||
);
|
);
|
||||||
|
final remoteApprovedMessage =
|
||||||
|
tr('msg.userfront.login.verification.approved_remote');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final res = await AuthProxyService.verifyLoginShortCode(
|
final res = await AuthProxyService.verifyLoginShortCode(
|
||||||
sanitized,
|
sanitized,
|
||||||
@@ -956,7 +1012,11 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
|
|
||||||
if (jwt == null && status == 'approved') {
|
if (jwt == null && status == 'approved') {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
if (_verificationOnly && !hasLocalSession) {
|
||||||
|
_markVerificationApproved(remoteApprovedMessage, isRemote: true);
|
||||||
|
} else {
|
||||||
|
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -970,7 +1030,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_verificationOnly) {
|
if (_verificationOnly) {
|
||||||
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
_markVerificationApproved(remoteApprovedMessage, isRemote: true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_onLoginSuccess(jwt, provider: res['provider'] as String?);
|
_onLoginSuccess(jwt, provider: res['provider'] as String?);
|
||||||
@@ -978,15 +1038,23 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_verificationOnly && mounted) {
|
if (_verificationOnly && mounted) {
|
||||||
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
if (!hasLocalSession) {
|
||||||
|
_markVerificationApproved(remoteApprovedMessage, isRemote: true);
|
||||||
|
} else {
|
||||||
|
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint("[Auth] Short code verification FAILED. Error: $e");
|
debugPrint("[Auth] Short code verification FAILED. Error: $e");
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
|
if (_verificationOnly && _isAlreadyVerifiedError(e)) {
|
||||||
|
_markVerificationApproved(remoteApprovedMessage, isRemote: true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
_showError(
|
_showError(
|
||||||
tr(
|
tr(
|
||||||
'msg.userfront.login.verification_failed',
|
'msg.userfront.login.verification_failed',
|
||||||
params: {'error': e.toString()},
|
params: {'error': e.toString().replaceFirst('Exception: ', '')},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user