modules/agent-framework/airavata-jupyter-magic/device_auth.py (45 lines of code) (raw):

import requests import time import os # Load environment variables from .env file class DeviceFlowAuthenticator: def __init__(self): self.client_id = "cybershuttle-agent" self.realm = "default" self.auth_server_url = "https://auth.cybershuttle.org" if not self.client_id or not self.realm or not self.auth_server_url: raise ValueError("Missing required environment variables for client ID, realm, or auth server URL") self.device_code = None self.interval = None def login(self): # Step 1: Request device and user code auth_device_url = f"{self.auth_server_url}/realms/{self.realm}/protocol/openid-connect/auth/device" response = requests.post(auth_device_url, data={"client_id": self.client_id, "scope": "openid"}) if response.status_code != 200: print(f"Error in device authorization request: {response.status_code} - {response.text}") return data = response.json() self.device_code = data.get("device_code") self.interval = data.get("interval", 5) print(f"User code: {data.get('user_code')}") print(f"Please authenticate by visiting: {data.get('verification_uri_complete')}") # Step 2: Poll for the token self.poll_for_token() def poll_for_token(self): assert self.interval is not None token_url = f"{self.auth_server_url}/realms/{self.realm}/protocol/openid-connect/token" while True: response = requests.post(token_url, data={ "client_id": self.client_id, "grant_type": "urn:ietf:params:oauth:grant-type:device_code", "device_code": self.device_code }) if response.status_code == 200: data = response.json() access_token = data.get("access_token") print(f"Received access token") os.environ['CS_ACCESS_TOKEN'] = access_token break elif response.status_code == 400 and response.json().get("error") == "authorization_pending": print("Authorization pending, retrying...") else: print(f"Error in token request: {response.status_code} - {response.text}") break time.sleep(self.interval)