Skip to main content

Authentication Overview

Clipron AI uses a robust authentication system combining JWT tokens with OAuth providers for secure access to the platform. This guide covers all authentication methods and security features.

Authentication Methods

JWT Tokens

Primary authentication
  • Stateless authentication
  • Access and refresh tokens
  • Secure token signing

Google OAuth

Social authentication
  • One-click login
  • Secure profile sync
  • No password management

GitHub OAuth

Developer-focused
  • Repository access
  • Developer workflow integration
  • Seamless GitHub integration

JWT Token System

Token Types

Short-lived authentication token
  • Lifetime: 30 minutes (configurable)
  • Purpose: API access authorization
  • Storage: Memory or secure storage only
  • Refresh: Automatically refreshed by client
{
  "sub": "user_id_123",
  "email": "[email protected]",
  "exp": 1640995200,
  "iat": 1640993400,
  "type": "access"
}
Long-lived token renewal
  • Lifetime: 7 days (configurable)
  • Purpose: Generate new access tokens
  • Storage: Secure HTTP-only cookie
  • Rotation: New refresh token on each use
{
  "sub": "user_id_123",
  "exp": 1641600000,
  "iat": 1640993400,
  "type": "refresh",
  "jti": "unique_token_id"
}

Token Usage

Including tokens in requests
# Header-based authentication (recommended)
curl -H "Authorization: Bearer <access_token>" \
     https://clipron.com/api/user/profile

# Query parameter (not recommended for production)
curl "https://clipron.com/api/user/profile?token=<access_token>"

OAuth Integration

Google OAuth Flow

1

Initiate OAuth

User clicks “Sign in with Google” button
window.location.href = '/api/auth/google';
2

Google Authorization

User authorizes application on Google’s consent screen
https://accounts.google.com/oauth/authorize?
  client_id=your_client_id&
  redirect_uri=https://clipron.com/auth/google/callback&
  scope=openid email profile&
  response_type=code
3

Authorization Code Exchange

Google redirects back with authorization code
@app.get("/auth/google/callback")
async def google_callback(code: str):
    # Exchange code for tokens
    token_response = await exchange_code_for_tokens(code)
    user_info = await get_google_user_info(token_response.access_token)
    
    # Create or update user
    user = await create_or_update_user(user_info)
    
    # Generate JWT tokens
    access_token = create_access_token(user.id)
    refresh_token = create_refresh_token(user.id)
    
    return {"access_token": access_token, "refresh_token": refresh_token}
4

User Session Creation

Application creates user session with JWT tokens

GitHub OAuth Flow

1

GitHub Authorization

Similar to Google OAuth but with GitHub-specific scopes
https://github.com/login/oauth/authorize?
  client_id=your_github_client_id&
  redirect_uri=https://clipron.com/auth/github/callback&
  scope=user:email repo&
  state=random_state_string
2

Repository Access

GitHub OAuth includes repository access permissions
# After successful OAuth
github_token = oauth_response.access_token

# Store GitHub token for repository access
await store_github_token(user.id, github_token)

# Fetch user's repositories
repos = await fetch_github_repositories(github_token)
await sync_user_repositories(user.id, repos)

API Authentication

Authentication Headers

For server-to-server communication
GET /api/analysis HTTP/1.1
Host: clipron.com
X-API-Key: clipron_api_key_your_key_here
Content-Type: application/json

Authentication Middleware

from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials

security = HTTPBearer()

async def get_current_user(
    credentials: HTTPAuthorizationCredentials = Depends(security)
):
    """Extract and validate user from JWT token"""
    try:
        payload = verify_token(credentials.credentials)
        user_id = payload.get("sub")
        
        if user_id is None:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Invalid token"
            )
            
        user = await get_user_by_id(user_id)
        if user is None:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="User not found"
            )
            
        return user
        
    except JWTError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid token"
        )

# Usage in protected endpoints
@app.get("/api/user/profile")
async def get_profile(current_user: User = Depends(get_current_user)):
    return current_user

Authorization and Permissions

Role-Based Access Control

Different access levels
class UserRole(Enum):
    FREE = "free"
    PRO = "pro"
    ENTERPRISE = "enterprise"
    ADMIN = "admin"

# Role-based permissions
ROLE_PERMISSIONS = {
    UserRole.FREE: {
        "analyses_per_month": 50,
        "private_repos": False,
        "api_access": False,
        "priority_support": False
    },
    UserRole.PRO: {
        "analyses_per_month": 500,
        "private_repos": True,
        "api_access": True,
        "priority_support": True
    },
    UserRole.ENTERPRISE: {
        "analyses_per_month": -1,  # Unlimited
        "private_repos": True,
        "api_access": True,
        "priority_support": True,
        "custom_integrations": True
    }
}

Security Features

Rate Limiting

Prevent abuse and ensure fair usage
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address

limiter = Limiter(key_func=get_remote_address)

@app.post("/api/analysis")
@limiter.limit("10/minute")  # 10 analyses per minute
async def create_analysis(
    request: Request,
    analysis_data: dict,
    current_user: User = Depends(get_current_user)
):
    # Rate limited endpoint
    pass
Revoke compromised tokens
# Store blacklisted tokens (in Redis or database)
blacklisted_tokens = set()

def blacklist_token(token: str):
    """Add token to blacklist"""
    blacklisted_tokens.add(token)
    # Also store in persistent storage
    redis_client.sadd("blacklisted_tokens", token)

def is_token_blacklisted(token: str) -> bool:
    """Check if token is blacklisted"""
    return token in blacklisted_tokens or \
           redis_client.sismember("blacklisted_tokens", token)
Track and manage user sessions
class SessionManager:
    def __init__(self):
        self.active_sessions = {}
    
    async def create_session(self, user_id: str, token: str):
        """Create new user session"""
        session_id = generate_session_id()
        self.active_sessions[session_id] = {
            "user_id": user_id,
            "token": token,
            "created_at": datetime.utcnow(),
            "last_activity": datetime.utcnow()
        }
        return session_id
    
    async def invalidate_user_sessions(self, user_id: str):
        """Invalidate all sessions for a user"""
        sessions_to_remove = [
            sid for sid, session in self.active_sessions.items()
            if session["user_id"] == user_id
        ]
        for sid in sessions_to_remove:
            del self.active_sessions[sid]

Error Handling

Authentication Errors

401 Unauthorized

Missing or invalid token
  • Token expired
  • Invalid signature
  • Malformed token
  • Missing Authorization header

403 Forbidden

Insufficient permissions
  • Role-based access denied
  • Resource ownership violation
  • Feature not available for user tier

Error Response Format

{
  "error": {
    "code": "INVALID_TOKEN",
    "message": "The provided token is invalid or expired",
    "details": {
      "reason": "token_expired",
      "expired_at": "2024-01-01T12:00:00Z"
    }
  },
  "request_id": "req_123456789"
}
Security Tip: Always use HTTPS in production, store refresh tokens in secure HTTP-only cookies, and implement proper token rotation to maintain security.