55
66from mock import patch
77
8+ from django .core .exceptions import SuspiciousOperation
89from django .contrib .auth import get_user_model
910from django .core .urlresolvers import reverse
1011from django .test import RequestFactory , TestCase , override_settings
@@ -32,6 +33,9 @@ def test_get_auth_success(self):
3233 }
3334 url = reverse ('oidc_authentication_callback' )
3435 request = self .factory .get (url , get_data )
36+ request .session = {
37+ 'oidc_state' : 'example_state'
38+ }
3539 callback_view = views .OIDCAuthenticationCallbackView .as_view ()
3640
3741 with patch ('mozilla_django_oidc.views.auth.authenticate' ) as mock_auth :
@@ -55,6 +59,9 @@ def test_get_auth_failure_nonexisting_user(self):
5559
5660 url = reverse ('oidc_authentication_callback' )
5761 request = self .factory .get (url , get_data )
62+ request .session = {
63+ 'oidc_state' : 'example_state'
64+ }
5865 callback_view = views .OIDCAuthenticationCallbackView .as_view ()
5966
6067 with patch ('mozilla_django_oidc.views.auth.authenticate' ) as mock_auth :
@@ -80,6 +87,9 @@ def test_get_auth_failure_inactive_user(self):
8087
8188 url = reverse ('oidc_authentication_callback' )
8289 request = self .factory .get (url , get_data )
90+ request .session = {
91+ 'oidc_state' : 'example_state'
92+ }
8393 callback_view = views .OIDCAuthenticationCallbackView .as_view ()
8494
8595 with patch ('mozilla_django_oidc.views.auth.authenticate' ) as mock_auth :
@@ -105,6 +115,54 @@ def test_get_auth_dirty_data(self):
105115 self .assertEqual (response .status_code , 302 )
106116 self .assertEqual (response .url , '/failure' )
107117
118+ @override_settings (LOGIN_REDIRECT_URL_FAILURE = '/failure' )
119+ def test_get_auth_failure_missing_session_state (self ):
120+ """Test authentication failure attempt for an inactive user."""
121+ user = User .objects .create_user ('example_username' )
122+ user .is_active = False
123+ user .save ()
124+
125+ get_data = {
126+ 'code' : 'example_code' ,
127+ 'state' : 'example_state'
128+ }
129+
130+ url = reverse ('oidc_authentication_callback' )
131+ request = self .factory .get (url , get_data )
132+ request .session = {
133+ }
134+ callback_view = views .OIDCAuthenticationCallbackView .as_view ()
135+
136+ response = callback_view (request )
137+
138+ self .assertEqual (response .status_code , 302 )
139+ self .assertEqual (response .url , '/failure' )
140+
141+ @override_settings (LOGIN_REDIRECT_URL_FAILURE = '/failure' )
142+ def test_get_auth_failure_tampered_session_state (self ):
143+ """Test authentication failure attempt for an inactive user."""
144+ user = User .objects .create_user ('example_username' )
145+ user .is_active = False
146+ user .save ()
147+
148+ get_data = {
149+ 'code' : 'example_code' ,
150+ 'state' : 'example_state'
151+ }
152+
153+ url = reverse ('oidc_authentication_callback' )
154+ request = self .factory .get (url , get_data )
155+ request .session = {
156+ 'oidc_state' : 'tampered_state'
157+ }
158+ callback_view = views .OIDCAuthenticationCallbackView .as_view ()
159+
160+ with self .assertRaises (SuspiciousOperation ) as context :
161+ callback_view (request )
162+
163+ expected_error_message = 'Session `oidc_state` does not match the OIDC callback state'
164+ self .assertEqual (context .exception .args , (expected_error_message ,))
165+
108166
109167class OIDCAuthorizationRequestViewTestCase (TestCase ):
110168 def setUp (self ):
@@ -119,6 +177,7 @@ def test_get(self, mock_random_string):
119177 mock_random_string .return_value = 'examplestring'
120178 url = reverse ('oidc_authentication_init' )
121179 request = self .factory .get (url )
180+ request .session = dict ()
122181 login_view = views .OIDCAuthenticationRequestView .as_view ()
123182 response = login_view (request )
124183 self .assertEqual (response .status_code , 302 )
0 commit comments