connectionRequest method
Check this client
Implementation
Future<bool?> connectionRequest() async {
///Client tarafına benzer şekilde(aynı şekilde )
///4 aşamalı bağlantı protokolü var
try {
// print("CONNECTION STARTED");
///
/// type
/// -----
/// id
///
///
/// Server Side Client Side
/// Server Side Client Side
///
///
/// deviceID request_connection
/// | <----------------------- deviceID
/// | requestID
/// |
/// |
/// |
/// | nonce_sending
/// serverNonce ------------------------> serverNonce
/// requestID |
/// |
/// |
/// |
/// |
/// auth_data c_nonce_sending auth_data
/// clientNonce <-------------------------- clientNonce
/// | secondID
/// |
/// |
/// |
/// |
/// | token_sending ✅
/// auth_token ---------------------------> auth token
/// secondID ✅
///
///
///Received connection request
///{
/// id: string,
/// type : 'request_connection',
/// device_id : string
///}
var stage1Data =
await waitMessage(socketBroadcast, type: 'request_connection');
if (stage1Data.fullData == null ||
stage1Data.type == null ||
stage1Data.messageId == null) {
throw Exception('Message is null');
}
// print('CONNECTION REQUESTED DATA : ${stage1Data.runtimeType}');
///unique id for each request
var requestID = stage1Data.messageId;
if (stage1Data.fullData!['device_id'] == null) return null;
///unique device id
deviceID = await encryptionService
.decrypt4((stage1Data.fullData!['device_id']) ?? "");
// print("DEVICE ID REVEIVED ::: $deviceID");
var req = WebSocketConnectRequest.received(deviceID);
if (service.connectRequests.contains(req)) {
service.connectRequests.remove(req);
}
///log device id and request id
var db = server.databaseApi;
await db.logConnection({
'id': requestID,
'deviceID': deviceID,
'timestamp': DateTime.now().millisecondsSinceEpoch,
}).timeout(const Duration(milliseconds: 500), onTimeout: () {
return {"error": "log_timeout"};
}).catchError((e) {
return {"error": e.toString()};
});
///generate server side nonce
nonce = Nonce.random();
/// Sending "nonce_sending" and waiting "c_nonce_sending"
/// ----------------------------------------
/// !!!! These messages are different id !!!!
/// ------------------------------------------
/// send stage 2 data
/// {
/// id : requestID
/// nonce : server side nonce Uint8List
/// type : 'nonce_sending'
/// }
/// wait stage 3 data
/// {
/// id : secondID
/// c_nonce: client side nonce Uint8List
/// type : 'c_nonce_sending'
/// data : encrypted auth data
/// }
///
///
var stage3Data = await sendAndWaitMessage(
this,
SocketData.fromFullData({
'message_id': requestID,
'nonce': nonce!.list,
'message_type': 'nonce_sending',
'success': true,
'data': {}
}),
waitingType: 'c_nonce_sending',
anyID: true);
// print('STAGE 3 : $stage3Data');
if (stage3Data == null ||
stage3Data.fullData == null ||
stage3Data.type == null ||
stage3Data.messageId == null) {
throw Exception('Message is null');
}
var secondID = stage3Data.fullData!['message_id'];
if (!stage3Data.success) return false;
///client nonce
cnonce = Statics.nonceCast(stage3Data.fullData!['c_nonce']);
///decrypt stage3 data
await stage3Data.decrypt(nonce, cnonce);
// print(stage3Data.data);
if (stage3Data.data!['auth_type'] == null) {
return false;
} else if (stage3Data.data!['auth_type'] == 'auth') {
var userData = await db.confirmUser(stage3Data.data, deviceID);
if (userData != null && userData['success']) {
// print("USER CONFIRMED : $userData");
///User Confirmed
var token = await AccessToken.generateForUser(
authType: AuthType.loggedIn,
deviceID: deviceID!,
mail: userData['open']['user_mail'],
uId: userData['open']['user_id'])
.encryptedToken;
isLogged = true;
userId = userData['open']['user_id'];
chatService.addOnline(userId, this);
var sending = SocketData.fromFullData({
'message_id': secondID,
'message_type': 'token_sending',
'success': true,
'data': {
'token': token,
'timestamp': DateTime.now().millisecondsSinceEpoch,
'timeout': 30,
'auth_type': 'auth',
'user_data': userData['open']
}
});
// print(
//"ACCESS::: ${await AccessToken.fromToken(token).decryptToken()}");
// print("SENDING DATA STAGE 4 : ${sending.fullData}");
await sending.encrypt(nonce, cnonce);
///Send token
sendMessage(client, sending);
return true;
} else {
// print("USER NOT CONFIRMED");
///User Confirmed
var token =
await AccessToken.generateForGuess(AuthType.guess, deviceID!)
.encryptedToken;
sendMessage(
client,
SocketData.fromFullData({
'message_id': secondID,
'message_type': 'token_sending',
'success': true,
'data': {
'token': token,
'timestamp': DateTime.now().millisecondsSinceEpoch,
'timeout': 30,
'auth_type': 'guess'
}
}));
return true;
}
/// if auth type admin
} else if (stage3Data.data!['auth_type'] == '_admin') {
var isAdmin = (await db.exists(Query.allowAll(
queryType: QueryType.exists,
equals: {"mail": stage3Data.data!["user_mail"]},
)))!["exists"];
if (!isAdmin) {
var userData = await db.confirmUser(stage3Data.data, deviceID);
if (userData != null && userData['success']) {
// print("USER CONFIRMED : $userData");
///User Confirmed
var token = await AccessToken.generateForUser(
authType: AuthType.admin,
deviceID: deviceID!,
mail: userData['open']['user_mail'],
uId: userData['open']['user_id'])
.encryptedToken;
isLogged = true;
userId = userData['open']['user_id'];
chatService.addOnline(userId, this);
var sending = SocketData.fromFullData({
'message_id': secondID,
'message_type': 'token_sending',
'success': true,
'data': {
'token': token,
'timestamp': DateTime.now().millisecondsSinceEpoch,
'timeout': 30,
'auth_type': 'admin',
'user_data': userData['open']
}
});
// print(
//"ACCESS::: ${await AccessToken.fromToken(token).decryptToken()}");
// print("SENDING DATA STAGE 4 : ${sending.fullData}");
await sending.encrypt(nonce, cnonce);
///Send token
sendMessage(client, sending);
return true;
} else {
// print("USER NOT CONFIRMED");
///User Confirmed
var token =
await AccessToken.generateForGuess(AuthType.guess, deviceID!)
.encryptedToken;
sendMessage(
client,
SocketData.fromFullData({
'message_id': secondID,
'message_type': 'token_sending',
'success': true,
'data': {
'token': token,
'timestamp': DateTime.now().millisecondsSinceEpoch,
'timeout': 30,
'auth_type': 'guess'
}
}));
return true;
}
} else {
throw Exception("Not Admin");
}
} else {
stage3Data.data!['timestamp'] = DateTime.now().millisecondsSinceEpoch;
var token =
await AccessToken.generateForGuess(AuthType.guess, deviceID!)
.encryptedToken;
///Send token
sendMessage(
client,
await SocketData.fromFullData({
'message_id': secondID,
'message_type': 'token_sending',
'success': true,
'data': {
'token': token,
'timestamp': DateTime.now().millisecondsSinceEpoch,
'timeout': 30,
'auth_type': 'guess'
}
}).encrypt(nonce, cnonce));
return true;
}
} on Exception {
//TODO:ADD ERROR
return false;
}
}