diff --git a/lti/adapters.py b/lti/adapters.py index d12f96b8..67f2c5da 100644 --- a/lti/adapters.py +++ b/lti/adapters.py @@ -118,9 +118,9 @@ class DjangoSessionService: return session_key in self.request.session def check_state_is_valid(self, state, nonce): - """Check if state is valid""" + """Check if state is valid - state is for CSRF protection, nonce is validated separately by JWT""" state_key = f'state-{state}' - print(f"Checking state validity: state={state}, nonce={nonce}", flush=True) + print(f"Checking state validity: state={state}", flush=True) print(f"Looking for state_key: {state_key}", flush=True) state_data = self.get_launch_data(state_key) @@ -130,12 +130,8 @@ class DjangoSessionService: print("ERROR: State data not found in session!", flush=True) return False - # 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 - + # State exists - that's sufficient for CSRF protection + # Nonce validation is handled by PyLTI1p3 through JWT signature and claims validation print("State is valid!", flush=True) return True