| |
|
|
| import requests |
|
|
| from ultralytics.hub.utils import HUB_API_ROOT, PREFIX, request_with_credentials |
| from ultralytics.yolo.utils import LOGGER, SETTINGS, emojis, is_colab, set_settings |
|
|
| API_KEY_URL = 'https://hub.ultralytics.com/settings?tab=api+keys' |
|
|
|
|
| class Auth: |
| id_token = api_key = model_key = False |
|
|
| def __init__(self, api_key='', verbose=False): |
| """ |
| Initialize the Auth class with an optional API key. |
| |
| Args: |
| api_key (str, optional): May be an API key or a combination API key and model ID, i.e. key_id |
| """ |
| |
| api_key = api_key.split('_')[0] |
|
|
| |
| self.api_key = api_key or SETTINGS.get('api_key', '') |
|
|
| |
| if self.api_key: |
| |
| if self.api_key == SETTINGS.get('api_key'): |
| |
| if verbose: |
| LOGGER.info(f'{PREFIX}Authenticated ✅') |
| return |
| else: |
| |
| success = self.authenticate() |
| |
| elif is_colab(): |
| |
| success = self.auth_with_cookies() |
| else: |
| |
| success = self.request_api_key() |
|
|
| |
| if success: |
| set_settings({'api_key': self.api_key}) |
| |
| if verbose: |
| LOGGER.info(f'{PREFIX}New authentication successful ✅') |
| elif verbose: |
| LOGGER.info(f'{PREFIX}Retrieve API key from {API_KEY_URL}') |
|
|
| def request_api_key(self, max_attempts=3): |
| """ |
| Prompt the user to input their API key. Returns the model ID. |
| """ |
| import getpass |
| for attempts in range(max_attempts): |
| LOGGER.info(f'{PREFIX}Login. Attempt {attempts + 1} of {max_attempts}') |
| input_key = getpass.getpass(f'Enter API key from {API_KEY_URL} ') |
| self.api_key = input_key.split('_')[0] |
| if self.authenticate(): |
| return True |
| raise ConnectionError(emojis(f'{PREFIX}Failed to authenticate ❌')) |
|
|
| def authenticate(self) -> bool: |
| """ |
| Attempt to authenticate with the server using either id_token or API key. |
| |
| Returns: |
| bool: True if authentication is successful, False otherwise. |
| """ |
| try: |
| header = self.get_auth_header() |
| if header: |
| r = requests.post(f'{HUB_API_ROOT}/v1/auth', headers=header) |
| if not r.json().get('success', False): |
| raise ConnectionError('Unable to authenticate.') |
| return True |
| raise ConnectionError('User has not authenticated locally.') |
| except ConnectionError: |
| self.id_token = self.api_key = False |
| LOGGER.warning(f'{PREFIX}Invalid API key ⚠️') |
| return False |
|
|
| def auth_with_cookies(self) -> bool: |
| """ |
| Attempt to fetch authentication via cookies and set id_token. |
| User must be logged in to HUB and running in a supported browser. |
| |
| Returns: |
| bool: True if authentication is successful, False otherwise. |
| """ |
| if not is_colab(): |
| return False |
| try: |
| authn = request_with_credentials(f'{HUB_API_ROOT}/v1/auth/auto') |
| if authn.get('success', False): |
| self.id_token = authn.get('data', {}).get('idToken', None) |
| self.authenticate() |
| return True |
| raise ConnectionError('Unable to fetch browser authentication details.') |
| except ConnectionError: |
| self.id_token = False |
| return False |
|
|
| def get_auth_header(self): |
| """ |
| Get the authentication header for making API requests. |
| |
| Returns: |
| (dict): The authentication header if id_token or API key is set, None otherwise. |
| """ |
| if self.id_token: |
| return {'authorization': f'Bearer {self.id_token}'} |
| elif self.api_key: |
| return {'x-api-key': self.api_key} |
| else: |
| return None |
|
|
| def get_state(self) -> bool: |
| """ |
| Get the authentication state. |
| |
| Returns: |
| bool: True if either id_token or API key is set, False otherwise. |
| """ |
| return self.id_token or self.api_key |
|
|
| def set_api_key(self, key: str): |
| """ |
| Set the API key for authentication. |
| |
| Args: |
| key (str): The API key string. |
| """ |
| self.api_key = key |
|
|