MCPcopy
hub / github.com/opentrace/opentrace / login

Function login

agent/src/opentrace_agent/cli/auth.py:387–456  ·  view source on GitHub ↗

Run the full OAuth 2.0 + PKCE browser login flow. 1. Fetch authorization server metadata (RFC 8414). 2. Ensure a client is registered (RFC 7591 dynamic registration or cached). 3. Start a local HTTP server for the callback. 4. Open the browser to the authorization endpoint. 5. W

()

Source from the content-addressed store, hash-verified

385
386
387def login() -> dict[str, Any]:
388 """Run the full OAuth 2.0 + PKCE browser login flow.
389
390 1. Fetch authorization server metadata (RFC 8414).
391 2. Ensure a client is registered (RFC 7591 dynamic registration or cached).
392 3. Start a local HTTP server for the callback.
393 4. Open the browser to the authorization endpoint.
394 5. Wait for the redirect with the authorization code.
395 6. Exchange the code for tokens and persist to disk.
396
397 Returns the saved auth payload.
398 """
399 disco = discover()
400
401 port = _find_open_port()
402 redirect_uris = [f"http://{CALLBACK_HOST}:{p}/callback" for p in CALLBACK_PORT_RANGE]
403 redirect_uri = f"http://{CALLBACK_HOST}:{port}/callback"
404
405 client = _ensure_client(disco, redirect_uris)
406 client_id = client["client_id"]
407
408 verifier, challenge = _generate_pkce()
409 state = secrets.token_urlsafe(32)
410
411 params = urlencode(
412 {
413 "response_type": "code",
414 "client_id": client_id,
415 "redirect_uri": redirect_uri,
416 "scope": SCOPES,
417 "state": state,
418 "code_challenge": challenge,
419 "code_challenge_method": "S256",
420 "prompt": "none", # Skip org selector — CLI controls org via config
421 }
422 )
423 authorize_url = f"{disco['authorization_endpoint']}?{params}"
424
425 result = _OAuthResult()
426 handler_cls = _make_handler(result, state)
427
428 server = _ThreadedHTTPServer((CALLBACK_HOST, port), handler_cls)
429 server_thread = threading.Thread(target=server.serve_forever, daemon=True)
430 server_thread.start()
431
432 try:
433 webbrowser.open(authorize_url)
434
435 # Wait for the callback (up to 5 minutes).
436 if not result.ready.wait(timeout=300):
437 raise TimeoutError("Timed out waiting for browser login (5 min)")
438
439 if result.error:
440 raise RuntimeError(result.error)
441
442 code = result.code
443 assert code is not None # noqa: S101
444

Callers

nothing calls this directly

Calls 11

save_tokensFunction · 0.90
discoverFunction · 0.85
_find_open_portFunction · 0.85
_ensure_clientFunction · 0.85
_generate_pkceFunction · 0.85
_OAuthResultClass · 0.85
_make_handlerFunction · 0.85
_ThreadedHTTPServerClass · 0.85
_exchange_codeFunction · 0.85
startMethod · 0.80
getMethod · 0.65

Tested by

no test coverage detected