@@ -186,7 +186,9 @@ function step(state::NoAuthentication)::Union{RequestLogin, Failure}
186186 headers = [" Accept" => " application/json" , " Content-Type" => " application/x-www-form-urlencoded" ],
187187 )
188188 if response isa Downloads. Response && response. status == 200
189- return RequestLogin (state. server, nothing , JSON. parse (String (take! (output))))
189+ body = JSON. parse (String (take! (output)))
190+ body[" client_id" ] = " device"
191+ return RequestLogin (state. server, " " , body)
190192 end
191193
192194 challenge = Random. randstring (32 )
@@ -198,7 +200,7 @@ function step(state::NoAuthentication)::Union{RequestLogin, Failure}
198200 throw = false ,
199201 )
200202 if response isa Downloads. Response && response. status == 200
201- return RequestLogin (state. server, challenge, String (take! (output)))
203+ return RequestLogin (state. server, challenge, String (take! (output)), false )
202204 else
203205 return HttpError (response)
204206 end
@@ -240,15 +242,26 @@ Base.show(io::IO, s::NeedRefresh) = print(io, "NeedRefresh($(s.server), <REDACTE
240242
241243function step (state:: NeedRefresh ):: Union{HasNewToken, NoAuthentication}
242244 refresh_token = state. token[" refresh_token" ]
243- headers = [" Authorization" => " Bearer $refresh_token " ]
244245 output = IOBuffer ()
245- response = Downloads. request (
246- state. token[" refresh_url" ],
247- method = " GET" ,
248- headers = headers,
249- output = output,
250- throw = false ,
251- )
246+ is_device = get (state. token, " client_id" , nothing ) == " device"
247+ response = if is_device
248+ Downloads. request (
249+ " $(state. server) /dex/token" ,
250+ method = " POST" ,
251+ headers = [" Content-Type" => " application/x-www-form-urlencoded" ],
252+ input = IOBuffer (" grant_type=refresh_token&client_id=device&refresh_token=$refresh_token " ),
253+ output = output,
254+ throw = false ,
255+ )
256+ else
257+ Downloads. request (
258+ state. token[" refresh_url" ],
259+ method = " GET" ,
260+ headers = [" Authorization" => " Bearer $refresh_token " ],
261+ output = output,
262+ throw = false ,
263+ )
264+ end
252265 # errors are recoverable by just getting a new token:
253266 if response isa Downloads. Response && response. status == 200
254267 try
@@ -258,6 +271,9 @@ function step(state::NeedRefresh)::Union{HasNewToken, NoAuthentication}
258271 assert_dict_keys (body, " expires_in" ; msg= msg)
259272 assert_dict_keys (body, " expires" , " expires_at" ; msg= msg)
260273 end
274+ if is_device
275+ body[" client_id" ] = " device"
276+ end
261277 return HasNewToken (state. server, body)
262278 catch err
263279 @debug " invalid body received while refreshing token" exception= (err, catch_backtrace ())
@@ -322,20 +338,21 @@ ClaimToken immediately, or to Failure if there was an unexpected failure.
322338"""
323339struct RequestLogin <: State
324340 server:: String
325- challenge:: Union{Nothing, String}
341+ challenge:: String
326342 response:: Union{String, Dict{String, Any}}
327343end
328344Base. show (io:: IO , s:: RequestLogin ) = print (io, " RequestLogin($(s. server) , <REDACTED>, $(s. response) )" )
329345
330346function step (state:: RequestLogin ):: Union{ClaimToken, Failure}
331- url = if state. challenge === nothing
332- string (state. server, " /response?" , state. response)
333- else
347+ is_device = response isa Dict{String, Any} && get (response, " client_id" , nothing ) == " device"
348+ url = if is_device
334349 string (state. response[" verification_uri_complete" ])
350+ else
351+ string (state. server, " /response?" , state. response)
335352 end
336353
337354 success = open_browser (url)
338- if success && state. challenge === nothing
355+ if success && state. is_device
339356 return ClaimToken (state. server, state. challenge, state. response, expiry= state. response[" expires_in" ])
340357 elseif success
341358 return ClaimToken (state. server, state. challenge, state. response)
@@ -377,7 +394,8 @@ function step(state::ClaimToken)::Union{ClaimToken, HasNewToken, Failure}
377394 sleep (state. poll_interval)
378395
379396 output = IOBuffer ()
380- if state. challenge === nothing
397+ is_device = response isa Dict{String, Any} && get (response, " client_id" , nothing ) == " device" )
398+ if is_device
381399 response = Downloads. request (
382400 string (state. server, " /dex/token" ),
383401 method = " POST" ,
@@ -416,7 +434,7 @@ function step(state::ClaimToken)::Union{ClaimToken, HasNewToken, Failure}
416434 end
417435 elseif response isa Downloads. Response && response. status == 200
418436 return HasNewToken (state. server, JSON. parse (String (take! (output)))[" access_token" ])
419- elseif response isa Downloads. Response && response. status == 401 && state . challenge === nothing
437+ elseif response isa Downloads. Response && response. status == 401 && is_device
420438 return ClaimToken (state. server, state. challenge, state. response, state. expiry, state. start_time, state. timeout, state. poll_interval, state. failures + 1 , state. max_failures)
421439 else
422440 return HttpError (response)
0 commit comments