CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-safety

Scan dependencies for known vulnerabilities and licenses.

Overall
score

61%

Overview
Eval results
Files

authentication.mddocs/

Authentication System

Safety CLI provides a comprehensive authentication system for accessing the Safety platform services. The system supports multiple authentication methods including OAuth2 token-based authentication and API key authentication.

Core Authentication Architecture

Authentication Models { .api }

Import Statements:

from safety.auth.models import Auth, Organization, XAPIKeyAuth
from safety.auth.utils import SafetyAuthSession
from safety.auth.cli_utils import (
    auth_options, proxy_options, 
    build_client_session, inject_session
)
from safety_schemas.models import Stage

Organization Model { .api }

Description: Represents a Safety platform organization for multi-tenant authentication.

@dataclass
class Organization:
    id: str                                       # Unique organization identifier
    name: str                                     # Organization display name
    
    def to_dict(self) -> Dict[str, Any]:
        """
        Convert organization to dictionary format.
        
        Returns:
            Dict[str, Any]: Organization data as dictionary
        """

Example Usage:

from safety.auth.models import Organization

# Create organization instance
org = Organization(id="12345", name="My Company")
org_dict = org.to_dict()
# Output: {"id": "12345", "name": "My Company"}

Auth Model { .api }

Description: Central authentication state container managing credentials, client sessions, and user information.

@dataclass
class Auth:
    org: Optional[Organization]                   # Associated organization
    keys: Any                                     # OAuth keys and certificates
    client: Any                                   # HTTP client session
    code_verifier: str                           # OAuth2 PKCE code verifier
    client_id: str                               # OAuth2 client identifier
    stage: Optional[Stage] = Stage.development   # Environment stage
    email: Optional[str] = None                  # User email address
    name: Optional[str] = None                   # User display name
    email_verified: bool = False                 # Email verification status

Methods:

def is_valid(self) -> bool:
    """
    Validate current authentication state.
    
    Returns:
        bool: True if authentication is valid and active
    """

def refresh_from(self, info: Dict[str, Any]) -> None:
    """
    Update authentication state from user information.
    
    Args:
        info (Dict[str, Any]): User profile information from OAuth provider
    """

def get_auth_method(self) -> str:
    """
    Get current authentication method being used.
    
    Returns:
        str: Authentication method ("API Key", "Token", or "None")
    """

Example Usage:

from safety.auth.models import Auth, Organization
from safety_schemas.models import Stage

# Create auth instance
auth = Auth(
    org=Organization(id="123", name="My Org"),
    keys={},
    client=None,
    code_verifier="abc123",
    client_id="safety-cli",
    stage=Stage.PRODUCTION,
    email="user@company.com",
    name="John Doe",
    email_verified=True
)

# Check authentication validity
if auth.is_valid():
    print(f"Authenticated as {auth.name} using {auth.get_auth_method()}")

Authentication Session Management { .api }

SafetyAuthSession Class { .api }

Description: Extended OAuth2Session with Safety-specific authentication handling and API integration.

class SafetyAuthSession(OAuth2Session):
    def __init__(self, *args: Any, **kwargs: Any) -> None:
        """
        Initialize Safety authentication session.
        
        Args:
            *args: Positional arguments for OAuth2Session
            **kwargs: Keyword arguments for OAuth2Session
        """
        
    # Authentication state properties
    proxy_required: bool                          # Require proxy for requests
    proxy_timeout: Optional[int]                 # Proxy timeout in seconds  
    api_key: Optional[str]                       # API key for authentication

Authentication Methods:

def get_credential(self) -> Optional[str]:
    """
    Get current authentication credential (API key or token).
    
    Returns:
        Optional[str]: Current credential or None if not authenticated
    """

def is_using_auth_credentials(self) -> bool:
    """
    Check if session is configured with authentication credentials.
    
    Note: This checks configuration, not validity of credentials.
    
    Returns:
        bool: True if credentials are configured
    """

def get_authentication_type(self) -> AuthenticationType:
    """
    Determine the type of authentication being used.
    
    Returns:
        AuthenticationType: Current authentication type (api_key, token, or none)
    """

HTTP Request Handling:

def request(
    self,
    method: str,                                 # HTTP method (GET, POST, etc.)
    url: str,                                    # Request URL
    withhold_token: bool = False,                # Skip token authentication
    auth: Optional[Tuple] = None,                # Custom authentication
    bearer: bool = True,                         # Use bearer token format
    **kwargs: Any                                # Additional request parameters
) -> requests.Response:
    """
    Make authenticated HTTP request with automatic credential handling.
    
    Automatically adds appropriate authentication headers:
    - X-Api-Key header for API key authentication
    - Authorization Bearer header for token authentication
    - Safety CLI metadata headers
    
    Args:
        method: HTTP method to use
        url: Target URL for request
        withhold_token: Skip automatic token authentication
        auth: Custom authentication tuple
        bearer: Use bearer token format
        **kwargs: Additional parameters (headers, timeout, etc.)
        
    Returns:
        requests.Response: HTTP response object
        
    Raises:
        RequestTimeoutError: If request times out
        NetworkConnectionError: If network connection fails
        ServerError: If server returns error status
    """

