Skip to content

ccproxy.auth.storage.keyring

ccproxy.auth.storage.keyring

OS keyring storage implementation for token storage.

KeyringTokenStorage

KeyringTokenStorage(
    service_name="claude-code-proxy", username="default"
)

Bases: TokenStorage

OS keyring storage implementation for Claude credentials.

Parameters:

Name Type Description Default
service_name str

Name of the service in the keyring

'claude-code-proxy'
username str

Username to associate with the stored credentials

'default'
Source code in ccproxy/auth/storage/keyring.py
def __init__(
    self, service_name: str = "claude-code-proxy", username: str = "default"
):
    """Initialize keyring storage.

    Args:
        service_name: Name of the service in the keyring
        username: Username to associate with the stored credentials
    """
    self.service_name = service_name
    self.username = username

load async

load()

Load credentials from the OS keyring.

Returns:

Type Description
ClaudeCredentials | None

Parsed credentials if found and valid, None otherwise

Raises:

Type Description
CredentialsStorageError

If the stored data is invalid

CredentialsStorageError

If there's an error reading from keyring

Source code in ccproxy/auth/storage/keyring.py
async def load(self) -> ClaudeCredentials | None:
    """Load credentials from the OS keyring.

    Returns:
        Parsed credentials if found and valid, None otherwise

    Raises:
        CredentialsStorageError: If the stored data is invalid
        CredentialsStorageError: If there's an error reading from keyring
    """
    try:
        import keyring
    except ImportError as e:
        raise CredentialsStorageError(
            "keyring package is required for keyring storage. "
            "Install it with: pip install keyring"
        ) from e

    try:
        logger.debug(
            "credentials_load_start",
            source="keyring",
            service_name=self.service_name,
        )
        password = keyring.get_password(self.service_name, self.username)

        if password is None:
            logger.debug(
                "credentials_not_found",
                source="keyring",
                service_name=self.service_name,
            )
            return None

        # Parse the stored JSON
        data = json.loads(password)
        credentials = ClaudeCredentials.model_validate(data)

        self._log_credential_details(credentials)
        return credentials

    except json.JSONDecodeError as e:
        raise CredentialsStorageError(
            f"Failed to parse credentials from keyring: {e}"
        ) from e
    except Exception as e:
        raise CredentialsStorageError(
            f"Error loading credentials from keyring: {e}"
        ) from e

save async

save(credentials)

Save credentials to the OS keyring.

Parameters:

Name Type Description Default
credentials ClaudeCredentials

Credentials to save

required

Returns:

Type Description
bool

True if saved successfully, False otherwise

Raises:

Type Description
CredentialsStorageError

If there's an error writing to keyring

Source code in ccproxy/auth/storage/keyring.py
async def save(self, credentials: ClaudeCredentials) -> bool:
    """Save credentials to the OS keyring.

    Args:
        credentials: Credentials to save

    Returns:
        True if saved successfully, False otherwise

    Raises:
        CredentialsStorageError: If there's an error writing to keyring
    """
    try:
        import keyring
    except ImportError as e:
        raise CredentialsStorageError(
            "keyring package is required for keyring storage. "
            "Install it with: pip install keyring"
        ) from e

    try:
        # Convert to JSON string
        data = credentials.model_dump(by_alias=True)
        json_data = json.dumps(data)

        # Store in keyring
        keyring.set_password(self.service_name, self.username, json_data)

        logger.debug(
            "credentials_save_completed",
            source="keyring",
            service_name=self.service_name,
        )
        return True

    except Exception as e:
        raise CredentialsStorageError(
            f"Error saving credentials to keyring: {e}"
        ) from e

exists async

exists()

Check if credentials exist in the keyring.

Returns:

Type Description
bool

True if credentials exist, False otherwise

Source code in ccproxy/auth/storage/keyring.py
async def exists(self) -> bool:
    """Check if credentials exist in the keyring.

    Returns:
        True if credentials exist, False otherwise
    """
    try:
        import keyring
    except ImportError:
        return False

    try:
        password = keyring.get_password(self.service_name, self.username)
        return password is not None
    except Exception:
        return False

delete async

delete()

Delete credentials from the keyring.

Returns:

Type Description
bool

True if deleted successfully, False otherwise

Raises:

Type Description
CredentialsStorageError

If there's an error deleting from keyring

Source code in ccproxy/auth/storage/keyring.py
async def delete(self) -> bool:
    """Delete credentials from the keyring.

    Returns:
        True if deleted successfully, False otherwise

    Raises:
        CredentialsStorageError: If there's an error deleting from keyring
    """
    try:
        import keyring
    except ImportError as e:
        raise CredentialsStorageError(
            "keyring package is required for keyring storage. "
            "Install it with: pip install keyring"
        ) from e

    try:
        if await self.exists():
            keyring.delete_password(self.service_name, self.username)
            logger.debug(
                "credentials_delete_completed",
                source="keyring",
                service_name=self.service_name,
            )
            return True
        return False
    except Exception as e:
        raise CredentialsStorageError(
            f"Error deleting credentials from keyring: {e}"
        ) from e

get_location

get_location()

Get the storage location description.

Returns:

Type Description
str

Description of the keyring storage location

Source code in ccproxy/auth/storage/keyring.py
def get_location(self) -> str:
    """Get the storage location description.

    Returns:
        Description of the keyring storage location
    """
    return f"OS keyring (service: {self.service_name}, user: {self.username})"