SHA256
TrustedDeviceLogin API и настройки входа через устройство
Что сделано:\n- публичный API сценария входа через доверенное устройство переведён на TrustedDeviceLogin\n- добавлен GetTrustedDeviceLoginSettings\n- отсутствие записи настроек на сервере теперь трактуется как enabled=true и hasPassword=false\n- ttlSeconds убран из клиентского API, TTL заявки фиксирован на сервере: 300 секунд\n- в shine-UI добавлен отдельный экран настроек входа через устройство и статус на основном экране\n- browser wallet переведён на новые TrustedDeviceLogin операции\n- в wallet добавлен выбор rootKey/deviceKey для будущего запроса подписи\n- документация API обновлена\n\nЧто ещё не проверено вручную end-to-end:\n- полный сценарий UI/plugin после этого деплоя не прогонялся руками до конца\n- сам signaling подписи в wallet всё ещё не реализован
This commit is contained in:
+18
@@ -11,6 +11,7 @@ import server.logic.ws_protocol.JSON.handlers.auth.Net_ListEspPairingRequests_Ha
|
||||
import server.logic.ws_protocol.JSON.handlers.auth.Net_ApproveEspPairing_Handler;
|
||||
import server.logic.ws_protocol.JSON.handlers.auth.Net_CancelEspPairing_Handler;
|
||||
import server.logic.ws_protocol.JSON.handlers.auth.Net_GetEspPairingStatus_Handler;
|
||||
import server.logic.ws_protocol.JSON.handlers.auth.Net_GetTrustedDeviceLoginSettings_Handler;
|
||||
import server.logic.ws_protocol.JSON.handlers.auth.Net_RejectEspPairing_Handler;
|
||||
|
||||
// --- NEW v2 session login ---
|
||||
@@ -30,6 +31,7 @@ import server.logic.ws_protocol.JSON.handlers.auth.entyties.Net_ListEspPairingRe
|
||||
import server.logic.ws_protocol.JSON.handlers.auth.entyties.Net_ApproveEspPairing_Request;
|
||||
import server.logic.ws_protocol.JSON.handlers.auth.entyties.Net_CancelEspPairing_Request;
|
||||
import server.logic.ws_protocol.JSON.handlers.auth.entyties.Net_GetEspPairingStatus_Request;
|
||||
import server.logic.ws_protocol.JSON.handlers.auth.entyties.Net_GetTrustedDeviceLoginSettings_Request;
|
||||
import server.logic.ws_protocol.JSON.handlers.auth.entyties.Net_RejectEspPairing_Request;
|
||||
import server.logic.ws_protocol.JSON.handlers.auth.entyties.Net_SessionChallenge_Request;
|
||||
import server.logic.ws_protocol.JSON.handlers.auth.entyties.Net_SessionLogin_Request;
|
||||
@@ -142,6 +144,14 @@ public final class JsonHandlerRegistry {
|
||||
Map.entry("RejectEspPairing", new Net_RejectEspPairing_Handler()),
|
||||
Map.entry("CancelEspPairing", new Net_CancelEspPairing_Handler()),
|
||||
Map.entry("GetEspPairingStatus", new Net_GetEspPairingStatus_Handler()),
|
||||
Map.entry("GetTrustedDeviceLoginSettings", new Net_GetTrustedDeviceLoginSettings_Handler()),
|
||||
Map.entry("UpsertTrustedDeviceLoginSettings", new Net_UpsertEspPairingSettings_Handler()),
|
||||
Map.entry("StartTrustedDeviceLogin", new Net_StartEspPairing_Handler()),
|
||||
Map.entry("ListTrustedDeviceLoginRequests", new Net_ListEspPairingRequests_Handler()),
|
||||
Map.entry("ApproveTrustedDeviceLogin", new Net_ApproveEspPairing_Handler()),
|
||||
Map.entry("RejectTrustedDeviceLogin", new Net_RejectEspPairing_Handler()),
|
||||
Map.entry("CancelTrustedDeviceLogin", new Net_CancelEspPairing_Handler()),
|
||||
Map.entry("GetTrustedDeviceLoginStatus", new Net_GetEspPairingStatus_Handler()),
|
||||
|
||||
// --- blockchain ---
|
||||
Map.entry("AddBlock", new Net_AddBlock_Handler()),
|
||||
@@ -207,6 +217,14 @@ public final class JsonHandlerRegistry {
|
||||
Map.entry("RejectEspPairing", Net_RejectEspPairing_Request.class),
|
||||
Map.entry("CancelEspPairing", Net_CancelEspPairing_Request.class),
|
||||
Map.entry("GetEspPairingStatus", Net_GetEspPairingStatus_Request.class),
|
||||
Map.entry("GetTrustedDeviceLoginSettings", Net_GetTrustedDeviceLoginSettings_Request.class),
|
||||
Map.entry("UpsertTrustedDeviceLoginSettings", Net_UpsertEspPairingSettings_Request.class),
|
||||
Map.entry("StartTrustedDeviceLogin", Net_StartEspPairing_Request.class),
|
||||
Map.entry("ListTrustedDeviceLoginRequests", Net_ListEspPairingRequests_Request.class),
|
||||
Map.entry("ApproveTrustedDeviceLogin", Net_ApproveEspPairing_Request.class),
|
||||
Map.entry("RejectTrustedDeviceLogin", Net_RejectEspPairing_Request.class),
|
||||
Map.entry("CancelTrustedDeviceLogin", Net_CancelEspPairing_Request.class),
|
||||
Map.entry("GetTrustedDeviceLoginStatus", Net_GetEspPairingStatus_Request.class),
|
||||
|
||||
// --- blockchain ---
|
||||
Map.entry("AddBlock", Net_AddBlock_Request.class),
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package server.logic.ws_protocol.JSON.handlers.auth;
|
||||
|
||||
import server.logic.ws_protocol.JSON.ConnectionContext;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Response;
|
||||
import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler;
|
||||
import server.logic.ws_protocol.JSON.handlers.auth.entyties.Net_GetTrustedDeviceLoginSettings_Request;
|
||||
import server.logic.ws_protocol.JSON.handlers.auth.entyties.Net_GetTrustedDeviceLoginSettings_Response;
|
||||
import server.logic.ws_protocol.JSON.utils.NetExceptionResponseFactory;
|
||||
import shine.db.dao.EspPairingSettingsDAO;
|
||||
import shine.db.entities.EspPairingSettingsEntry;
|
||||
|
||||
public class Net_GetTrustedDeviceLoginSettings_Handler implements JsonMessageHandler {
|
||||
|
||||
@Override
|
||||
public Net_Response handle(Net_Request baseReq, ConnectionContext ctx) throws Exception {
|
||||
Net_GetTrustedDeviceLoginSettings_Request req = (Net_GetTrustedDeviceLoginSettings_Request) baseReq;
|
||||
|
||||
if (!EspPairingSupport.isTrustedUserSession(ctx)) {
|
||||
return NetExceptionResponseFactory.error(
|
||||
req,
|
||||
EspPairingSupport.STATUS_PAIRING_REQUIRES_AUTH_SESSION,
|
||||
"PAIRING_REQUIRES_AUTH_SESSION",
|
||||
"Операция доступна только для авторизованной доверенной сессии пользователя"
|
||||
);
|
||||
}
|
||||
|
||||
EspPairingSettingsEntry entry = EspPairingSettingsDAO.getInstance().getByLogin(ctx.getLogin());
|
||||
boolean enabled = entry == null || entry.isEnabled();
|
||||
boolean hasPassword = enabled
|
||||
&& entry != null
|
||||
&& entry.getPasswordHash() != null
|
||||
&& !entry.getPasswordHash().trim().isBlank();
|
||||
|
||||
Net_GetTrustedDeviceLoginSettings_Response resp = new Net_GetTrustedDeviceLoginSettings_Response();
|
||||
resp.setOp(req.getOp());
|
||||
resp.setRequestId(req.getRequestId());
|
||||
resp.setStatus(200);
|
||||
resp.setEnabled(enabled);
|
||||
resp.setHasPassword(hasPassword);
|
||||
return resp;
|
||||
}
|
||||
}
|
||||
+7
-4
@@ -67,7 +67,8 @@ public class Net_StartEspPairing_Handler implements JsonMessageHandler {
|
||||
String canonicalLogin = user.getLogin();
|
||||
|
||||
EspPairingSettingsEntry settings = EspPairingSettingsDAO.getInstance().getByLogin(canonicalLogin);
|
||||
if (settings == null || !settings.isEnabled()) {
|
||||
boolean enabled = settings == null || settings.isEnabled();
|
||||
if (!enabled) {
|
||||
return NetExceptionResponseFactory.error(req, 422, "PAIRING_NOT_AVAILABLE", "Для этого login pairing недоступен");
|
||||
}
|
||||
|
||||
@@ -85,7 +86,9 @@ public class Net_StartEspPairing_Handler implements JsonMessageHandler {
|
||||
if (recentAttempts >= EspPairingSupport.REQUEST_RATE_LIMIT) {
|
||||
return NetExceptionResponseFactory.error(req, EspPairingSupport.STATUS_PAIRING_RATE_LIMIT, "PAIRING_RATE_LIMITED", "Слишком много pairing-запросов за короткое время");
|
||||
}
|
||||
String configuredPasswordHash = settings.getPasswordHash() == null ? "" : settings.getPasswordHash().trim();
|
||||
String configuredPasswordHash = settings == null || settings.getPasswordHash() == null
|
||||
? ""
|
||||
: settings.getPasswordHash().trim();
|
||||
boolean requiresPassword = !configuredPasswordHash.isBlank();
|
||||
boolean suppliedPassword = passwordHash != null && !passwordHash.isBlank();
|
||||
if ((requiresPassword && !configuredPasswordHash.equals(passwordHash))
|
||||
@@ -94,7 +97,7 @@ public class Net_StartEspPairing_Handler implements JsonMessageHandler {
|
||||
}
|
||||
|
||||
String clientPlatform = AuthSessionTypeSupport.normalizeClientPlatform(req.getRequesterClientPlatform());
|
||||
int ttlSeconds = EspPairingSupport.normalizeTtlSeconds(settings.getTtlSeconds());
|
||||
int ttlSeconds = EspPairingSupport.DEFAULT_TTL_SECONDS;
|
||||
List<ConnectionContext> approverConnections = EspPairingSupport.findOnlineTrustedConnections(canonicalLogin);
|
||||
if (approverConnections.isEmpty()) {
|
||||
return NetExceptionResponseFactory.error(
|
||||
@@ -143,7 +146,7 @@ public class Net_StartEspPairing_Handler implements JsonMessageHandler {
|
||||
payload.put("fingerprintB58", entry.getFingerprintB58());
|
||||
payload.put("createdAtMs", entry.getCreatedAtMs());
|
||||
payload.put("expiresAtMs", entry.getExpiresAtMs());
|
||||
delivered |= WsEventSender.sendEvent(targetCtx, "IncomingEspPairingRequest", eventId, payload);
|
||||
delivered |= WsEventSender.sendEvent(targetCtx, "IncomingTrustedDeviceLoginRequest", eventId, payload);
|
||||
}
|
||||
if (delivered) {
|
||||
EspPairingRequestsDAO.getInstance().updateDeliveryFlag(entry.getPairingId(), true, System.currentTimeMillis());
|
||||
|
||||
+3
-5
@@ -37,14 +37,12 @@ public class Net_UpsertEspPairingSettings_Handler implements JsonMessageHandler
|
||||
"passwordHash должен быть пустым или иметь формат sha256$<64 hex>"
|
||||
);
|
||||
}
|
||||
int ttlSeconds = EspPairingSupport.normalizeTtlSeconds(req.getTtlSeconds());
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
EspPairingSettingsEntry entry = new EspPairingSettingsEntry();
|
||||
entry.setLogin(ctx.getLogin());
|
||||
entry.setEnabled(enabled);
|
||||
entry.setPasswordHash(passwordHash == null ? "" : passwordHash);
|
||||
entry.setTtlSeconds(ttlSeconds);
|
||||
entry.setPasswordHash(enabled && passwordHash != null ? passwordHash : "");
|
||||
entry.setTtlSeconds(EspPairingSupport.DEFAULT_TTL_SECONDS);
|
||||
entry.setFailedAttempts(0);
|
||||
entry.setFirstFailedAtMs(0L);
|
||||
entry.setBlockedUntilMs(0L);
|
||||
@@ -56,7 +54,7 @@ public class Net_UpsertEspPairingSettings_Handler implements JsonMessageHandler
|
||||
resp.setRequestId(req.getRequestId());
|
||||
resp.setStatus(WireCodes.Status.OK);
|
||||
resp.setEnabled(enabled);
|
||||
resp.setTtlSeconds(ttlSeconds);
|
||||
resp.setHasPassword(enabled && passwordHash != null && !passwordHash.isBlank());
|
||||
return resp;
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package server.logic.ws_protocol.JSON.handlers.auth.entyties;
|
||||
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Request;
|
||||
|
||||
public class Net_GetTrustedDeviceLoginSettings_Request extends Net_Request {
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package server.logic.ws_protocol.JSON.handlers.auth.entyties;
|
||||
|
||||
import server.logic.ws_protocol.JSON.entyties.Net_Response;
|
||||
|
||||
public class Net_GetTrustedDeviceLoginSettings_Response extends Net_Response {
|
||||
private boolean enabled;
|
||||
private boolean hasPassword;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public boolean isHasPassword() {
|
||||
return hasPassword;
|
||||
}
|
||||
|
||||
public void setHasPassword(boolean hasPassword) {
|
||||
this.hasPassword = hasPassword;
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -4,7 +4,7 @@ import server.logic.ws_protocol.JSON.entyties.Net_Response;
|
||||
|
||||
public class Net_UpsertEspPairingSettings_Response extends Net_Response {
|
||||
private boolean enabled;
|
||||
private int ttlSeconds;
|
||||
private boolean hasPassword;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
@@ -14,11 +14,11 @@ public class Net_UpsertEspPairingSettings_Response extends Net_Response {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public int getTtlSeconds() {
|
||||
return ttlSeconds;
|
||||
public boolean isHasPassword() {
|
||||
return hasPassword;
|
||||
}
|
||||
|
||||
public void setTtlSeconds(int ttlSeconds) {
|
||||
this.ttlSeconds = ttlSeconds;
|
||||
public void setHasPassword(boolean hasPassword) {
|
||||
this.hasPassword = hasPassword;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user