Authentication Types { .api }

from safety.scan.util import AuthenticationType

class AuthenticationType(Enum):
    NONE = "none"                                # No authentication
    API_KEY = "api_key"                         # API key authentication
    TOKEN = "token"                             # OAuth2 token authentication

API Key Authentication { .api }

XAPIKeyAuth Class { .api }

Description: API key authentication handler for requests.

class XAPIKeyAuth(BaseOAuth):
    def __init__(self, api_key: str) -> None:
        """
        Initialize API key authentication.
        
        Args:
            api_key (str): Safety platform API key
        """
        
    def __call__(self, request: Any) -> Any:
        """
        Add API key to request headers.
        
        Args:
            request: HTTP request object to modify
            
        Returns:
            Any: Modified request with X-API-Key header
        """

Example Usage:

from safety.auth.models import XAPIKeyAuth
import requests

# Create API key authenticator
auth = XAPIKeyAuth("sk-12345abcdef")

# Use with requests
response = requests.get(
    "https://api.safetycli.com/scan", 
    auth=auth
)

Authentication Commands Integration

CLI Authentication Decorators { .api }

Description: Decorators for integrating authentication into CLI commands.

from safety.auth.cli_utils import auth_options, proxy_options, inject_session

@auth_options
@proxy_options
def my_command(ctx, ...):
    """Command with authentication support."""
    # Authentication automatically injected into ctx.obj.auth
    session = ctx.obj.auth.client

auth_options Decorator { .api }

Description: Adds authentication-related command line options.

Added Options:

--key TEXT                     # API key for authentication
--auth-org-id TEXT            # Organization ID override
--auth-stage {development,staging,production}  # Environment stage

proxy_options Decorator { .api }

Description: Adds proxy configuration options for corporate environments.

Added Options:

--proxy-protocol {http,https}  # Proxy protocol
--proxy-host TEXT             # Proxy hostname
--proxy-port INTEGER          # Proxy port number
--proxy-timeout INTEGER       # Proxy timeout in seconds

inject_session Decorator { .api }

Description: Injects authenticated session into command context.

Usage Pattern:

@inject_session
def authenticated_command(ctx):
    """Command with automatic session injection."""
    # Access authenticated session
    session: SafetyAuthSession = ctx.obj.auth.client
    
    # Make authenticated requests
    response = session.get("https://api.safetycli.com/user/profile")

Session Building { .api }

build_client_session Function { .api }

Description: Factory function for creating authenticated client sessions.

def build_client_session(
    api_key: Optional[str] = None,               # API key override
    proxy_protocol: Optional[str] = None,        # Proxy protocol
    proxy_host: Optional[str] = None,            # Proxy hostname 
    proxy_port: Optional[int] = None,            # Proxy port
    proxy_timeout: Optional[int] = None,         # Proxy timeout
    organization: Optional[Organization] = None,  # Target organization
    stage: Optional[Stage] = None                # Environment stage
) -> SafetyAuthSession:
    """
    Build authenticated client session with specified configuration.
    
    Args:
        api_key: API key for authentication (overrides stored credentials)
        proxy_protocol: HTTP/HTTPS proxy protocol
        proxy_host: Proxy server hostname
        proxy_port: Proxy server port number
        proxy_timeout: Timeout for proxy connections
        organization: Target organization for multi-tenant access
        stage: Environment stage for configuration
        
    Returns:
        SafetyAuthSession: Configured authenticated session
        
    Raises:
        InvalidCredentialError: If provided credentials are invalid
        NetworkConnectionError: If proxy configuration is invalid
    """

Example Usage:

from safety.auth.cli_utils import build_client_session
from safety.auth.models import Organization
from safety_schemas.models import Stage

# Build session with API key
session = build_client_session(
    api_key="sk-12345abcdef",
    organization=Organization(id="123", name="My Org"),
    stage=Stage.PRODUCTION
)

# Build session with proxy
session = build_client_session(
    proxy_protocol="https",
    proxy_host="proxy.company.com", 
    proxy_port=8080,
    proxy_timeout=30
)

Platform API Integration

Core API Endpoints { .api }

The SafetyAuthSession provides methods for interacting with Safety platform APIs:

# User and organization management
session.get_user_info() -> Dict[str, Any]                    # Get user profile
session.get_organizations() -> List[Organization]            # List organizations

# Project and scan management  
session.create_project(name: str, org_id: str) -> Dict      # Create project
session.upload_requirements(payload: Dict) -> Response      # Upload scan data
session.download_policy(
    project_id: str, 
    stage: Stage, 
    branch: Optional[str]
) -> Optional[Dict]                                          # Download policy

# Vulnerability data access
session.get_vulnerabilities(packages: List) -> List         # Get vulnerability data
session.get_licenses(packages: List) -> Dict                # Get license data

Authentication Flow Integration {.api }

from safety.auth.main import get_authorization_data, handle_authentication_flow

