Metadata-Version: 2.4
Name: secureauth-sdk
Version: 1.0.0
Summary: A secure authentication client for integrating with SecureAuth server
Home-page: https://github.com/secureauth/python-sdk
Author: SecureAuth Team
Author-email: support@secureauth.com
Project-URL: Bug Tracker, https://github.com/secureauth/python-sdk/issues
Project-URL: Documentation, https://secureauth.com/docs
Project-URL: Source Code, https://github.com/secureauth/python-sdk
Keywords: authentication security jwt api secureauth login oauth
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Internet
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: System :: Systems Administration :: Authentication/Directory
Requires-Python: >=3.7
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.28.0
Requires-Dist: cryptography>=3.4.0
Requires-Dist: flask>=2.0.0
Requires-Dist: python-dotenv>=0.19.0
Provides-Extra: dev
Requires-Dist: pytest>=6.0; extra == "dev"
Requires-Dist: pytest-cov>=2.0; extra == "dev"
Requires-Dist: black>=21.0; extra == "dev"
Requires-Dist: flake8>=3.8; extra == "dev"
Requires-Dist: mypy>=0.800; extra == "dev"
Provides-Extra: docs
Requires-Dist: sphinx>=4.0; extra == "docs"
Requires-Dist: sphinx-rtd-theme>=0.5; extra == "docs"
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: license-file
Dynamic: project-url
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# SecureAuth Python SDK

A secure Python client for integrating with SecureAuth authentication system.

## Installation

### Requirements
- Python 3.7+
- pip package manager

### Install Dependencies
```bash
pip install requests cryptography
```

### Install the SDK
1. Copy the `secureauth_client.py` file to your project
2. Or install it as a module:

```bash
# Option 1: Copy the file
cp secureauth_client.py your_project/

# Option 2: Install as package (if you create setup.py)
pip install secureauth-python-sdk
```

## Quick Start

### Basic Usage

```python
from secureauth_client import SecureAuthClient, SecureAuthError

# Initialize the client
client = SecureAuthClient(
    api_key="your_api_key_here",
    api_secret="your_api_secret_here", 
    base_url="http://localhost:3002"  # Your SecureAuth server URL
)

# Verify a token
try:
    result = client.verify_token("jwt_token_here")
    if result['success']:
        print(f"User authenticated: {result['user']['email']}")
    else:
        print(f"Authentication failed: {result['error']}")
except SecureAuthError as e:
    print(f"Error: {e}")
```

### Flask Integration

```python
from flask import Flask, request, jsonify
from secureauth_client import SecureAuthClient, SecureAuthFlask

app = Flask(__name__)

# Configure SecureAuth
app.config['SECUREAUTH_API_KEY'] = 'your_api_key'
app.config['SECUREAUTH_API_SECRET'] = 'your_api_secret'
app.config['SECUREAUTH_BASE_URL'] = 'http://localhost:3002'

# Initialize SecureAuth
secureauth = SecureAuthFlask(app)

@app.route('/protected')
@secureauth.require_auth
def protected():
    return jsonify({
        'message': 'Access granted',
        'user': request.current_user
    })

@app.route('/admin')
@secureauth.require_auth
@secureauth.require_role('admin')
def admin_only():
    return jsonify({'message': 'Admin access granted'})

if __name__ == '__main__':
    app.run(debug=True)
```

### Django Integration

