1
0
forked from baron/baron-sso

논리 검사 계속. 스케폴딩 일부 진행

This commit is contained in:
Lectom C Han
2025-12-23 17:59:37 +09:00
parent 48589dca5d
commit 904b35e6e6
15 changed files with 556 additions and 77 deletions

View File

@@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:descope/descope.dart';
import 'package:go_router/go_router.dart';
class LoginScreen extends ConsumerStatefulWidget {
const LoginScreen({super.key});
@@ -31,14 +33,133 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
super.dispose();
}
void _handleEmailLogin() {
// TODO: Implement Descope Email/Password Flow
debugPrint("Email Login: ${_emailController.text}");
Future<void> _handleEmailLogin() async {
final email = _emailController.text.trim();
if (email.isEmpty) return;
// Determine if it's Password or Enchanted Link flow
// For this PoC, we'll try Enchanted Link as primary for 'Email' tab per requirements,
// but the UI has a password field. Let's support both based on input.
// However, PRD says Primary is Email/Password.
final password = _passwordController.text;
if (password.isNotEmpty) {
// Email + Password Flow
try {
final authResponse = await Descope.auth.password.signIn(
loginId: email,
password: password,
);
final session = DescopeSession.fromAuthenticationResponse(authResponse);
Descope.sessionManager.manageSession(session);
if (mounted) context.go('/dashboard');
} catch (e) {
_showError("Email/Password Login Failed: $e");
}
} else {
// Enchanted Link Flow (Passwordless)
try {
// Start Enchanted Link
final response = await Descope.auth.enchantedLink.signUpOrIn(
loginId: email,
uri: "baronsso://auth", // Deep link for the 'Clicked' device
);
// Show Polling Dialog
if (mounted) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => AlertDialog(
title: const Text("Check your Email"),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text("We sent an email to $email"),
const SizedBox(height: 16),
const LinearProgressIndicator(),
const SizedBox(height: 16),
Text("Link: ${response.linkId}"), // Display for debug/PoC
],
),
),
);
// Poll for completion
final authResponse = await Descope.auth.enchantedLink.poll(
response.pendingRef,
);
final session = DescopeSession.fromAuthenticationResponse(
authResponse,
);
Descope.sessionManager.manageSession(session);
if (mounted) {
Navigator.of(context).pop(); // Close Dialog
context.go('/dashboard');
}
}
} catch (e) {
if (mounted) Navigator.of(context).pop(); // Close dialog if open
_showError("Enchanted Link Failed: $e");
}
}
}
void _handleSmsLogin() {
// TODO: Implement Descope SMS Enchanted Link Flow
debugPrint("SMS Login: ${_phoneController.text}");
Future<void> _handleSmsLogin() async {
final phone = _phoneController.text.trim();
if (phone.isEmpty) return;
try {
// Enchanted Link via SMS (Polling)
// Note: This assumes Descope project is configured to send SMS for this loginId
final response = await Descope.auth.enchantedLink.signUpOrIn(
loginId: phone,
uri: "baronsso://auth", // Link for the device that receives SMS
);
if (mounted) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => AlertDialog(
title: const Text("Check your Messages"),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text("We sent a message to $phone"),
const SizedBox(height: 16),
const LinearProgressIndicator(),
const SizedBox(height: 16),
// Text("Link: ${response.linkId}"), // Debug
],
),
),
);
// Poll for completion
final authResponse = await Descope.auth.enchantedLink.poll(
response.pendingRef,
);
final session = DescopeSession.fromAuthenticationResponse(authResponse);
Descope.sessionManager.manageSession(session);
if (mounted) {
Navigator.of(context).pop(); // Close Dialog
context.go('/dashboard');
}
}
} catch (e) {
if (mounted && Navigator.canPop(context)) Navigator.of(context).pop();
_showError("SMS Enchanted Link Failed: $e");
}
}
void _showError(String message) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(message), backgroundColor: Colors.red),
);
}
@override

View File

@@ -18,7 +18,7 @@ void main() async {
// Initialize Descope
final projectId = dotenv.env['DESCOPE_PROJECT_ID'] ?? 'your-project-id';
Descope.projectId = projectId;
Descope.setup(projectId);
// Load saved session if any
await Descope.sessionManager.loadSession();