Skip to content

Commit c3968cb

Browse files
committed
fix oauth sign in
1 parent 0858a54 commit c3968cb

File tree

2 files changed

+138
-24
lines changed

2 files changed

+138
-24
lines changed

lib/screens/auth/webview_login_screen.dart

Lines changed: 123 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -341,30 +341,49 @@ class _WebViewLoginScreenState extends State<WebViewLoginScreen> {
341341
}
342342
}
343343

344-
// Check if we're on the AGiXT domain and on the chat page (successful login)
345-
final isAgixtDomain = uri.host.contains('agixt');
344+
// Check if we're on the app domain and on the chat page (successful login)
345+
// Use the configured appUri domain instead of hardcoding 'agixt'
346+
final appHost = Uri.parse(AuthService.appUri).host;
347+
final isAppDomain = uri.host == appHost ||
348+
uri.host.endsWith('.$appHost') ||
349+
uri.host.contains('agixt');
346350
final isOnChat = uri.path == '/chat' || uri.path.startsWith('/chat/');
347351

348-
if (isAgixtDomain && isOnChat) {
352+
if (isAppDomain && isOnChat) {
349353
debugPrint('WebView Login: Successfully landed on chat page');
350354
_hasCheckedAuth = true;
351355

352356
// We're on the chat page - try to extract the JWT
353357
String? jwtToken = await _extractJwtFromWebView();
354358

355359
if (jwtToken != null && jwtToken.isNotEmpty) {
356-
debugPrint('WebView Login: Found JWT token, storing it');
357-
await AuthService.storeJwt(jwtToken);
360+
debugPrint('WebView Login: Found JWT token from webview, navigating to home');
361+
await _handleSuccessfulLogin(jwtToken);
358362
} else {
359-
// Even if we couldn't extract the JWT, we're logged in via the web app cookies
360-
debugPrint(
361-
'WebView Login: No JWT found but on chat page - using cookie auth');
362-
await AuthService.setCookieAuthenticated(true);
363-
}
363+
// Try to get JWT from the API using the session cookies in the webview
364+
debugPrint('WebView Login: No JWT in storage, trying API extraction...');
365+
jwtToken = await _extractJwtFromApi();
366+
367+
if (jwtToken != null && jwtToken.isNotEmpty) {
368+
debugPrint('WebView Login: Got JWT from API, navigating to home');
369+
await _handleSuccessfulLogin(jwtToken);
370+
} else {
371+
// Fallback: use cookie-based auth
372+
debugPrint('WebView Login: No JWT found, using cookie auth fallback');
373+
await AuthService.setCookieAuthenticated(true);
374+
375+
if (mounted) {
376+
AGiXTApp.onLoginSuccess?.call();
377+
await Future.delayed(const Duration(milliseconds: 100));
364378

365-
// Mark as authenticated and stay on this page (don't navigate away)
366-
// The user is already on the chat page in this WebView, so let them continue
367-
await _markAuthenticatedAndStayInWebView();
379+
Navigator.of(context).pushNamedAndRemoveUntil(
380+
'/home',
381+
(route) => false,
382+
arguments: {'forceNewChat': true},
383+
);
384+
}
385+
}
386+
}
368387
}
369388
}
370389

@@ -1209,37 +1228,97 @@ class _WebViewLoginScreenState extends State<WebViewLoginScreen> {
12091228
}
12101229
}
12111230