```python
# settings.py
SECUREAUTH_API_KEY = 'your_api_key'
SECUREAUTH_API_SECRET = 'your_api_secret'
SECUREAUTH_BASE_URL = 'http://localhost:3002'

# middleware.py
from secureauth_client import SecureAuthClient
from django.http import JsonResponse
from django.core.exceptions import PermissionDenied

class SecureAuthMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        self.client = SecureAuthClient(
            api_key=settings.SECUREAUTH_API_KEY,
            api_secret=settings.SECUREAUTH_API_SECRET,
            base_url=settings.SECUREAUTH_BASE_URL
        )

    def __call__(self, request):
        # Skip authentication for certain paths
        if request.path.startswith('/admin/login') or request.path.startswith('/static'):
            return self.get_response(request)

        auth_header = request.META.get('HTTP_AUTHORIZATION')
        if not auth_header or not auth_header.startswith('Bearer '):
            return JsonResponse({'error': 'Authentication required'}, status=401)

        token = auth_header[7:]  # Remove 'Bearer '
        
        try:
            result = self.client.verify_token(token)
            if result['success']:
                request.user = result['user']
                return self.get_response(request)
            else:
                return JsonResponse({'error': result['error']}, status=401)
        except Exception as e:
            return JsonResponse({'error': str(e)}, status=401)

# views.py
from django.views.decorators.http import require_http_methods
from django.http import JsonResponse
from secureauth_client import SecureAuthClient

@require_http_methods(["GET"])
def protected_view(request):
    return JsonResponse({
        'message': 'Access granted',
        'user': request.user
    })
```

## API Reference

### SecureAuthClient Methods

#### `verify_token(token)`
Verify a JWT token and return user information.

**Parameters:**
- `token` (str): JWT token to verify

**Returns:** Dictionary with verification result

```python
result = client.verify_token("eyJhbGciOiJIUzI1NiIs...")
```

#### `get_user_info(user_id)`
Get detailed user information.

**Parameters:**
- `user_id` (str): User ID to fetch

**Returns:** User information dictionary

```python
user_info = client.get_user_info("user_123")
```

#### `create_user_session(user_id, device_info=None)`
Create a new user session.

**Parameters:**
- `user_id` (str): User ID
- `device_info` (dict, optional): Device fingerprinting data

**Returns:** Session creation result

```python
session = client.create_user_session(
    "user_123",
    device_info={
        "user_agent": "Mozilla/5.0...",
        "ip_address": "192.168.1.1"
    }
)
```

#### `revoke_session(session_id)`
Revoke a user session.

**Parameters:**
- `session_id` (str): Session ID to revoke

**Returns:** Revocation result

```python
result = client.revoke_session("session_123")
```

#### `get_user_sessions(user_id)`
Get all active sessions for a user.

**Parameters:**
- `user_id` (str): User ID

**Returns:** List of user sessions

```python
sessions = client.get_user_sessions("user_123")
```

#### `log_security_event(event_type, severity, details)`
Log a security event.

**Parameters:**
- `event_type` (str): Type of security event
- `severity` (str): Event severity ('low', 'medium', 'high', 'critical')
- `details` (dict): Event details

**Returns:** Event logging result

```python
result = client.log_security_event(
    "suspicious_login",
    "medium",
    {"ip": "192.168.1.1", "user_agent": "..."}
)
```

#### `check_permissions(user_id, permission)`
Check if user has specific permission.

**Parameters:**
- `user_id` (str): User ID
- `permission` (str): Permission to check

**Returns:** Permission check result

```python
result = client.check_permissions("user_123", "admin_access")
```

#### `update_user_role(user_id, role)`
Update user role.

**Parameters:**
- `user_id` (str): User ID
- `role` (str): New role ('user', 'admin', 'moderator')

**Returns:** Role update result

```python
result = client.update_user_role("user_123", "admin")
```

### Decorators

#### `@secureauth.require_auth`
Require authentication for a view/function.

#### `@secureauth.require_role(*roles)`
Require specific role(s) for access.

#### `@secureauth.require_verification`
Require user to be verified.

## Examples

### Complete Flask Application