def get_authorization_data(
    client: SafetyAuthSession,                   # Client session
    code_verifier: str,                         # PKCE code verifier
    organization: Optional[Organization] = None, # Target organization
    headless: bool = False                      # Headless mode flag
) -> Tuple[str, Dict]:
    """
    Generate OAuth2 authorization URL and initial state.
    
    Args:
        client: Authenticated client session
        code_verifier: PKCE code verifier for security
        organization: Target organization for login
        headless: Enable headless mode for CI/CD
        
    Returns:
        Tuple[str, Dict]: Authorization URL and initial state data
    """

def handle_authentication_flow(
    ctx,                                        # Command context
    authorization_url: str,                     # OAuth authorization URL
    initial_state: Dict,                        # Initial authentication state
    headless: bool = False                      # Headless mode flag
) -> bool:
    """
    Handle complete OAuth2 authentication flow.
    
    Args:
        ctx: Typer command context
        authorization_url: URL for user authentication
        initial_state: Authentication state data
        headless: Use headless authentication mode
        
    Returns:
        bool: True if authentication successful
        
    Raises:
        InvalidCredentialError: If authentication fails
        NetworkConnectionError: If unable to connect to auth server
    """

Error Handling { .api }

Authentication Exceptions { .api }

from safety.errors import (
    InvalidCredentialError,
    NetworkConnectionError, 
    RequestTimeoutError,
    ServerError,
    TooManyRequestsError
)

# Authentication-specific errors
class InvalidCredentialError(SafetyError):
    """Raised when provided credentials are invalid or expired."""
    
class NetworkConnectionError(SafetyError):
    """Raised when unable to establish network connection."""
    
class RequestTimeoutError(SafetyError):
    """Raised when requests exceed configured timeout."""

Error Handling Patterns { .api }

from safety.auth.utils import SafetyAuthSession
from safety.errors import InvalidCredentialError

try:
    session = SafetyAuthSession()
    session.api_key = "sk-invalid-key"
    
    response = session.get("https://api.safetycli.com/user/profile")
    response.raise_for_status()
    
except InvalidCredentialError as e:
    print(f"Authentication failed: {e}")
except NetworkConnectionError as e:
    print(f"Network error: {e}")
except RequestTimeoutError as e:
    print(f"Request timed out: {e}")

Configuration and Environment

Environment Variables { .api }

Authentication behavior can be configured via environment variables:

# API authentication
SAFETY_API_KEY                 # Default API key
SAFETY_API_BASE_URL           # API base URL override

# Proxy configuration  
SAFETY_PROXY_HOST             # Proxy hostname
SAFETY_PROXY_PORT             # Proxy port
SAFETY_PROXY_PROTOCOL         # Proxy protocol (http/https)
SAFETY_PROXY_TIMEOUT          # Proxy timeout in seconds

# OAuth configuration
SAFETY_AUTH_SERVER_URL        # Authentication server URL
SAFETY_CLIENT_ID              # OAuth2 client ID

Configuration Files { .api }

Authentication settings are stored in Safety configuration directories:

# User configuration (Linux/macOS)
~/.config/safety/auth.json

# System configuration  
/etc/safety/auth.json

# Windows user configuration
%APPDATA%\safety\auth.json

Usage Examples

Basic Authentication Setup

from safety.auth.cli_utils import build_client_session
from safety.auth.models import Organization
from safety_schemas.models import Stage

# API Key Authentication
session = build_client_session(api_key="sk-12345abcdef")

# OAuth Token Authentication (requires prior login)
session = build_client_session()

# Organization-specific Authentication
org = Organization(id="123", name="My Company")
session = build_client_session(
    organization=org,
    stage=Stage.PRODUCTION
)

Corporate Proxy Configuration

# Configure session with corporate proxy
session = build_client_session(
    api_key="sk-12345abcdef",
    proxy_protocol="https",
    proxy_host="proxy.company.com",
    proxy_port=8080,
    proxy_timeout=60
)

# Make authenticated request through proxy
response = session.get("https://api.safetycli.com/scan")

Multi-Organization Access

from safety.auth.models import Auth, Organization

# List available organizations
session = build_client_session()
orgs_response = session.get("/organizations")
organizations = [
    Organization(id=org["id"], name=org["name"])
    for org in orgs_response.json()
]

# Switch to specific organization
target_org = organizations[0]
org_session = build_client_session(organization=target_org)

Authentication State Management

from safety.auth.models import Auth

# Check authentication status
auth = Auth(...)  # Initialized from context

if auth.is_valid():
    method = auth.get_auth_method()
    print(f"Authenticated via {method}")
    
    if auth.org:
        print(f"Organization: {auth.org.name}")
    
    if auth.email:
        print(f"User: {auth.name} ({auth.email})")
else:
    print("Not authenticated")

This comprehensive authentication documentation covers all aspects of Safety CLI's authentication system, enabling developers to implement secure and robust integrations with the Safety platform.

Install with Tessl CLI

npx tessl i tessl/pypi-safety

docs

authentication.md

cli-commands.md

configuration.md

errors.md

formatters.md

index.md

models.md

programmatic.md

scanning.md

tile.json