86 lines
2.8 KiB
Dart
86 lines
2.8 KiB
Dart
|
|
|
|
import 'package:logging/logging.dart';
|
|
|
|
import 'package:pshared/api/errors/unauthorized.dart';
|
|
import 'package:pshared/api/requests/tokens/access_refresh.dart';
|
|
import 'package:pshared/api/requests/tokens/refresh_rotate.dart';
|
|
import 'package:pshared/api/responses/account.dart';
|
|
import 'package:pshared/api/responses/login.dart';
|
|
import 'package:pshared/api/responses/token.dart';
|
|
import 'package:pshared/config/constants.dart';
|
|
import 'package:pshared/service/authorization/storage.dart';
|
|
import 'package:pshared/service/device_id.dart';
|
|
import 'package:pshared/service/services.dart';
|
|
import 'package:pshared/utils/http/requests.dart';
|
|
|
|
|
|
class TokenService {
|
|
static final _logger = Logger('service.authorization.token');
|
|
static const String _objectType = Services.account;
|
|
|
|
static bool _isTokenExpiringSoon(TokenData token, Duration duration) {
|
|
return token.expiration.isBefore(DateTime.now().add(duration));
|
|
}
|
|
|
|
static Future<String> getAccessToken() async {
|
|
TokenData token = await AuthorizationStorage.getAccessToken();
|
|
if (_isTokenExpiringSoon(token, const Duration(hours: 4))) {
|
|
token = (await _refreshAccessToken()).accessToken;
|
|
}
|
|
return token.token;
|
|
}
|
|
|
|
static Future<void> _updateTokens(LoginResponse response) async {
|
|
await AuthorizationStorage.updateToken(response.accessToken);
|
|
await AuthorizationStorage.updateRefreshToken(response.refreshToken);
|
|
}
|
|
|
|
static Future<AccountResponse> _refreshAccessToken() async {
|
|
_logger.fine('Refreshing access token...');
|
|
final deviceId = await DeviceIdManager.getDeviceId();
|
|
final refresh = await AuthorizationStorage.getRefreshToken();
|
|
|
|
if (_isTokenExpiringSoon(refresh, const Duration(days: 7))) {
|
|
return await rotateRefreshToken();
|
|
}
|
|
|
|
final response = await getPOSTResponse(
|
|
_objectType,
|
|
'/refresh',
|
|
AccessTokenRefreshRequest(
|
|
deviceId: deviceId,
|
|
clientId: Constants.clientId,
|
|
token: refresh.token,
|
|
).toJson(),
|
|
);
|
|
|
|
final accountResp = AccountResponse.fromJson(response);
|
|
await AuthorizationStorage.updateToken(accountResp.accessToken);
|
|
return accountResp;
|
|
}
|
|
|
|
static Future<LoginResponse> rotateRefreshToken() async {
|
|
_logger.fine('Rotating refresh token...');
|
|
final refresh = await AuthorizationStorage.getRefreshToken();
|
|
|
|
if (refresh.expiration.isBefore(DateTime.now())) throw ErrorUnauthorized();
|
|
|
|
final deviceId = await DeviceIdManager.getDeviceId();
|
|
final response = await getPOSTResponse(
|
|
_objectType,
|
|
'/rotate',
|
|
RotateRefreshTokenRequest(
|
|
token: refresh.token,
|
|
clientId: Constants.clientId,
|
|
deviceId: deviceId,
|
|
).toJson(),
|
|
);
|
|
|
|
final loginResponse = LoginResponse.fromJson(response);
|
|
await _updateTokens(loginResponse);
|
|
return loginResponse;
|
|
}
|
|
|
|
}
|