1
0
forked from baron/baron-sso
Files
baron-sso/userfront/lib/features/auth/presentation/consent_screen.dart

124 lines
4.3 KiB
Dart

import 'dart:html' as html;
import 'package:flutter/material.dart';
import 'package:userfront/core/services/auth_proxy_service.dart';
class ConsentScreen extends StatefulWidget {
final String consentChallenge;
const ConsentScreen({super.key, required this.consentChallenge});
@override
State<ConsentScreen> createState() => _ConsentScreenState();
}
class _ConsentScreenState extends State<ConsentScreen> {
Map<String, dynamic>? _consentInfo;
bool _isLoading = true;
String? _error;
@override
void initState() {
super.initState();
_fetchConsentInfo();
}
Future<void> _fetchConsentInfo() async {
try {
final info = await AuthProxyService.getConsentInfo(widget.consentChallenge);
setState(() {
_consentInfo = info;
_isLoading = false;
});
} catch (e) {
setState(() {
_error = 'Failed to load consent information: $e';
_isLoading = false;
});
}
}
Future<void> _acceptConsent() async {
setState(() {
_isLoading = true;
_error = null;
});
try {
final result =
await AuthProxyService.acceptConsent(widget.consentChallenge);
if (result['redirectTo'] != null) {
html.window.location.href = result['redirectTo'];
} else {
setState(() {
_error = 'Consent accepted, but no redirect URL received.';
_isLoading = false;
});
}
} catch (e) {
setState(() {
_error = 'Failed to accept consent: $e';
_isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Grant Access')),
body: Center(
child: _isLoading
? const CircularProgressIndicator()
: _error != null
? Text(_error!, style: const TextStyle(color: Colors.red))
: _consentInfo != null
? Card(
elevation: 4,
margin: const EdgeInsets.all(16),
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'${_consentInfo!['client']?['client_name'] ?? 'An application'} wants to access your account',
style: Theme.of(context).textTheme.headlineSmall,
textAlign: TextAlign.center,
),
const SizedBox(height: 24),
const Text('This will allow the application to:'),
const SizedBox(height: 16),
if (_consentInfo!['requested_scope'] != null)
...(_consentInfo!['requested_scope'] as List)
.map((scope) => ListTile(
leading: const Icon(Icons.check_circle_outline),
title: Text(scope.toString()),
))
.toList(),
const SizedBox(height: 24),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
TextButton(
onPressed: () {
// TODO: Implement reject consent
html.window.alert('Consent rejected. You can close this window.');
},
child: const Text('Deny'),
),
ElevatedButton(
onPressed: _acceptConsent,
child: const Text('Allow'),
),
],
)
],
),
),
)
: const Text('No consent information available.'),
),
);
}
}