Saxo connector

This commit is contained in:
OpenSquared
2026-07-18 17:14:13 +02:00
parent 91054979ec
commit bff2f70781
10 changed files with 826 additions and 2 deletions

View File

@@ -0,0 +1,41 @@
"""OAuth2 login/callback for Saxo — paths outside /api, matching the callback URL
registered on the Saxo app dashboard (https://openfin.open-squared.tech/oauth/saxo/callback)."""
import logging
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import RedirectResponse
from services import saxo_auth
logger = logging.getLogger(__name__)
router = APIRouter(tags=["saxo-oauth"])
FRONTEND_CONFIG_URL = "/config"
@router.get("/oauth/saxo/login")
def saxo_login():
if not saxo_auth.is_configured():
raise HTTPException(status_code=400, detail="SAXO_APP_KEY / SAXO_APP_SECRET manquants dans backend/.env")
state = saxo_auth.new_login_state()
return RedirectResponse(saxo_auth.build_authorize_url(state))
@router.get("/oauth/saxo/callback")
def saxo_callback(code: str = Query(...), state: str = Query(...)):
if not saxo_auth.consume_and_verify_state(state):
raise HTTPException(status_code=400, detail="État OAuth invalide (CSRF) — relancez la connexion depuis Config.")
try:
saxo_auth.exchange_code_for_tokens(code)
except Exception as e:
logger.error(f"[Saxo OAuth] Token exchange failed: {e}")
return RedirectResponse(f"{FRONTEND_CONFIG_URL}?saxo_error=1")
return RedirectResponse(f"{FRONTEND_CONFIG_URL}?saxo_connected=1")
@router.post("/oauth/saxo/refresh")
def saxo_manual_refresh():
result = saxo_auth.refresh_tokens()
if not result:
raise HTTPException(status_code=400, detail="Saxo n'est pas connecté")
return {"refreshed": True}