⚡ Optimized refresh credentials
This commit is contained in:
parent
22ee817676
commit
75c753ef63
@ -56,10 +56,10 @@ class AccountProvider extends GetxController {
|
||||
final AuthProvider auth = Get.find();
|
||||
await auth.ensureCredentials();
|
||||
|
||||
if (globalCredentials == null) await auth.loadCredentials();
|
||||
if (auth.credentials == null) await auth.loadCredentials();
|
||||
|
||||
final uri = Uri.parse(
|
||||
'${ServiceFinder.services['passport']}/api/ws?tk=${globalCredentials!.accessToken}'
|
||||
'${ServiceFinder.services['passport']}/api/ws?tk=${auth.credentials!.accessToken}'
|
||||
.replaceFirst('http', 'ws'),
|
||||
);
|
||||
|
||||
|
@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get_connect/http/src/request/request.dart';
|
||||
import 'package:mutex/mutex.dart';
|
||||
import 'package:solian/controllers/chat_events_controller.dart';
|
||||
import 'package:solian/providers/account.dart';
|
||||
import 'package:solian/providers/chat.dart';
|
||||
@ -39,8 +40,6 @@ class TokenSet {
|
||||
bool get isExpired => expiredAt?.isBefore(DateTime.now()) ?? true;
|
||||
}
|
||||
|
||||
TokenSet? globalCredentials;
|
||||
|
||||
class RiskyAuthenticateException implements Exception {
|
||||
final int ticketId;
|
||||
|
||||
@ -56,6 +55,9 @@ class AuthProvider extends GetConnect {
|
||||
|
||||
static const storage = FlutterSecureStorage();
|
||||
|
||||
TokenSet? credentials;
|
||||
Mutex credentialsRefreshMutex = Mutex();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
httpClient.baseUrl = ServiceFinder.services['passport'];
|
||||
@ -63,28 +65,36 @@ class AuthProvider extends GetConnect {
|
||||
}
|
||||
|
||||
Future<void> refreshCredentials() async {
|
||||
try {
|
||||
credentialsRefreshMutex.acquire();
|
||||
if (!credentials!.isExpired) return;
|
||||
final resp = await post('/api/auth/token', {
|
||||
'refresh_token': globalCredentials!.refreshToken,
|
||||
'refresh_token': credentials!.refreshToken,
|
||||
'grant_type': 'refresh_token',
|
||||
});
|
||||
if (resp.statusCode != 200) {
|
||||
throw Exception(resp.bodyString);
|
||||
}
|
||||
globalCredentials = TokenSet(
|
||||
credentials = TokenSet(
|
||||
accessToken: resp.body['access_token'],
|
||||
refreshToken: resp.body['refresh_token'],
|
||||
expiredAt: DateTime.now().add(const Duration(minutes: 3)),
|
||||
);
|
||||
storage.write(
|
||||
key: 'auth_credentials',
|
||||
value: jsonEncode(globalCredentials!.toJson()),
|
||||
value: jsonEncode(credentials!.toJson()),
|
||||
);
|
||||
} catch (_) {
|
||||
rethrow;
|
||||
} finally {
|
||||
credentialsRefreshMutex.release();
|
||||
}
|
||||
}
|
||||
|
||||
Future<Request<T?>> requestAuthenticator<T>(Request<T?> request) async {
|
||||
try {
|
||||
await ensureCredentials();
|
||||
request.headers['Authorization'] = 'Bearer ${globalCredentials!.accessToken}';
|
||||
request.headers['Authorization'] = 'Bearer ${credentials!.accessToken}';
|
||||
} catch (_) {}
|
||||
|
||||
return request;
|
||||
@ -108,9 +118,9 @@ class AuthProvider extends GetConnect {
|
||||
|
||||
Future<void> ensureCredentials() async {
|
||||
if (!await isAuthorized) throw Exception('unauthorized');
|
||||
if (globalCredentials == null) await loadCredentials();
|
||||
if (credentials == null) await loadCredentials();
|
||||
|
||||
if (globalCredentials!.isExpired) {
|
||||
if (credentials!.isExpired) {
|
||||
await refreshCredentials();
|
||||
log('Refreshed credentials at ${DateTime.now()}');
|
||||
}
|
||||
@ -119,7 +129,7 @@ class AuthProvider extends GetConnect {
|
||||
Future<void> loadCredentials() async {
|
||||
if (await isAuthorized) {
|
||||
final content = await storage.read(key: 'auth_credentials');
|
||||
globalCredentials = TokenSet.fromJson(jsonDecode(content!));
|
||||
credentials = TokenSet.fromJson(jsonDecode(content!));
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,7 +162,7 @@ class AuthProvider extends GetConnect {
|
||||
throw Exception(tokenResp.bodyString);
|
||||
}
|
||||
|
||||
globalCredentials = TokenSet(
|
||||
credentials = TokenSet(
|
||||
accessToken: tokenResp.body['access_token'],
|
||||
refreshToken: tokenResp.body['refresh_token'],
|
||||
expiredAt: DateTime.now().add(const Duration(minutes: 3)),
|
||||
@ -160,14 +170,14 @@ class AuthProvider extends GetConnect {
|
||||
|
||||
storage.write(
|
||||
key: 'auth_credentials',
|
||||
value: jsonEncode(globalCredentials!.toJson()),
|
||||
value: jsonEncode(credentials!.toJson()),
|
||||
);
|
||||
|
||||
Get.find<AccountProvider>().connect();
|
||||
Get.find<AccountProvider>().notifyPrefetch();
|
||||
Get.find<ChatProvider>().connect();
|
||||
|
||||
return globalCredentials!;
|
||||
return credentials!;
|
||||
}
|
||||
|
||||
void signout() {
|
||||
|
@ -26,10 +26,10 @@ class ChatProvider extends GetxController {
|
||||
final AuthProvider auth = Get.find();
|
||||
await auth.ensureCredentials();
|
||||
|
||||
if (globalCredentials == null) await auth.loadCredentials();
|
||||
if (auth.credentials == null) await auth.loadCredentials();
|
||||
|
||||
final uri = Uri.parse(
|
||||
'${ServiceFinder.services['messaging']}/api/ws?tk=${globalCredentials!.accessToken}'
|
||||
'${ServiceFinder.services['messaging']}/api/ws?tk=${auth.credentials!.accessToken}'
|
||||
.replaceFirst('http', 'ws'),
|
||||
);
|
||||
|
||||
|
@ -1008,6 +1008,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
mutex:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: mutex
|
||||
sha256: "8827da25de792088eb33e572115a5eb0d61d61a3c01acbc8bcbe76ed78f1a1f2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
nm:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -53,6 +53,7 @@ dependencies:
|
||||
media_kit_video: ^1.2.4
|
||||
media_kit_libs_video: ^1.0.4
|
||||
textfield_tags: ^3.0.1
|
||||
mutex: ^3.1.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Loading…
Reference in New Issue
Block a user