This commit is contained in:
Markos Gogoulos
2025-12-28 15:35:29 +02:00
parent f85299a600
commit f9a94321ad
2 changed files with 20 additions and 14 deletions

View File

@@ -120,7 +120,7 @@ class DjangoSessionService:
def check_state_is_valid(self, state, nonce):
"""Check if state is valid"""
state_key = f'state-{state}'
print(f"Checking state validity: state={state}", flush=True)
print(f"Checking state validity: state={state}, nonce={nonce}", flush=True)
print(f"Looking for state_key: {state_key}", flush=True)
state_data = self.get_launch_data(state_key)
@@ -130,8 +130,12 @@ class DjangoSessionService:
print("ERROR: State data not found in session!", flush=True)
return False
# State exists, which is sufficient for CSRF protection
# Nonce is validated by PyLTI1p3 through JWT signature verification
# Check if nonce matches (if we stored one)
stored_nonce = state_data.get('nonce')
if stored_nonce and stored_nonce != nonce:
print(f"ERROR: Nonce mismatch! Expected: {stored_nonce}, Got: {nonce}", flush=True)
return False
print("State is valid!", flush=True)
return True

View File

@@ -83,7 +83,6 @@ class OIDCLoginView(View):
client_id = request.GET.get('client_id') or request.POST.get('client_id')
login_hint = request.GET.get('login_hint') or request.POST.get('login_hint')
lti_message_hint = request.GET.get('lti_message_hint') or request.POST.get('lti_message_hint')
lti_deployment_id = request.GET.get('lti_deployment_id') or request.POST.get('lti_deployment_id')
print(f"OIDC params - iss: {iss}, client_id: {client_id}, target: {target_link_uri}", flush=True)
print(f"login_hint: {login_hint}, lti_message_hint: {lti_message_hint}", flush=True)
@@ -130,29 +129,32 @@ class OIDCLoginView(View):
if not redirect_url:
print("PyLTI1p3 redirect failed, building URL manually...", flush=True)
# Manual OIDC redirect construction
# Note: We don't send nonce - Moodle generates it and includes it in the JWT
# Manual OIDC redirect construction with all required OAuth 2.0 parameters
import uuid
from urllib.parse import urlencode
state = str(uuid.uuid4())
nonce = str(uuid.uuid4())
# Store state in session (nonce will come from JWT)
session_service.save_launch_data(f'state-{state}', {'target_link_uri': target_link_uri})
# Store state and nonce in session for validation
session_service.save_launch_data(f'state-{state}', {'target_link_uri': target_link_uri, 'nonce': nonce})
# Build redirect URL - only LTI 1.3 required parameters
# Build redirect URL with all required parameters
params = {
'iss': iss,
'login_hint': login_hint,
'target_link_uri': target_link_uri,
'response_type': 'id_token',
'redirect_uri': target_link_uri,
'state': state,
'client_id': client_id,
'login_hint': login_hint,
'scope': 'openid',
'response_mode': 'form_post',
'prompt': 'none',
'nonce': nonce,
}
# Add optional parameters if present
if lti_message_hint:
params['lti_message_hint'] = lti_message_hint
if lti_deployment_id:
params['lti_deployment_id'] = lti_deployment_id
redirect_url = f"{platform.auth_login_url}?{urlencode(params)}"
print(f"Manually built redirect URL: {redirect_url}", flush=True)