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 getAccessToken() async { TokenData token = await AuthorizationStorage.getAccessToken(); if (_isTokenExpiringSoon(token, const Duration(hours: 4))) { token = (await _refreshAccessToken()).accessToken; } return token.token; } static Future _updateTokens(LoginResponse response) async { await AuthorizationStorage.updateToken(response.accessToken); await AuthorizationStorage.updateRefreshToken(response.refreshToken); } static Future _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 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; } }