Revision 5b65fb47

b/snf-astakos-app/astakos/im/tests/auth.py
31 31
# interpreted as representing official policies, either expressed
32 32
# or implied, of GRNET S.A.
33 33

  
34
import urlparse
35
import urllib
36

  
34 37
from astakos.im.tests.common import *
35 38

  
36 39
ui_url = lambda url: '/' + astakos_settings.BASE_PATH + '/ui/%s' % url
......
1297 1300
        self.assertTrue(user.moderated_at)
1298 1301
        self.assertEqual(user.email_verified, True)
1299 1302
        self.assertTrue(user.activation_sent)
1303

  
1304

  
1305
class TestWebloginRedirect(TestCase):
1306

  
1307
    @with_settings(settings, COOKIE_DOMAIN='.astakos.synnefo.org')
1308
    def test_restricts_domains(self):
1309
        get_local_user('user1@synnefo.org')
1310

  
1311
        # next url construct helpers
1312
        weblogin = lambda nxt: reverse('weblogin') + '?next=%s' % nxt
1313
        weblogin_quoted = lambda nxt: reverse('weblogin') + '?next=%s' % \
1314
            urllib.quote_plus(nxt)
1315

  
1316
        # common cases
1317
        invalid_domain = weblogin("https://www.invaliddomain.synnefo.org")
1318
        invalid_scheme = weblogin("customscheme://localhost")
1319
        invalid_scheme_with_valid_domain = \
1320
                weblogin("http://www.invaliddomain.com")
1321
        valid_scheme = weblogin("pithos://localhost/")
1322
        # to be used in assertRedirects
1323
        valid_scheme_quoted = weblogin_quoted("pithos://localhost/")
1324

  
1325
        # not authenticated, redirects to login which contains next param with
1326
        # additional nested quoted next params
1327
        r = self.client.get(valid_scheme, follow=True)
1328
        login_redirect = reverse('index') + '?next=' + \
1329
            urllib.quote_plus("http://testserver" + valid_scheme_quoted)
1330
        self.assertRedirects(r, login_redirect)
1331

  
1332
        # authenticate client
1333
        self.client.login(username="user1@synnefo.org", password="password")
1334

  
1335
        # valid scheme
1336
        r = self.client.get(valid_scheme, follow=True)
1337
        self.assertEqual(len(r.redirect_chain), 3)
1338
        url = r.redirect_chain[1][0]
1339
        # scheme preserved
1340
        self.assertTrue(url.startswith('pithos://localhost/'))
1341
        # redirect contains token param
1342
        params = urlparse.urlparse(urlparse.urlparse(url).path, 'https').query
1343
        params = urlparse.parse_qs(params)
1344
        self.assertEqual(params['token'][0],
1345
                         AstakosUser.objects.get().auth_token)
1346
        # does not contain uuid
1347
        self.assertFalse('uuid' in params)
1348

  
1349
        # invalid cases
1350
        r = self.client.get(invalid_scheme, follow=True)
1351
        self.assertEqual(r.status_code, 403)
1352

  
1353
        r = self.client.get(invalid_scheme_with_valid_domain, follow=True)
1354
        self.assertEqual(r.status_code, 403)
1355

  
1356
        r = self.client.get(invalid_domain, follow=True)
1357
        self.assertEqual(r.status_code, 403)
b/snf-astakos-app/astakos/im/util.py
112 112
    redirect location of an http redirect response. The method parses the
113 113
    provided url and identifies if it conforms CORS against provided domain
114 114
    AND url scheme matches any of the schemes in `allowed_schemes` parameter.
115
    If verirication succeeds sanitized safe url is returned so you must use
116
    the method's response in the response location header and not the
117
    originally provided url. If verification fails the method returns None.
115
    If verirication succeeds sanitized safe url is returned. Consider using
116
    the method's result in the response location header and not the originally
117
    provided url. If verification fails the method returns None.
118 118

  
119 119
    >>> print restrict_next('/im/feedback', '.okeanos.grnet.gr')
120 120
    /im/feedback
......
162 162
    if not domain and not allowed_schemes:
163 163
        return url
164 164

  
165
    # domain validation
165 166
    if domain:
166 167
        if not parts.netloc:
167 168
            return url
......
170 171
        else:
171 172
            return None
172 173

  
174
    # scheme validation
173 175
    if allowed_schemes:
174 176
        if parts.scheme in allowed_schemes:
175 177
            return url
b/snf-astakos-app/astakos/im/weblogin_urls.py
34 34
from django.conf.urls.defaults import patterns, url
35 35

  
36 36
urlpatterns = (
37
    url(r'^login$', 'astakos.im.views.target.redirect.login'),
37
    url(r'^login$', 'astakos.im.views.target.redirect.login',
38
        name="weblogin"),
38 39
)

Also available in: Unified diff