Skip to content

Commit 44d4357

Browse files
committed
refactor(auth): integrate FirebaseAuthenticator service
Refactors `app_dependencies.dart` to use the new `FirebaseAuthenticator` service for obtaining Firebase access tokens. This change removes the inline token generation logic, instantiates the new service, and provides it to the `firebaseHttpClient`. This improves separation of concerns and makes the dependency setup more readable and maintainable.
1 parent 99e39bd commit 44d4357

File tree

1 file changed

+11
-52
lines changed

1 file changed

+11
-52
lines changed

lib/src/config/app_dependencies.dart

Lines changed: 11 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// ignore_for_file: public_member_api_docs
22

33
import 'dart:async';
4+
45
import 'package:core/core.dart';
5-
import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
66
import 'package:data_mongodb/data_mongodb.dart';
77
import 'package:data_repository/data_repository.dart';
88
import 'package:email_repository/email_repository.dart';
@@ -17,6 +17,7 @@ import 'package:flutter_news_app_api_server_full_source_code/src/services/dashbo
1717
import 'package:flutter_news_app_api_server_full_source_code/src/services/database_migration_service.dart';
1818
import 'package:flutter_news_app_api_server_full_source_code/src/services/database_seeding_service.dart';
1919
import 'package:flutter_news_app_api_server_full_source_code/src/services/default_user_preference_limit_service.dart';
20+
import 'package:flutter_news_app_api_server_full_source_code/src/services/firebase_authenticator.dart';
2021
import 'package:flutter_news_app_api_server_full_source_code/src/services/firebase_push_notification_client.dart';
2122
import 'package:flutter_news_app_api_server_full_source_code/src/services/jwt_auth_token_service.dart';
2223
import 'package:flutter_news_app_api_server_full_source_code/src/services/mongodb_rate_limit_service.dart';
@@ -86,6 +87,7 @@ class AppDependencies {
8687
late final RateLimitService rateLimitService;
8788
late final CountryQueryService countryQueryService;
8889
late final IPushNotificationService pushNotificationService;
90+
late final IFirebaseAuthenticator firebaseAuthenticator;
8991
late final IPushNotificationClient firebasePushNotificationClient;
9092
late final IPushNotificationClient oneSignalPushNotificationClient;
9193

@@ -115,56 +117,6 @@ class AppDependencies {
115117
/// The core logic for initializing all dependencies.
116118
/// This method is private and should only be called once by [init].
117119
Future<void> _initializeDependencies() async {
118-
Future<String?> getFirebaseAccessToken() async {
119-
try {
120-
// Step 1: Create and sign the JWT.
121-
final pem = EnvironmentConfig.firebasePrivateKey.replaceAll(
122-
r'\n',
123-
'\n',
124-
);
125-
final privateKey = RSAPrivateKey(pem);
126-
final jwt = JWT(
127-
{'scope': 'https://www.googleapis.com/auth/cloud-platform'},
128-
issuer: EnvironmentConfig.firebaseClientEmail,
129-
audience: Audience.one('https://oauth2.googleapis.com/token'),
130-
);
131-
final signedToken = jwt.sign(
132-
privateKey,
133-
algorithm: JWTAlgorithm.RS256,
134-
expiresIn: const Duration(minutes: 5),
135-
);
136-
137-
// Step 2: Exchange the JWT for an access token.
138-
final tokenClient = HttpClient(
139-
baseUrl: 'https://oauth2.googleapis.com',
140-
// The tokenProvider for this client is null because this request
141-
// does not use a Bearer token.
142-
tokenProvider: () async => null,
143-
);
144-
145-
final response = await tokenClient.post<Map<String, dynamic>>(
146-
'/token',
147-
data: {
148-
'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
149-
'assertion': signedToken,
150-
},
151-
);
152-
153-
final accessToken = response['access_token'] as String?;
154-
if (accessToken == null) {
155-
throw const OperationFailedException(
156-
'Could not retrieve Firebase access token.',
157-
);
158-
}
159-
return accessToken;
160-
} catch (e, s) {
161-
_log.severe('Error during Firebase token exchange: $e', e, s);
162-
throw OperationFailedException(
163-
'Failed to authenticate with Firebase: $e',
164-
);
165-
}
166-
}
167-
168120
_log.info('Initializing application dependencies...');
169121
try {
170122
// 1. Initialize Database Connection
@@ -277,6 +229,13 @@ class AppDependencies {
277229
logger: Logger('DataMongodb<PushNotificationSubscription>'),
278230
);
279231

232+
// --- Initialize Firebase Authenticator ---
233+
// This dedicated service encapsulates the logic for obtaining a Firebase
234+
// access token, keeping the dependency setup clean.
235+
firebaseAuthenticator = FirebaseAuthenticator(
236+
log: Logger('FirebaseAuthenticator'),
237+
);
238+
280239
// --- Initialize HTTP clients for push notification providers ---
281240

282241
// The Firebase client requires a short-lived OAuth2 access token. This
@@ -286,7 +245,7 @@ class AppDependencies {
286245
final firebaseHttpClient = HttpClient(
287246
baseUrl:
288247
'https://fcm.googleapis.com/v1/projects/${EnvironmentConfig.firebaseProjectId}/',
289-
tokenProvider: getFirebaseAccessToken,
248+
tokenProvider: firebaseAuthenticator.getAccessToken,
290249
logger: Logger('FirebasePushNotificationClient'),
291250
);
292251

0 commit comments

Comments
 (0)