@@ -458,6 +458,11 @@ def _global_output_options(func):
458458 cls = _AliasedGroupRoot , invoke_without_command = True , context_settings = _ctxt_settings
459459)
460460@click .option ("-m" , "--manual-auth" , is_flag = True , help = "Force manual authentication" )
461+ @click .option (
462+ "--device-auth" ,
463+ is_flag = True ,
464+ help = "Use device authorization flow when manual authentication is required" ,
465+ )
461466@click .option (
462467 "-s" ,
463468 "--script" ,
@@ -3078,6 +3083,7 @@ def _initialize(opts):
30783083
30793084 try :
30803085 man_auth = opts ["manual_auth" ]
3086+ use_device_auth = opts .get ("device_auth" )
30813087
30823088 if man_auth :
30833089 # print("CLI - manual auth")
@@ -3119,19 +3125,22 @@ def _initialize(opts):
31193125 "Cannot manually authentication when running non-interactively."
31203126 )
31213127
3122- i = 0
3123- while i < 3 :
3124- i += 1
3125- uid = click .prompt ("User ID" )
3126- password = getpass .getpass (prompt = "Password: " )
3127- try :
3128- _capi .loginByPassword (uid , password )
3129- break
3130- except Exception as e :
3131- click .echo (e )
3128+ if use_device_auth :
3129+ _perform_device_authorization (_capi )
3130+ else :
3131+ i = 0
3132+ while i < 3 :
3133+ i += 1
3134+ uid = click .prompt ("User ID" )
3135+ password = getpass .getpass (prompt = "Password: " )
3136+ try :
3137+ _capi .loginByPassword (uid , password )
3138+ break
3139+ except Exception as e :
3140+ click .echo (e )
31323141
3133- if i == 3 :
3134- raise Exception ("Too many failed log-in attempts." )
3142+ if i == 3 :
3143+ raise Exception ("Too many failed log-in attempts." )
31353144
31363145 tmp = _capi .cfg .get ("verbosity" )
31373146 if tmp is not None :
@@ -3149,6 +3158,35 @@ def _initialize(opts):
31493158 raise
31503159
31513160
3161+ def _perform_device_authorization (capi ):
3162+ """
3163+ Run the interactive device authorization login flow.
3164+ """
3165+ try :
3166+ session = capi .startDeviceAuthorization ()
3167+ except Exception as exc :
3168+ raise Exception ("Unable to start device authorization flow: {}" .format (exc ))
3169+
3170+ verification_uri = session .get ("verification_uri" )
3171+ code = session .get ("code" )
3172+
3173+ if not verification_uri or not code :
3174+ raise Exception ("Device authorization response was incomplete." )
3175+
3176+ click .echo ("Complete authentication by visiting: {}" .format (verification_uri ))
3177+ click .echo ("When prompted, enter the code: {}" .format (code ))
3178+ click .echo ("Waiting for authorization to complete..." )
3179+
3180+ try :
3181+ capi .pollDeviceAuthorization (code = code )
3182+ except TimeoutError as exc :
3183+ raise Exception ("Device authorization timed out." ) from exc
3184+ except Exception :
3185+ raise
3186+
3187+ if _output_mode == _OM_TEXT :
3188+ click .echo ("Device authorization successful." )
3189+
31523190def _addConfigOptions ():
31533191 for _ , v in Config ._opt_info .items ():
31543192 if not v [3 ] & Config ._OPT_NO_CL :
0 commit comments