implementation of security service
This commit is contained in:
parent
71a48750bd
commit
0e9c2e0055
@ -40,6 +40,7 @@ import 'package:on_field_work/model/service_project/service_project_job_detail_m
|
|||||||
import 'package:on_field_work/model/service_project/job_attendance_logs_model.dart';
|
import 'package:on_field_work/model/service_project/job_attendance_logs_model.dart';
|
||||||
import 'package:on_field_work/model/service_project/job_allocation_model.dart';
|
import 'package:on_field_work/model/service_project/job_allocation_model.dart';
|
||||||
import 'package:on_field_work/model/service_project/service_project_branches_model.dart';
|
import 'package:on_field_work/model/service_project/service_project_branches_model.dart';
|
||||||
|
import 'package:on_field_work/helpers/services/security_service.dart';
|
||||||
|
|
||||||
class ApiService {
|
class ApiService {
|
||||||
static const bool enableLogs = true;
|
static const bool enableLogs = true;
|
||||||
@ -165,7 +166,7 @@ class ApiService {
|
|||||||
.timeout(extendedTimeout);
|
.timeout(extendedTimeout);
|
||||||
|
|
||||||
logSafe("Response Status: ${response.statusCode}", level: LogLevel.debug);
|
logSafe("Response Status: ${response.statusCode}", level: LogLevel.debug);
|
||||||
logSafe("Response Body: ${response.body}", level: LogLevel.debug);
|
logSafe("Encrypted Response: ${response.body}", level: LogLevel.debug);
|
||||||
|
|
||||||
if (response.statusCode == 401 && !hasRetried) {
|
if (response.statusCode == 401 && !hasRetried) {
|
||||||
logSafe("Unauthorized (401). Attempting token refresh...",
|
logSafe("Unauthorized (401). Attempting token refresh...",
|
||||||
@ -186,6 +187,14 @@ class ApiService {
|
|||||||
await LocalStorage.logout();
|
await LocalStorage.logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// *********** DECRYPT HERE *************
|
||||||
|
final decrypted = await SecurityService.decryptResponse(response.body);
|
||||||
|
|
||||||
|
if (decrypted != null) {
|
||||||
|
return http.Response(jsonEncode(decrypted), response.statusCode);
|
||||||
|
}
|
||||||
|
// *************************************
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logSafe("HTTP GET Exception: $e", level: LogLevel.error);
|
logSafe("HTTP GET Exception: $e", level: LogLevel.error);
|
||||||
@ -219,6 +228,17 @@ class ApiService {
|
|||||||
customTimeout: customTimeout, hasRetried: true);
|
customTimeout: customTimeout, hasRetried: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logSafe("Encrypted Response: ${response.body}", level: LogLevel.debug);
|
||||||
|
|
||||||
|
// *********** DECRYPT HERE *************
|
||||||
|
final decrypted = await SecurityService.decryptResponse(response.body);
|
||||||
|
|
||||||
|
if (decrypted != null) {
|
||||||
|
return http.Response(jsonEncode(decrypted), response.statusCode);
|
||||||
|
}
|
||||||
|
// *************************************
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logSafe("HTTP POST Exception: $e", level: LogLevel.error);
|
logSafe("HTTP POST Exception: $e", level: LogLevel.error);
|
||||||
@ -671,8 +691,7 @@ class ApiService {
|
|||||||
'pageNumber': pageNumber.toString(),
|
'pageNumber': pageNumber.toString(),
|
||||||
'pageSize': pageSize.toString(),
|
'pageSize': pageSize.toString(),
|
||||||
'isActive': isActive.toString(),
|
'isActive': isActive.toString(),
|
||||||
if (isArchive)
|
if (isArchive) 'isArchive': 'true',
|
||||||
'isArchive': 'true',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
final response = await _getRequest(endpoint, queryParams: queryParams);
|
final response = await _getRequest(endpoint, queryParams: queryParams);
|
||||||
|
|||||||
41
lib/helpers/services/security_service.dart
Normal file
41
lib/helpers/services/security_service.dart
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'package:cryptography/cryptography.dart';
|
||||||
|
|
||||||
|
class SecurityService {
|
||||||
|
// Same 32-byte key
|
||||||
|
static const _keyBase64 = "Your32ByteBase64KeyGoesHere/1234567890+XY=";
|
||||||
|
|
||||||
|
static Future<dynamic> decryptResponse(String encryptedBase64) async {
|
||||||
|
final algorithm = AesGcm.with256bits();
|
||||||
|
|
||||||
|
// 1. Decode Key and Data
|
||||||
|
final secretKey = await algorithm.newSecretKeyFromBytes(base64.decode(_keyBase64));
|
||||||
|
final encryptedBytes = base64.decode(encryptedBase64);
|
||||||
|
|
||||||
|
// 2. Extract Parts: [Nonce 12] + [Ciphertext] + [Tag 16]
|
||||||
|
// The "SecretBox" class helps us organize these parts
|
||||||
|
final nonce = encryptedBytes.sublist(0, 12);
|
||||||
|
final ciphertext = encryptedBytes.sublist(12, encryptedBytes.length - 16);
|
||||||
|
final mac = encryptedBytes.sublist(encryptedBytes.length - 16);
|
||||||
|
|
||||||
|
final secretBox = SecretBox(
|
||||||
|
ciphertext,
|
||||||
|
nonce: nonce,
|
||||||
|
mac: Mac(mac),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 3. Decrypt
|
||||||
|
try {
|
||||||
|
final decryptedBytes = await algorithm.decrypt(
|
||||||
|
secretBox,
|
||||||
|
secretKey: secretKey,
|
||||||
|
);
|
||||||
|
|
||||||
|
final decryptedString = utf8.decode(decryptedBytes);
|
||||||
|
return json.decode(decryptedString);
|
||||||
|
} catch (e) {
|
||||||
|
print("Decryption failed: $e");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -83,6 +83,8 @@ dependencies:
|
|||||||
timeago: ^3.7.1
|
timeago: ^3.7.1
|
||||||
cached_network_image: ^3.4.1
|
cached_network_image: ^3.4.1
|
||||||
|
|
||||||
|
cryptography: ^2.7.0
|
||||||
|
|
||||||
gallery_saver_plus: ^3.2.9
|
gallery_saver_plus: ^3.2.9
|
||||||
share_plus: ^12.0.1
|
share_plus: ^12.0.1
|
||||||
timeline_tile: ^2.0.0
|
timeline_tile: ^2.0.0
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user