forked from baron/baron-sso
userfront 로그인 후 /dashboard로 이동하게 변경
This commit is contained in:
@@ -9,9 +9,11 @@ import '../../../core/widgets/language_selector.dart';
|
||||
import '../../../core/services/web_auth_integration.dart';
|
||||
import '../../../core/services/auth_proxy_service.dart';
|
||||
import '../../../core/services/auth_token_store.dart';
|
||||
import '../../../core/i18n/locale_utils.dart';
|
||||
import '../../../core/services/oidc_redirect_guard.dart';
|
||||
import '../../../core/notifiers/auth_notifier.dart';
|
||||
import '../domain/login_challenge_resolver.dart';
|
||||
import '../domain/cookie_session_policy.dart';
|
||||
import '../../profile/domain/notifiers/profile_notifier.dart';
|
||||
import '../../../core/services/web_window.dart';
|
||||
|
||||
@@ -65,6 +67,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
bool _verificationOnly = false;
|
||||
bool _verificationApproved = false;
|
||||
bool _dismissedOverlays = false;
|
||||
bool _localNavigationCompleted = false;
|
||||
String _verificationMessage = '';
|
||||
String _verificationTitle = tr('ui.userfront.login.verification.title');
|
||||
String _verificationPageTitle = tr(
|
||||
@@ -125,7 +128,11 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
if (hasLoginCode) {
|
||||
_verifyLoginCode(loginIdParam, codeParam, pendingRef: pendingRefParam);
|
||||
} else if (hasVerificationToken) {
|
||||
_verifyToken(widget.verificationToken ?? uri.queryParameters['t']!);
|
||||
final verificationToken =
|
||||
widget.verificationToken ?? uri.queryParameters['t'];
|
||||
if (verificationToken != null && verificationToken.isNotEmpty) {
|
||||
_verifyToken(verificationToken);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_noticeHandled && notice == 'qr_login_required') {
|
||||
@@ -142,8 +149,12 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
}
|
||||
|
||||
Future<void> _tryCookieSession({bool silent = true}) async {
|
||||
if (AuthTokenStore.getToken() != null &&
|
||||
(_loginChallenge == null || _loginChallenge!.isEmpty)) {
|
||||
final loginChallenge = _loginChallenge;
|
||||
final token = AuthTokenStore.getToken();
|
||||
if (!shouldPromoteCookieSession(
|
||||
currentToken: token,
|
||||
loginChallenge: loginChallenge,
|
||||
)) {
|
||||
return;
|
||||
}
|
||||
final pendingProvider = AuthTokenStore.getPendingProvider();
|
||||
@@ -151,6 +162,12 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
|
||||
try {
|
||||
await AuthProxyService.checkCookieSession();
|
||||
if (!shouldPromoteCookieSession(
|
||||
currentToken: AuthTokenStore.getToken(),
|
||||
loginChallenge: loginChallenge,
|
||||
)) {
|
||||
return;
|
||||
}
|
||||
AuthTokenStore.setCookieMode(provider: provider);
|
||||
AuthTokenStore.clearPendingProvider();
|
||||
if (mounted) {
|
||||
@@ -171,7 +188,6 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
|
||||
Future<void> _onCookieLoginSuccess(String provider) async {
|
||||
debugPrint("[Auth] Cookie-based login success. Provider: $provider");
|
||||
AuthNotifier.instance.notify();
|
||||
if (_hasLoginChallenge) {
|
||||
final accepted = await _acceptOidcLoginAndRedirect();
|
||||
if (accepted) {
|
||||
@@ -185,8 +201,9 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
|
||||
final token = AuthTokenStore.getToken();
|
||||
if (token != null && token.isNotEmpty) {
|
||||
final redirectUrl = _redirectUrl;
|
||||
if (WebAuthIntegration.isPopup() ||
|
||||
(_redirectUrl != null && _redirectUrl!.isNotEmpty)) {
|
||||
(redirectUrl != null && redirectUrl.isNotEmpty)) {
|
||||
debugPrint(
|
||||
"[Auth] Cookie session with external integration. Notifying...",
|
||||
);
|
||||
@@ -196,14 +213,23 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
context.go('/');
|
||||
_goLocalizedHomeOnce();
|
||||
}
|
||||
}
|
||||
|
||||
void _goLocalizedHomeOnce() {
|
||||
if (!mounted || _localNavigationCompleted) {
|
||||
return;
|
||||
}
|
||||
_localNavigationCompleted = true;
|
||||
context.go(buildLocalizedHomePath(Uri.base));
|
||||
}
|
||||
|
||||
Future<void> _attemptOidcAutoAccept() async {
|
||||
if (_oidcAutoAcceptTried) return;
|
||||
_oidcAutoAcceptTried = true;
|
||||
if (_loginChallenge == null || _loginChallenge!.isEmpty) {
|
||||
final loginChallenge = _loginChallenge;
|
||||
if (loginChallenge == null || loginChallenge.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -227,12 +253,13 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
}
|
||||
|
||||
Future<bool> _acceptOidcLoginAndRedirect({String? token}) async {
|
||||
if (_loginChallenge == null || _loginChallenge!.isEmpty) {
|
||||
final loginChallenge = _loginChallenge;
|
||||
if (loginChallenge == null || loginChallenge.isEmpty) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
final res = await AuthProxyService.acceptOidcLogin(
|
||||
_loginChallenge!,
|
||||
loginChallenge,
|
||||
token: token,
|
||||
);
|
||||
final redirectTo = res['redirectTo'] as String?;
|
||||
@@ -274,8 +301,10 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
}
|
||||
}
|
||||
|
||||
bool get _hasLoginChallenge =>
|
||||
_loginChallenge != null && _loginChallenge!.isNotEmpty;
|
||||
bool get _hasLoginChallenge {
|
||||
final loginChallenge = _loginChallenge;
|
||||
return loginChallenge != null && loginChallenge.isNotEmpty;
|
||||
}
|
||||
|
||||
LoginChallengeResolution _resolveLoginChallenge(Uri uri) {
|
||||
return resolveLoginChallenge(
|
||||
@@ -486,7 +515,11 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
}
|
||||
|
||||
try {
|
||||
final res = await AuthProxyService.pollQrStatus(_qrPendingRef!);
|
||||
final pendingRef = _qrPendingRef;
|
||||
if (pendingRef == null || pendingRef.isEmpty) {
|
||||
return;
|
||||
}
|
||||
final res = await AuthProxyService.pollQrStatus(pendingRef);
|
||||
if (res['error'] == 'slow_down') {
|
||||
final interval = res['interval'];
|
||||
if (interval is int && interval > 0) {
|
||||
@@ -656,9 +689,11 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
FilledButton(
|
||||
onPressed: () {
|
||||
final hasLocalSession =
|
||||
AuthTokenStore.getToken() != null ||
|
||||
(AuthTokenStore.getToken()?.isNotEmpty ?? false) ||
|
||||
AuthTokenStore.usesCookie();
|
||||
final target = hasLocalSession ? '/' : '/signin';
|
||||
final target = hasLocalSession
|
||||
? buildLocalizedHomePath(Uri.base)
|
||||
: buildLocalizedSigninPath(Uri.base);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_verificationOnly = false;
|
||||
@@ -691,7 +726,9 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
final jwt = res['token'] ?? res['sessionJwt'] ?? res['sessionToken'];
|
||||
final status = res['status']?.toString();
|
||||
final hasLocalSession = await _hasValidLocalSession();
|
||||
final actionPath = hasLocalSession ? '/' : '/signin';
|
||||
final actionPath = hasLocalSession
|
||||
? buildLocalizedHomePath(Uri.base)
|
||||
: buildLocalizedSigninPath(Uri.base);
|
||||
|
||||
if (status == 'approved' || (jwt == null && _verificationOnly)) {
|
||||
if (mounted) {
|
||||
@@ -754,7 +791,9 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
"[Auth] Code verification successful for loginId: $sanitizedLoginId",
|
||||
);
|
||||
final hasLocalSession = await _hasValidLocalSession();
|
||||
final actionPath = hasLocalSession ? '/' : '/signin';
|
||||
final actionPath = hasLocalSession
|
||||
? buildLocalizedHomePath(Uri.base)
|
||||
: buildLocalizedSigninPath(Uri.base);
|
||||
|
||||
if (jwt == null && status == 'approved') {
|
||||
if (mounted) {
|
||||
@@ -814,7 +853,9 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
final status = res['status']?.toString();
|
||||
debugPrint("[Auth] Short code verification successful");
|
||||
final hasLocalSession = await _hasValidLocalSession();
|
||||
final actionPath = hasLocalSession ? '/' : '/signin';
|
||||
final actionPath = hasLocalSession
|
||||
? buildLocalizedHomePath(Uri.base)
|
||||
: buildLocalizedSigninPath(Uri.base);
|
||||
|
||||
if (jwt == null && status == 'approved') {
|
||||
if (mounted) {
|
||||
@@ -1147,14 +1188,15 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
}
|
||||
|
||||
// [Priority 2] OIDC Challenge Handling
|
||||
if (_loginChallenge != null && _loginChallenge!.isNotEmpty) {
|
||||
final loginChallenge = _loginChallenge;
|
||||
if (loginChallenge != null && loginChallenge.isNotEmpty) {
|
||||
try {
|
||||
// Save token first, it's needed for acceptance
|
||||
final providerName = provider ?? AuthTokenStore.getProvider();
|
||||
AuthTokenStore.setToken(token, provider: providerName);
|
||||
|
||||
final res = await AuthProxyService.acceptOidcLogin(
|
||||
_loginChallenge!,
|
||||
loginChallenge,
|
||||
token: token,
|
||||
);
|
||||
final nextRedirectTo = res['redirectTo'] as String?;
|
||||
@@ -1196,9 +1238,8 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
return;
|
||||
}
|
||||
|
||||
AuthNotifier.instance.notify();
|
||||
if (mounted) {
|
||||
context.go('/');
|
||||
_goLocalizedHomeOnce();
|
||||
}
|
||||
} catch (globalErr) {
|
||||
// ignore
|
||||
@@ -1237,7 +1278,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
title: Text(_verificationPageTitle),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () => context.go('/'),
|
||||
onPressed: () => context.go(buildLocalizedHomePath(Uri.base)),
|
||||
),
|
||||
),
|
||||
body: _buildVerificationResultView(),
|
||||
|
||||
Reference in New Issue
Block a user