@@ -427,7 +427,7 @@ def login(self) -> None:
427427
428428 params_enc = {
429429 'account' : self ._username ,
430- 'enable_device_token' : 'no ' ,
430+ 'enable_device_token' : 'yes ' ,
431431 'logintype' : 'local' ,
432432 'otp_code' : '' ,
433433 'rememberme' : 0 ,
@@ -443,11 +443,14 @@ def login(self) -> None:
443443
444444 if self ._otp_code :
445445 params ['otp_code' ] = self ._otp_code
446- if self ._device_id is not None and self ._device_name is not None :
446+ # Device token (2FA): when a device_id is available (either provided by
447+ # the caller or captured from a previous OTP login), send it in place of
448+ # the OTP. DSM then skips the 2FA challenge for subsequent logins.
449+ if self ._device_id is not None :
447450 params ['device_id' ] = self ._device_id
448- params ['device_name' ] = self . _device_name
449- if self . _device_id is not None and self ._device_name is None or self ._device_id is None and self . _device_name is not None :
450- print ( "device_id and device_name must be set together" )
451+ params ['device_name' ] = (
452+ self ._device_name or f"synology-api- { self ._username } "
453+ )
451454
452455 if not self ._session_expire and self ._sid is not None :
453456 self ._session_expire = False
@@ -479,6 +482,9 @@ def login(self) -> None:
479482 if not error_code :
480483 self ._sid = session_request_json ['data' ]['sid' ]
481484 self ._syno_token = session_request_json ['data' ]['synotoken' ]
485+ device_id = session_request_json ['data' ].get ('device_id' )
486+ if device_id :
487+ self ._device_id = device_id
482488 self ._finish_noise_handshake (session_request_json ['data' ])
483489 self ._session_expire = False
484490 if self ._debug is True :
0 commit comments