```python
from flask import Flask, request, jsonify, render_template_string
from secureauth_client import SecureAuthClient, SecureAuthFlask, SecureAuthError

app = Flask(__name__)
app.secret_key = 'your-secret-key'

# SecureAuth configuration
app.config['SECUREAUTH_API_KEY'] = 'sak_6266b5a44517a29999cead848062739b81e6d7343f71062eed3001d18b651efa'
app.config['SECUREAUTH_API_SECRET'] = '40d4435182c2fe81a3ce66b47d9a0d50b6847114d78694c08c7309279fdf231df727d4aa38948f5408524e3a6d5fcb2ff81d40283a3fe1861fabaad6a6eaa867'
app.config['SECUREAUTH_BASE_URL'] = 'http://localhost:3002'

# Initialize SecureAuth
secureauth = SecureAuthFlask(app)

# HTML Template
HTML_TEMPLATE = """
<!DOCTYPE html>
<html>
<head>
    <title>SecureAuth Python Demo</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .container { max-width: 600px; margin: 0 auto; }
        .form-group { margin: 15px 0; }
        label { display: block; margin-bottom: 5px; }
        input { width: 100%; padding: 8px; }
        button { padding: 10px 20px; background: #007bff; color: white; border: none; }
        .error { color: red; }
        .success { color: green; }
    </style>
</head>
<body>
    <div class="container">
        <h1>SecureAuth Python Demo</h1>
        {% if error %}
        <div class="error">{{ error }}</div>
        {% endif %}
        {% if success %}
        <div class="success">{{ success }}</div>
        {% endif %}
        
        {% if not current_user %}
        <form method="post">
            <div class="form-group">
                <label>Email:</label>
                <input type="email" name="email" value="fwaaryn@gmail.com" required>
            </div>
            <div class="form-group">
                <label>Password:</label>
                <input type="password" name="password" value="2117" required>
            </div>
            <button type="submit">Login</button>
        </form>
        {% else %}
        <h2>Welcome, {{ current_user.username }}!</h2>
        <p>Email: {{ current_user.email }}</p>
        <p>Role: {{ current_user.role }}</p>
        <p>Verified: {{ 'Yes' if current_user.is_verified else 'No' }}</p>
        
        <h3>API Test Results:</h3>
        <pre>{{ api_results }}</pre>
        
        <form method="post" action="/logout">
            <button type="submit">Logout</button>
        </form>
        {% endif %}
    </div>
</body>
</html>
"""

@app.route('/')
def index():
    return render_template_string(HTML_TEMPLATE)

@app.route('/', methods=['POST'])
def login():
    email = request.form.get('email')
    password = request.form.get('password')
    
    try:
        # Direct login to SecureAuth server
        import requests
        login_url = f"{app.config['SECUREAUTH_BASE_URL']}/api/v1/auth/login"
        
        response = requests.post(login_url, json={
            'email': email,
            'password': password,
            'deviceFingerprint': request.headers.get('User-Agent', '')
        })
        
        if response.status_code == 200:
            result = response.json()
            # Store token in session
            from flask import session
            session['access_token'] = result['accessToken']
            session['user'] = result['user']
            
            return render_template_string(HTML_TEMPLATE, 
                current_user=result['user'],
                success="Login successful!")
        else:
            error_data = response.json() if response.headers.get('content-type') == 'application/json' else {}
            return render_template_string(HTML_TEMPLATE, 
                error=error_data.get('error', 'Login failed'))
            
    except Exception as e:
        return render_template_string(HTML_TEMPLATE, error=f"Login error: {str(e)}")

@app.route('/dashboard')
@secureauth.require_auth
def dashboard():
    client = SecureAuthClient(
        app.config['SECUREAUTH_API_KEY'],
        app.config['SECUREAUTH_API_SECRET'],
        app.config['SECUREAUTH_BASE_URL']
    )
    
    api_results = {}
    
    try:
        # Test various API endpoints
        api_results['profile'] = client.get_user_info(request.current_user['id'])
        api_results['sessions'] = client.get_user_sessions(request.current_user['id'])
        
        if request.current_user['role'] == 'admin':
            api_results['admin_dashboard'] = client.log_security_event(
                'dashboard_access', 
                'low', 
                {'user': request.current_user['username']}
            )
    except Exception as e:
        api_results['error'] = str(e)
    
    return render_template_string(HTML_TEMPLATE, 
        current_user=request.current_user,
        api_results=str(api_results))

@app.route('/logout', methods=['POST'])
def logout():
    from flask import session
    session.clear()
    return render_template_string(HTML_TEMPLATE, success="Logged out successfully!")

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)
```

### FastAPI Integration

