forked from baron/baron-sso
세션정보 누락 해결.
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:descope/descope.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import '../../../../core/services/auth_proxy_service.dart';
|
||||
import '../../../../core/services/auth_token_store.dart';
|
||||
@@ -49,9 +48,8 @@ class _ApproveQrScreenState extends State<ApproveQrScreen> {
|
||||
void _redirectIfNotLoggedIn() {
|
||||
if (_redirectingToLogin || !mounted) return;
|
||||
final hasStoredToken = AuthTokenStore.getToken() != null;
|
||||
final hasDescopeSession = Descope.sessionManager.session?.refreshToken.isExpired == false;
|
||||
final usesCookie = AuthTokenStore.usesCookie();
|
||||
final isLoggedIn = hasStoredToken || hasDescopeSession || usesCookie;
|
||||
final isLoggedIn = hasStoredToken || usesCookie;
|
||||
if (!isLoggedIn) {
|
||||
_redirectingToLogin = true;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
@@ -65,13 +63,12 @@ class _ApproveQrScreenState extends State<ApproveQrScreen> {
|
||||
if (widget.pendingRef == null) return;
|
||||
|
||||
final storedToken = AuthTokenStore.getToken();
|
||||
final session = Descope.sessionManager.session;
|
||||
final usesCookie = AuthTokenStore.usesCookie();
|
||||
var hasCookie = usesCookie;
|
||||
if (storedToken == null && (session == null || session.refreshToken.isExpired) && !hasCookie) {
|
||||
if (storedToken == null && !hasCookie) {
|
||||
hasCookie = await _bootstrapCookieSession();
|
||||
}
|
||||
if (storedToken == null && (session == null || session.refreshToken.isExpired) && !hasCookie) {
|
||||
if (storedToken == null && !hasCookie) {
|
||||
if (mounted) {
|
||||
context.go('/signin?notice=qr_login_required');
|
||||
}
|
||||
@@ -84,7 +81,7 @@ class _ApproveQrScreenState extends State<ApproveQrScreen> {
|
||||
});
|
||||
// jwt 유효성 확인
|
||||
try {
|
||||
final token = storedToken ?? session?.sessionToken.jwt ?? '';
|
||||
final token = storedToken ?? '';
|
||||
await AuthProxyService.approveQrLogin(
|
||||
widget.pendingRef!,
|
||||
token: token,
|
||||
@@ -109,9 +106,8 @@ class _ApproveQrScreenState extends State<ApproveQrScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final hasStoredToken = AuthTokenStore.getToken() != null;
|
||||
final hasDescopeSession = Descope.sessionManager.session?.refreshToken.isExpired == false;
|
||||
final usesCookie = AuthTokenStore.usesCookie();
|
||||
final isLoggedIn = hasStoredToken || hasDescopeSession || usesCookie || _isCheckingSession;
|
||||
final isLoggedIn = hasStoredToken || usesCookie || _isCheckingSession;
|
||||
|
||||
if (!isLoggedIn && !_redirectingToLogin) {
|
||||
_redirectIfNotLoggedIn();
|
||||
|
||||
@@ -2,7 +2,6 @@ import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:descope/descope.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
@@ -191,7 +190,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
});
|
||||
}
|
||||
|
||||
// Helper to decode JWT and get loginId
|
||||
// JWT를 디코딩해 표시용 로그인 아이디 추출
|
||||
String _getLoginIdFromJwt(String jwt) {
|
||||
try {
|
||||
final parts = jwt.split('.');
|
||||
@@ -199,7 +198,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
|
||||
final payload = utf8.decode(base64Url.decode(base64Url.normalize(parts[1])));
|
||||
final data = json.decode(payload);
|
||||
// Descope tokens usually have 'name', 'email', or 'sub'
|
||||
// 일반적으로 name/email/sub 필드를 사용
|
||||
return data['name'] ?? data['email'] ?? data['sub'] ?? 'User';
|
||||
} catch (e) {
|
||||
debugPrint("[JWT] Decode error: $e");
|
||||
@@ -207,20 +206,6 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to decode JWT and get User ID (sub claim)
|
||||
String _getUserIdFromJwt(String jwt) {
|
||||
try {
|
||||
final parts = jwt.split('.');
|
||||
if (parts.length != 3) return 'unknown';
|
||||
final payload = utf8.decode(base64Url.decode(base64Url.normalize(parts[1])));
|
||||
final data = json.decode(payload) as Map<String, dynamic>;
|
||||
return data['sub'] as String? ?? 'unknown';
|
||||
} catch (e) {
|
||||
debugPrint("[JWT] Could not extract User ID (sub): $e");
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
|
||||
void _handleTabSelection() {
|
||||
// QR 탭 (세 번째 탭, index 2)이 선택되었을 때 QR 플로우 시작
|
||||
if (_tabController.index == 2 && _qrPendingRef == null) {
|
||||
@@ -350,12 +335,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
}) {
|
||||
final isJwt = token.split('.').length == 3;
|
||||
if (isJwt) {
|
||||
final displayName = _getLoginIdFromJwt(token);
|
||||
final dummyUser = DescopeUser(
|
||||
'unknown', [], 0, displayName, null, '', false, '', false, {}, '', '', '', false, 'enabled', [], [], [],
|
||||
);
|
||||
final session = DescopeSession.fromJwt(token, token, dummyUser);
|
||||
Descope.sessionManager.manageSession(session);
|
||||
_getLoginIdFromJwt(token);
|
||||
}
|
||||
|
||||
if (!mounted) return;
|
||||
@@ -813,33 +793,14 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
|
||||
_logTokenDetails(token);
|
||||
|
||||
final userId = _getUserIdFromJwt(token);
|
||||
final providerName = provider ?? AuthTokenStore.getProvider();
|
||||
final isJwt = token.split('.').length == 3;
|
||||
final isOry = (providerName ?? '').toLowerCase().contains('ory') || !isJwt;
|
||||
|
||||
AuthTokenStore.setToken(token, provider: providerName);
|
||||
AuthTokenStore.clearPendingProvider();
|
||||
|
||||
// [New] 로그인 성공 직후 백엔드에서 전체 프로필 정보를 가져와 세션 업데이트
|
||||
// 로그인 성공 직후 백엔드에서 전체 프로필 정보를 가져와 세션 업데이트
|
||||
try {
|
||||
if (!isOry) {
|
||||
// 임시 세션 생성 (API 호출을 위해)
|
||||
final tempUser = DescopeUser(userId, [], 0, 'User', null, '', false, '', false, {}, '', '', '', false, 'enabled', [], [], []);
|
||||
final tempSession = DescopeSession.fromJwt(token, token, tempUser);
|
||||
Descope.sessionManager.manageSession(tempSession);
|
||||
}
|
||||
|
||||
// 백엔드 GetMe 호출 (프로필 노티파이어 사용)
|
||||
final profile = await ref.read(profileProvider.notifier).loadProfile();
|
||||
if (profile != null && !isOry) {
|
||||
// 실제 정보로 세션 유저 정보 교체
|
||||
final realUser = DescopeUser(
|
||||
userId, [], 0, profile.name, null, profile.email, false, profile.phone, false, {}, '', '', '', false, 'enabled', [], [], [],
|
||||
);
|
||||
final realSession = DescopeSession.fromJwt(token, token, realUser);
|
||||
Descope.sessionManager.manageSession(realSession);
|
||||
}
|
||||
await ref.read(profileProvider.notifier).loadProfile();
|
||||
} catch (e) {
|
||||
debugPrint("[Auth] Failed to pre-fetch profile: $e");
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:mobile_scanner/mobile_scanner.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:descope/descope.dart';
|
||||
import '../../../core/services/auth_proxy_service.dart';
|
||||
import '../../../core/services/auth_token_store.dart';
|
||||
|
||||
@@ -94,7 +93,7 @@ class _QRScanScreenState extends State<QRScanScreen> {
|
||||
final approveRef = qrData;
|
||||
|
||||
final storedToken = AuthTokenStore.getToken();
|
||||
final sessionToken = storedToken ?? Descope.sessionManager.session?.sessionToken.jwt;
|
||||
final sessionToken = storedToken;
|
||||
var usesCookie = AuthTokenStore.usesCookie();
|
||||
if (sessionToken == null && !usesCookie) {
|
||||
usesCookie = await _bootstrapCookieSession();
|
||||
|
||||
Reference in New Issue
Block a user