1231+
/// Try to get a JWT by calling the user endpoint from within the webview
1232+
/// This works because the webview has the session cookies from SSO
1233+
Future<String?> _extractJwtFromApi() async {
1234+
if (_controller == null) return null;
1235+
1236+
try {
1237+
final serverUrl = AuthService.serverUrl;
1238+
final jsResult = await _controller!.runJavaScriptReturningResult('''
1239+
(async function() {
1240+
try {
1241+
// The jwt cookie should already be set by the Next.js middleware
1242+
// Try reading it directly first
1243+
var cookies = document.cookie.split(';');
1244+
for (var i = 0; i < cookies.length; i++) {
1245+
var cookie = cookies[i].trim();
1246+
if (cookie.startsWith('jwt=')) {
1247+
var val = cookie.substring(4);
1248+
// Decode URI component in case it's encoded
1249+
try { val = decodeURIComponent(val); } catch(e) {}
1250+
if (val && val.length > 20 && val !== 'null' && val !== 'undefined') {
1251+
return val;
1252+
}
1253+
}
1254+
}
1255+
return 'null';
1256+
} catch(e) {
1257+
return 'null';
1258+
}
1259+
})()
1260+
''');
1261+
1262+
if (jsResult != null && jsResult.toString() != 'null') {
1263+
var token = jsResult.toString().replaceAll('"', '').replaceAll("'", '');
1264+
if (token != 'null' && token.isNotEmpty && token.length > 20) {
1265+
debugPrint('WebView Login: Found JWT from API/cookie extraction');
1266+
return token;
1267+
}
1268+
}
1269+
} catch (e) {
1270+
debugPrint('WebView Login: Error extracting JWT from API: $e');
1271+
}
1272+
1273+
return null;
1274+
}
1275+
12121276
Future<String?> _extractJwtFromWebView() async {
12131277
if (_controller == null) return null;
12141278

12151279
try {
12161280
final jsResult = await _controller!.runJavaScriptReturningResult('''
12171281
(function() {
1282+
// PRIORITY: Check the 'jwt' cookie first - this is what the web app uses
1283+
var cookies = document.cookie.split(';');
1284+
for (var j = 0; j < cookies.length; j++) {
1285+
var cookie = cookies[j].trim();
1286+
if (cookie.startsWith('jwt=')) {
1287+
var val = cookie.substring(4);
1288+
try { val = decodeURIComponent(val); } catch(e) {}
1289+
if (val && val.length > 20 && val !== 'null' && val !== 'undefined') {
1290+
return val;
1291+
}
1292+
}
1293+
}
1294+
12181295
// Try localStorage with various keys
12191296
var keys = ['jwt', 'token', 'access_token', 'accessToken', 'auth_token', 'authToken', 'id_token', 'idToken'];
12201297
for (var i = 0; i < keys.length; i++) {
12211298
var token = localStorage.getItem(keys[i]);
1222-
if (token && token !== 'null' && token !== 'undefined') {
1299+
if (token && token !== 'null' && token !== 'undefined' && token.length > 20) {
12231300
return token;
12241301
}
12251302
}
12261303
12271304
// Try sessionStorage with various keys
12281305
for (var i = 0; i < keys.length; i++) {
12291306
var token = sessionStorage.getItem(keys[i]);
1230-
if (token && token !== 'null' && token !== 'undefined') {
1307+
if (token && token !== 'null' && token !== 'undefined' && token.length > 20) {
12311308
return token;
12321309
}
12331310
}
12341311
1235-
// Try cookies with various names
1236-
var cookieKeys = ['jwt', 'token', 'access_token', 'accessToken', 'auth_token', 'authToken'];
1237-
var cookies = document.cookie.split(';');
1312+
// Try other cookies with various names
1313+
var cookieKeys = ['token', 'access_token', 'accessToken', 'auth_token', 'authToken'];
12381314
for (var j = 0; j < cookies.length; j++) {
12391315
var cookie = cookies[j].trim();
12401316
for (var k = 0; k < cookieKeys.length; k++) {
12411317
if (cookie.startsWith(cookieKeys[k] + '=')) {
1242-
return cookie.substring(cookieKeys[k].length + 1);
1318+
var val = cookie.substring(cookieKeys[k].length + 1);
1319+
if (val && val.length > 20) {
1320+
return val;
1321+
}
12431322
}
12441323
}
12451324
}
@@ -1262,7 +1341,7 @@ class _WebViewLoginScreenState extends State<WebViewLoginScreen> {
12621341
if (jsResult != 'null' && jsResult.toString().isNotEmpty) {
12631342
// Remove quotes if present
12641343
var token = jsResult.toString().replaceAll('"', '').replaceAll("'", '');
1265-
if (token != 'null' && token.isNotEmpty) {
1344+
if (token != 'null' && token.isNotEmpty && token.length > 20) {
12661345
return token;
12671346
}
12681347
}
@@ -1296,8 +1375,30 @@ class _WebViewLoginScreenState extends State<WebViewLoginScreen> {
12961375
debugPrint(
12971376
'WebView Login: After storing JWT, isLoggedIn = $isNowLoggedIn');
12981377

1299-
// Stay in WebView instead of navigating away
1300-
await _markAuthenticatedAndStayInWebView();
1378+
if (!isNowLoggedIn) {
1379+
throw StateError('JWT was not stored properly');
1380+
}
1381+
1382+
setState(() {
1383+
_isAuthenticated = true;
1384+
});
1385+
1386+
if (mounted) {
1387+
// Notify the root state of successful login
1388+
debugPrint('WebView Login: Calling onLoginSuccess callback...');
1389+
AGiXTApp.onLoginSuccess?.call();
1390+
1391+
// Small delay to ensure state propagates
1392+
await Future.delayed(const Duration(milliseconds: 100));
1393+
1394+
// Navigate directly to home screen (like Phantom wallet flow)
1395+
debugPrint('WebView Login: Navigating to /home...');
1396+
Navigator.of(context).pushNamedAndRemoveUntil(
1397+
'/home',
1398+
(route) => false,
1399+
arguments: {'forceNewChat': true},
1400+
);
1401+
}
13011402
} catch (e) {
13021403
debugPrint('WebView Login: Error storing token: $e');
13031404
if (mounted) {

lib/screens/home_screen.dart

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,15 @@ class _HomePageState extends State<HomePage> {
316316
return NavigationDecision.navigate;
317317
}
318318

319-
if (!request.url.contains('agixt')) {
319+
// Check if this is an internal link by comparing against the app domain
320+
final requestUri = Uri.tryParse(request.url);
321+
final appHost = Uri.parse(AuthService.appUri).host;
322+
final isInternal = requestUri != null &&
323+
(requestUri.host == appHost ||
324+
requestUri.host.endsWith('.$appHost') ||
325+
request.url.contains('agixt'));
326+
327+
if (!isInternal) {
320328
// External link, launch in browser
321329
_launchInBrowser(request.url);
322330
return NavigationDecision.prevent;
@@ -1420,7 +1428,12 @@ class _HomePageState extends State<HomePage> {
14201428

14211429
/// Refresh the WebView content
14221430
Future<void> _refreshWebView() async {
1423-
if (_webViewController == null) return;
1431+
if (_webViewController == null) {
1432+
// WebView hasn't initialized yet - try to initialize it
1433+
debugPrint('HomeScreen: WebView controller is null, re-initializing');
1434+
await _initializeWebView();
1435+
return;
1436+
}
14241437

14251438
debugPrint('HomeScreen: Refreshing WebView content');
14261439
await _webViewController!.reload();

0 commit comments

Comments
 (0)