forked from baron/baron-sso
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
@@ -730,6 +730,7 @@ 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),
|
||||||
|
VoidCallback? onAction,
|
||||||
}) {
|
}) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
final resolvedTitle = title ?? tr('ui.userfront.login.verification.title');
|
final resolvedTitle = title ?? tr('ui.userfront.login.verification.title');
|
||||||
@@ -743,16 +744,23 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
_verificationTitle = resolvedTitle;
|
_verificationTitle = resolvedTitle;
|
||||||
_verificationPageTitle = resolvedPageTitle;
|
_verificationPageTitle = resolvedPageTitle;
|
||||||
_verificationActionLabel = resolvedActionLabel;
|
_verificationActionLabel = resolvedActionLabel;
|
||||||
|
_onVerificationAction = onAction;
|
||||||
});
|
});
|
||||||
_verificationRedirectTimer?.cancel();
|
_verificationRedirectTimer?.cancel();
|
||||||
if (autoRedirect) {
|
if (autoRedirect) {
|
||||||
_verificationRedirectTimer = Timer(redirectDelay, () {
|
_verificationRedirectTimer = Timer(redirectDelay, () {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
context.go(actionPath);
|
if (onAction != null) {
|
||||||
|
onAction();
|
||||||
|
} else {
|
||||||
|
context.go(actionPath);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VoidCallback? _onVerificationAction;
|
||||||
|
|
||||||
Widget _buildVerificationResultView() {
|
Widget _buildVerificationResultView() {
|
||||||
return Center(
|
return Center(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@@ -785,6 +793,10 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
FilledButton(
|
FilledButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
if (_onVerificationAction != null) {
|
||||||
|
_onVerificationAction!();
|
||||||
|
return;
|
||||||
|
}
|
||||||
final hasLocalSession =
|
final hasLocalSession =
|
||||||
(AuthTokenStore.getToken()?.isNotEmpty ?? false) ||
|
(AuthTokenStore.getToken()?.isNotEmpty ?? false) ||
|
||||||
AuthTokenStore.usesCookie();
|
AuthTokenStore.usesCookie();
|
||||||
@@ -810,6 +822,8 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
Future<void> _verifyToken(String token) async {
|
Future<void> _verifyToken(String token) async {
|
||||||
debugPrint("[Auth] Starting verification for token: $token");
|
debugPrint("[Auth] Starting verification for token: $token");
|
||||||
final approvedMessage = tr('msg.userfront.login.verification.approved');
|
final approvedMessage = tr('msg.userfront.login.verification.approved');
|
||||||
|
final remoteApprovedMessage =
|
||||||
|
tr('msg.userfront.login.verification.approved_remote');
|
||||||
final localSessionMessage = tr(
|
final localSessionMessage = tr(
|
||||||
'msg.userfront.login.verification.approved_local',
|
'msg.userfront.login.verification.approved_local',
|
||||||
);
|
);
|
||||||
@@ -829,7 +843,12 @@ 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);
|
_markVerificationApproved(
|
||||||
|
remoteApprovedMessage,
|
||||||
|
title: tr('ui.userfront.login.verification.title_remote'),
|
||||||
|
actionLabel: tr('ui.userfront.login.verification.action_label_close'),
|
||||||
|
onAction: () => webWindow.close(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -851,6 +870,23 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint("[Auth] Verification FAILED for token: $token. Error: $e");
|
debugPrint("[Auth] Verification FAILED for token: $token. Error: $e");
|
||||||
|
|
||||||
|
// Handle the case where the token is already verified/used (common in remote flows)
|
||||||
|
final errorStr = e.toString();
|
||||||
|
if (errorStr.contains('already_used') ||
|
||||||
|
errorStr.contains('already_verified') ||
|
||||||
|
errorStr.contains('session_active')) {
|
||||||
|
if (mounted) {
|
||||||
|
_markVerificationApproved(
|
||||||
|
remoteApprovedMessage,
|
||||||
|
title: tr('ui.userfront.login.verification.title_remote'),
|
||||||
|
actionLabel: tr('ui.userfront.login.verification.action_label_close'),
|
||||||
|
onAction: () => webWindow.close(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
_showError(
|
_showError(
|
||||||
tr(
|
tr(
|
||||||
@@ -872,6 +908,8 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
"[Auth] Starting code verification for loginId: $sanitizedLoginId",
|
"[Auth] Starting code verification for loginId: $sanitizedLoginId",
|
||||||
);
|
);
|
||||||
final approvedMessage = tr('msg.userfront.login.verification.approved');
|
final approvedMessage = tr('msg.userfront.login.verification.approved');
|
||||||
|
final remoteApprovedMessage =
|
||||||
|
tr('msg.userfront.login.verification.approved_remote');
|
||||||
final localSessionMessage = tr(
|
final localSessionMessage = tr(
|
||||||
'msg.userfront.login.verification.approved_local',
|
'msg.userfront.login.verification.approved_local',
|
||||||
);
|
);
|
||||||
@@ -894,7 +932,12 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
|
|
||||||
if (jwt == null && status == 'approved') {
|
if (jwt == null && status == 'approved') {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
_markVerificationApproved(
|
||||||
|
remoteApprovedMessage,
|
||||||
|
title: tr('ui.userfront.login.verification.title_remote'),
|
||||||
|
actionLabel: tr('ui.userfront.login.verification.action_label_close'),
|
||||||
|
onAction: () => webWindow.close(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -908,7 +951,12 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_verificationOnly) {
|
if (_verificationOnly) {
|
||||||
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
_markVerificationApproved(
|
||||||
|
remoteApprovedMessage,
|
||||||
|
title: tr('ui.userfront.login.verification.title_remote'),
|
||||||
|
actionLabel: tr('ui.userfront.login.verification.action_label_close'),
|
||||||
|
onAction: () => webWindow.close(),
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_onLoginSuccess(jwt, provider: res['provider'] as String?);
|
_onLoginSuccess(jwt, provider: res['provider'] as String?);
|
||||||
@@ -916,12 +964,34 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_verificationOnly && mounted) {
|
if (_verificationOnly && mounted) {
|
||||||
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
_markVerificationApproved(
|
||||||
|
remoteApprovedMessage,
|
||||||
|
title: tr('ui.userfront.login.verification.title_remote'),
|
||||||
|
actionLabel: tr('ui.userfront.login.verification.action_label_close'),
|
||||||
|
onAction: () => webWindow.close(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint(
|
debugPrint(
|
||||||
"[Auth] Code verification FAILED for loginId: $sanitizedLoginId. Error: $e",
|
"[Auth] Code verification FAILED for loginId: $sanitizedLoginId. Error: $e",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Handle the case where the code is already verified/used (common in remote flows)
|
||||||
|
final errorStr = e.toString();
|
||||||
|
if (errorStr.contains('already_used') ||
|
||||||
|
errorStr.contains('already_verified') ||
|
||||||
|
errorStr.contains('session_active')) {
|
||||||
|
if (mounted) {
|
||||||
|
_markVerificationApproved(
|
||||||
|
remoteApprovedMessage,
|
||||||
|
title: tr('ui.userfront.login.verification.title_remote'),
|
||||||
|
actionLabel: tr('ui.userfront.login.verification.action_label_close'),
|
||||||
|
onAction: () => webWindow.close(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
_showError(
|
_showError(
|
||||||
tr(
|
tr(
|
||||||
@@ -938,6 +1008,8 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
if (sanitized.isEmpty) return;
|
if (sanitized.isEmpty) return;
|
||||||
debugPrint("[Auth] Starting short code verification for code: $sanitized");
|
debugPrint("[Auth] Starting short code verification for code: $sanitized");
|
||||||
final approvedMessage = tr('msg.userfront.login.verification.approved');
|
final approvedMessage = tr('msg.userfront.login.verification.approved');
|
||||||
|
final remoteApprovedMessage =
|
||||||
|
tr('msg.userfront.login.verification.approved_remote');
|
||||||
final localSessionMessage = tr(
|
final localSessionMessage = tr(
|
||||||
'msg.userfront.login.verification.approved_local',
|
'msg.userfront.login.verification.approved_local',
|
||||||
);
|
);
|
||||||
@@ -956,7 +1028,12 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
|
|
||||||
if (jwt == null && status == 'approved') {
|
if (jwt == null && status == 'approved') {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
_markVerificationApproved(
|
||||||
|
remoteApprovedMessage,
|
||||||
|
title: tr('ui.userfront.login.verification.title_remote'),
|
||||||
|
actionLabel: tr('ui.userfront.login.verification.action_label_close'),
|
||||||
|
onAction: () => webWindow.close(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -970,7 +1047,12 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_verificationOnly) {
|
if (_verificationOnly) {
|
||||||
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
_markVerificationApproved(
|
||||||
|
remoteApprovedMessage,
|
||||||
|
title: tr('ui.userfront.login.verification.title_remote'),
|
||||||
|
actionLabel: tr('ui.userfront.login.verification.action_label_close'),
|
||||||
|
onAction: () => webWindow.close(),
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_onLoginSuccess(jwt, provider: res['provider'] as String?);
|
_onLoginSuccess(jwt, provider: res['provider'] as String?);
|
||||||
@@ -978,10 +1060,32 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_verificationOnly && mounted) {
|
if (_verificationOnly && mounted) {
|
||||||
_markVerificationApproved(approvedMessage, actionPath: actionPath);
|
_markVerificationApproved(
|
||||||
|
remoteApprovedMessage,
|
||||||
|
title: tr('ui.userfront.login.verification.title_remote'),
|
||||||
|
actionLabel: tr('ui.userfront.login.verification.action_label_close'),
|
||||||
|
onAction: () => webWindow.close(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint("[Auth] Short code verification FAILED. Error: $e");
|
debugPrint("[Auth] Short code verification FAILED. Error: $e");
|
||||||
|
|
||||||
|
// Handle the case where the code is already verified/used (common in remote flows)
|
||||||
|
final errorStr = e.toString();
|
||||||
|
if (errorStr.contains('already_used') ||
|
||||||
|
errorStr.contains('already_verified') ||
|
||||||
|
errorStr.contains('session_active')) {
|
||||||
|
if (mounted) {
|
||||||
|
_markVerificationApproved(
|
||||||
|
remoteApprovedMessage,
|
||||||
|
title: tr('ui.userfront.login.verification.title_remote'),
|
||||||
|
actionLabel: tr('ui.userfront.login.verification.action_label_close'),
|
||||||
|
onAction: () => webWindow.close(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
_showError(
|
_showError(
|
||||||
tr(
|
tr(
|
||||||
|
|||||||
@@ -645,6 +645,8 @@ const Map<String, String> koStrings = {
|
|||||||
"msg.userfront.login.token_missing": "로그인 토큰을 확인할 수 없습니다.",
|
"msg.userfront.login.token_missing": "로그인 토큰을 확인할 수 없습니다.",
|
||||||
"msg.userfront.login.unregistered.body": "가입되지 않은 정보입니다.\\\\n회원가입 후 이용해 주세요.",
|
"msg.userfront.login.unregistered.body": "가입되지 않은 정보입니다.\\\\n회원가입 후 이용해 주세요.",
|
||||||
"msg.userfront.login.verification.approved": "승인되었습니다. 로그인은 요청하신 창에서 완료됩니다.",
|
"msg.userfront.login.verification.approved": "승인되었습니다. 로그인은 요청하신 창에서 완료됩니다.",
|
||||||
|
"msg.userfront.login.verification.approved_remote":
|
||||||
|
"승인되었습니다. 요청하신 브라우저 또는 PC 화면으로 돌아가 주세요.",
|
||||||
"msg.userfront.login.verification.approved_local":
|
"msg.userfront.login.verification.approved_local":
|
||||||
"승인 되었습니다. 이 기기는 로그인되어 있는 상태입니다. 원격 창도 로그인이 될 예정입니다",
|
"승인 되었습니다. 이 기기는 로그인되어 있는 상태입니다. 원격 창도 로그인이 될 예정입니다",
|
||||||
"msg.userfront.login.verification.success": "로그인 승인에 성공했습니다.",
|
"msg.userfront.login.verification.success": "로그인 승인에 성공했습니다.",
|
||||||
@@ -1914,8 +1916,10 @@ const Map<String, String> koStrings = {
|
|||||||
"ui.userfront.login.unregistered.action": "회원가입 하기",
|
"ui.userfront.login.unregistered.action": "회원가입 하기",
|
||||||
"ui.userfront.login.unregistered.title": "미등록 회원",
|
"ui.userfront.login.unregistered.title": "미등록 회원",
|
||||||
"ui.userfront.login.verification.action_label": "확인",
|
"ui.userfront.login.verification.action_label": "확인",
|
||||||
|
"ui.userfront.login.verification.action_label_close": "창 닫기",
|
||||||
"ui.userfront.login.verification.page_title": "로그인 승인",
|
"ui.userfront.login.verification.page_title": "로그인 승인",
|
||||||
"ui.userfront.login.verification.title": "승인 완료",
|
"ui.userfront.login.verification.title": "승인 완료",
|
||||||
|
"ui.userfront.login.verification.title_remote": "로그인 승인 완료",
|
||||||
"ui.userfront.login_success.later": "나중에 하기 (대시보드로 이동)",
|
"ui.userfront.login_success.later": "나중에 하기 (대시보드로 이동)",
|
||||||
"ui.userfront.login_success.qr": "QR 인증 (카메라 켜기)",
|
"ui.userfront.login_success.qr": "QR 인증 (카메라 켜기)",
|
||||||
"ui.userfront.login_success.title": "로그인 완료",
|
"ui.userfront.login_success.title": "로그인 완료",
|
||||||
@@ -2777,6 +2781,8 @@ const Map<String, String> enStrings = {
|
|||||||
"We could not find an account for that information.\\\\\\\\\\\\\\\\nPlease sign up before continuing.",
|
"We could not find an account for that information.\\\\\\\\\\\\\\\\nPlease sign up before continuing.",
|
||||||
"msg.userfront.login.verification.approved":
|
"msg.userfront.login.verification.approved":
|
||||||
"Approved. Complete sign-in in the original window.",
|
"Approved. Complete sign-in in the original window.",
|
||||||
|
"msg.userfront.login.verification.approved_remote":
|
||||||
|
"Approved. Please return to the original browser or PC screen.",
|
||||||
"msg.userfront.login.verification.approved_local":
|
"msg.userfront.login.verification.approved_local":
|
||||||
"Approved. This device is already signed in, and the remote window will be signed in shortly.",
|
"Approved. This device is already signed in, and the remote window will be signed in shortly.",
|
||||||
"msg.userfront.login.verification.success": "Sign-in approval completed.",
|
"msg.userfront.login.verification.success": "Sign-in approval completed.",
|
||||||
@@ -4110,8 +4116,10 @@ const Map<String, String> enStrings = {
|
|||||||
"ui.userfront.login.unregistered.action": "Create an account",
|
"ui.userfront.login.unregistered.action": "Create an account",
|
||||||
"ui.userfront.login.unregistered.title": "Account not found",
|
"ui.userfront.login.unregistered.title": "Account not found",
|
||||||
"ui.userfront.login.verification.action_label": "Done",
|
"ui.userfront.login.verification.action_label": "Done",
|
||||||
|
"ui.userfront.login.verification.action_label_close": "Close Window",
|
||||||
"ui.userfront.login.verification.page_title": "Sign-in approval",
|
"ui.userfront.login.verification.page_title": "Sign-in approval",
|
||||||
"ui.userfront.login.verification.title": "Approval complete",
|
"ui.userfront.login.verification.title": "Approval complete",
|
||||||
|
"ui.userfront.login.verification.title_remote": "Sign-in approved",
|
||||||
"ui.userfront.login_success.later": "Do this later (go to dashboard)",
|
"ui.userfront.login_success.later": "Do this later (go to dashboard)",
|
||||||
"ui.userfront.login_success.qr": "Use QR approval",
|
"ui.userfront.login_success.qr": "Use QR approval",
|
||||||
"ui.userfront.login_success.title": "Sign-in complete",
|
"ui.userfront.login_success.title": "Sign-in complete",
|
||||||
|
|||||||
Reference in New Issue
Block a user