fix: auto-login after signup and context-aware token clearing

This fixes the "Authorization header required for API calls" error during
vendor onboarding after signup.

Changes:
- Generate JWT access token on signup completion
- Set vendor_token cookie for page navigation
- Return access_token in signup response for localStorage
- Store vendor_token in localStorage after signup completion
- Make clearTokens() context-aware to prevent cross-portal interference
- Fix vendor logout to not clear admin/customer tokens

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-28 18:10:18 +01:00
parent 3c403ab1b8
commit 4298af9f79
6 changed files with 85 additions and 13 deletions

View File

@@ -14,11 +14,12 @@ All endpoints are public (no authentication required).
import logging
from fastapi import APIRouter, Depends
from fastapi import APIRouter, Depends, Response
from pydantic import BaseModel, EmailStr
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.core.environment import should_use_secure_cookies
from app.services.platform_signup_service import platform_signup_service
router = APIRouter()
@@ -111,6 +112,7 @@ class CompleteSignupResponse(BaseModel):
vendor_id: int
redirect_url: str
trial_ends_at: str
access_token: str | None = None # JWT token for automatic login
# =============================================================================
@@ -215,12 +217,14 @@ async def setup_payment(request: SetupPaymentRequest) -> SetupPaymentResponse:
@router.post("/signup/complete", response_model=CompleteSignupResponse) # public
async def complete_signup(
request: CompleteSignupRequest,
response: Response,
db: Session = Depends(get_db),
) -> CompleteSignupResponse:
"""
Complete signup after card collection.
Step 5: Verify SetupIntent, attach payment method, create subscription.
Also sets HTTP-only cookie for page navigation and returns token for localStorage.
"""
result = platform_signup_service.complete_signup(
db=db,
@@ -228,12 +232,27 @@ async def complete_signup(
setup_intent_id=request.setup_intent_id,
)
# Set HTTP-only cookie for page navigation (same as login does)
# This enables the user to access vendor pages immediately after signup
if result.access_token:
response.set_cookie(
key="vendor_token",
value=result.access_token,
httponly=True, # JavaScript cannot access (XSS protection)
secure=should_use_secure_cookies(), # HTTPS only in production/staging
samesite="lax", # CSRF protection
max_age=3600 * 24, # 24 hours
path="/vendor", # RESTRICTED TO VENDOR ROUTES ONLY
)
logger.info(f"Set vendor_token cookie for new vendor {result.vendor_code}")
return CompleteSignupResponse(
success=result.success,
vendor_code=result.vendor_code,
vendor_id=result.vendor_id,
redirect_url=result.redirect_url,
trial_ends_at=result.trial_ends_at,
access_token=result.access_token,
)