```python
from fastapi import FastAPI, Depends, HTTPException, Request
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from secureauth_client import SecureAuthClient, SecureAuthError
from pydantic import BaseModel

app = FastAPI()
security = HTTPBearer()

# Initialize SecureAuth client
secureauth_client = SecureAuthClient(
    api_key="your_api_key",
    api_secret="your_api_secret",
    base_url="http://localhost:3002"
)

class LoginRequest(BaseModel):
    email: str
    password: str

async def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(security)):
    try:
        result = secureauth_client.verify_token(credentials.credentials)
        if not result['success']:
            raise HTTPException(status_code=401, detail="Invalid token")
        return result['user']
    except SecureAuthError as e:
        raise HTTPException(status_code=401, detail=str(e))

@app.post("/login")
async def login(request: LoginRequest):
    try:
        import requests
        response = requests.post("http://localhost:3002/api/v1/auth/login", json={
            "email": request.email,
            "password": request.password,
            "deviceFingerprint": "FastAPI Client"
        })
        
        if response.status_code == 200:
            return response.json()
        else:
            raise HTTPException(status_code=400, detail="Login failed")
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/protected")
async def protected(current_user: dict = Depends(get_current_user)):
    return {"message": "Access granted", "user": current_user}

@app.get("/admin")
async def admin_only(current_user: dict = Depends(get_current_user)):
    if current_user.get('role') != 'admin':
        raise HTTPException(status_code=403, detail="Admin access required")
    return {"message": "Admin access granted", "user": current_user}
```

## Configuration

### Environment Variables

Create a `.env` file in your project:

```env
SECUREAUTH_API_KEY=your_api_key_here
SECUREAUTH_API_SECRET=your_api_secret_here
SECUREAUTH_BASE_URL=http://localhost:3002
```

### Configuration File

```python
# config.py
import os
from dotenv import load_dotenv

load_dotenv()

SECUREAUTH_CONFIG = {
    'api_key': os.getenv('SECUREAUTH_API_KEY'),
    'api_secret': os.getenv('SECUREAUTH_API_SECRET'),
    'base_url': os.getenv('SECUREAUTH_BASE_URL', 'http://localhost:3002'),
    'timeout': 30,
    'retry_attempts': 3
}
```

## Error Handling

```python
from secureauth_client import SecureAuthError, SecureAuthClient

try:
    client = SecureAuthClient(api_key, api_secret, base_url)
    result = client.verify_token(token)
except SecureAuthError as e:
    print(f"SecureAuth error: {e}")
    # Handle authentication error
except Exception as e:
    print(f"Unexpected error: {e}")
    # Handle other errors
```

## Security Best Practices

1. **Store credentials securely**: Use environment variables, not hardcoded values
2. **Use HTTPS**: Always use HTTPS in production
3. **Validate tokens**: Always verify tokens on each request
4. **Handle errors gracefully**: Don't expose sensitive information in error messages
5. **Implement rate limiting**: Add client-side rate limiting
6. **Log security events**: Log authentication attempts and failures

## Testing

```python
import unittest
from secureauth_client import SecureAuthClient, SecureAuthError

class TestSecureAuthClient(unittest.TestCase):
    def setUp(self):
        self.client = SecureAuthClient(
            api_key="test_key",
            api_secret="test_secret",
            base_url="http://localhost:3002"
        )
    
    def test_verify_token(self):
        # Test with valid token
        result = self.client.verify_token("valid_token")
        self.assertTrue(result['success'])
    
    def test_verify_invalid_token(self):
        # Test with invalid token
        with self.assertRaises(SecureAuthError):
            self.client.verify_token("invalid_token")

if __name__ == '__main__':
    unittest.main()
```

## Deployment

### Docker

```dockerfile
FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY secureauth_client.py .
COPY your_app.py .

EXPOSE 5000

CMD ["python", "your_app.py"]
```

### Requirements.txt

```
requests>=2.28.0
cryptography>=3.4.0
flask>=2.0.0  # if using Flask
django>=4.0.0   # if using Django
fastapi>=0.68.0 # if using FastAPI
python-dotenv>=0.19.0
```

## Support

For issues and questions:
1. Check the [SecureAuth Documentation](../INTEGRATION_GUIDE.md)
2. Review the API endpoints in your SecureAuth server
3. Test with the provided examples
4. Check server logs for authentication errors
