wip use a transit token

This commit is contained in:
lebaudantoine
2026-04-02 17:43:25 +02:00
parent f6ec01f3c8
commit 0ee050ab37
4 changed files with 35 additions and 13 deletions
@@ -50,8 +50,8 @@ function startPolling(session_id, { onSuccess, onTimeout, onError }) {
// ─── Transit Dialog ───────────────────────────────────────────────────────
function openTransitDialog(session_id, { onCancel, onError }) {
const meetUrl = `${BASE_URL}/addons/transit/?session_id=${session_id}`;
function openTransitDialog(transit_token, { onCancel, onError }) {
const meetUrl = `${BASE_URL}/addons/transit/?transit_token=${transit_token}`;
Office.context.ui.displayDialogAsync(
meetUrl,
@@ -92,6 +92,7 @@ function connect() {
.then((res) => res.json())
.then((data) => {
const session_id = data.session_id;
const transit_token = data.transit_token;
setStatus("En attente d'authentification...");
const pollInterval = startPolling(session_id, {
@@ -109,7 +110,7 @@ function connect() {
},
});
openTransitDialog(session_id, {
openTransitDialog(transit_token, {
onCancel: () => clearInterval(pollInterval),
onError: (err) => {
clearInterval(pollInterval);
+21 -5
View File
@@ -35,7 +35,7 @@ class TokenExchangeService:
secret_key=settings.ADDONS_JWT_SECRET_KEY,
algorithm=settings.ADDONS_JWT_ALG,
issuer=settings.ADDONS_JWT_ISSUER,
audience=settings.ADDONS_JWT_AUDIENCE,
audience=settings.ADDONS_JWT_AUDIENCE, # todo - precise
expiration_seconds=settings.ADDONS_JWT_EXPIRATION_SECONDS,
token_type=settings.ADDONS_JWT_TOKEN_TYPE,
)
@@ -48,7 +48,7 @@ class TokenExchangeService:
"""Wip."""
return f"{settings.ADDONS_SESSION_TOKEN_PREFIX}_{result_token}"
def init_session(self) -> tuple[str, str]:
def init_session(self) -> tuple[str, str, str]:
"""Create a new pending authentication session and return its ID."""
session_id = secrets.token_urlsafe(settings.ADDONS_SESSION_ID_LENGTH)
@@ -77,10 +77,18 @@ class TokenExchangeService:
timeout=settings.ADDONS_SESSION_TIMEOUT,
)
print('$$ init session_id')
print(session_id)
# Transit token → session_id, very short TTL, one-time use
transit_token = secrets.token_urlsafe(32)
cache.set(
f"addon_transit_{transit_token}",
session_id,
timeout=120
)
return session_id, result_token
print('$$ init transit_token')
print(transit_token)
return session_id, result_token, transit_token
# todo - wip
def get_session(self, session_id: str) -> dict:
@@ -174,3 +182,11 @@ class TokenExchangeService:
def token_to_session(self, result_token):
"""wip."""
return None
def consume_transit_token(self, transit_token: str) -> str | None:
"""Resolve and immediately delete the transit token (one-time use)."""
key = f"addon_transit_{transit_token}"
session_id = cache.get(key)
if session_id:
cache.delete(key) # consumed — cannot be replayed
return session_id
+8 -3
View File
@@ -18,13 +18,18 @@ def render_error(request, message, status=400):
def transit_page(request):
"""Initialize authentication flow for add-on session."""
session_id = request.GET.get("session_id")
transit_token = request.GET.get("transit_token")
if not transit_token:
return render_error(request, _("Transit token is required."), status=400)
session_id = TokenExchangeService().consume_transit_token(transit_token)
if not session_id:
return render_error(request, _("Session ID is required."), status=400)
return render_error(request, _("Invalid or expired transit token."), status=404)
# Validate the session is still pending
data = TokenExchangeService().get_session(session_id)
if not data:
return render_error(request, _("Session not found or expired."), status=404)
+2 -2
View File
@@ -30,9 +30,9 @@ class AuthSessionViewSet(viewsets.ViewSet):
Returns session_id in the body (client forwards it to the 3rd-party view).
Sets result_token as an HttpOnly cookie (the only poll credential).
"""
session_id, result_token = TokenExchangeService().init_session()
session_id, result_token, transit_token = TokenExchangeService().init_session()
response = drf_response.Response(
{"session_id": session_id}, status=drf_status.HTTP_201_CREATED
{"session_id": session_id, "transit_token": transit_token}, status=drf_status.HTTP_201_CREATED
)
response.set_cookie(
key=settings.ADDONS_RESULT_TOKEN_COOKIE_NAME,