Files
swift_companion/swiftyCompanion/swifty_companion/lib/services/intra_auth_service.dart
2026-09-29 15:07:05 +02:00

79 lines
2.2 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:convert';
import 'package:flutter_appauth/flutter_appauth.dart';
import 'package:http/http.dart' as http;
import '../config/intra_config.dart';
/// OAuth2 Intra : un token réutilisé pour toutes les requêtes API.
class IntraAuthService {
IntraAuthService._();
static final IntraAuthService instance = IntraAuthService._();
final FlutterAppAuth _appAuth = const FlutterAppAuth();
String? _accessToken;
String? get accessToken => _accessToken;
bool get isAuthenticated => _accessToken != null && _accessToken!.isNotEmpty;
static final AuthorizationServiceConfiguration _serviceConfiguration =
AuthorizationServiceConfiguration(
authorizationEndpoint: IntraConfig.authorizeUrl,
tokenEndpoint: IntraConfig.tokenUrl,
);
Future<void> signIn() async {
if (!IntraConfig.isConfigured) {
throw StateError(
'CLIENT_ID, CLIENT_SECRET ou REDIRECT_URI manquant dans .env',
);
}
final result = await _appAuth.authorizeAndExchangeCode(
AuthorizationTokenRequest(
IntraConfig.clientId,
IntraConfig.redirectUri,
clientSecret: IntraConfig.clientSecret,
serviceConfiguration: _serviceConfiguration,
// `projects` requis pour projects_users ; skills via cursus_users (pas /experiences).
scopes: ['public', 'projects'],
),
);
_accessToken = result.accessToken;
if (!isAuthenticated) {
throw StateError('Connexion 42 annulée ou token absent');
}
}
void signOut() {
_accessToken = null;
}
/// Header Authorization pour les appels `api.intra.42.fr`.
Map<String, String> authHeaders() {
if (!isAuthenticated) {
throw StateError('Non connecté à l’Intra');
}
return {
'Authorization': 'Bearer $_accessToken',
'Accept': 'application/json',
};
}
Future<Map<String, dynamic>> fetchMe() async {
final response = await http.get(
Uri.parse('${IntraConfig.apiBaseUrl}/me'),
headers: authHeaders(),
);
if (response.statusCode != 200) {
throw Exception('GET /v2/me a échoué (${response.statusCode})');
}
return jsonDecode(response.body) as Map<String, dynamic>;
}
}