Esempio n. 1
0
def login(request):
    cache = caches['default']
    cookies_allowed = str(request.GET.get('cookies_allowed', 0))
    if cookies_allowed == '1':
        login_unique_id = str(request.GET.get('login_unique_id', ''))
        if not login_unique_id:
            raise Exception('Missing "login_unique_id" param')

        login_data = cache.get(login_unique_id)
        if not login_data:
            raise Exception("Can't restore login data from cache")

        tool_conf = ToolConfJsonFile(get_lti_config_path())
        request_like_obj = DjangoFakeRequest(
            login_data['GET'], login_data['POST'],
            login_data['COOKIES'], request.session, request.is_secure())
        oidc_login = DjangoOIDCLogin(request_like_obj, tool_conf)
        target_link_uri = get_launch_url(request_like_obj)
        return oidc_login.redirect(target_link_uri)
    else:
        login_unique_id = str(uuid.uuid4())
        cache.set(login_unique_id, {
            'GET': {k: v for k, v in request.GET.items()},
            'POST': {k: v for k, v in request.POST.items()},
            'COOKIES': {k: v for k, v in request.COOKIES.items()}
        }, 3600)
        return render(request, 'check_cookie.html', {
            'login_unique_id': login_unique_id,
            'same_site': getattr(settings, 'SESSION_COOKIE_SAMESITE'),
            'page_title': PAGE_TITLE
        })
Esempio n. 2
0
 def post(self, request):
     """Initialize 3rd-party login requests to redirect."""
     oidc_login = DjangoOIDCLogin(self.request,
                                  self.lti_tool_config,
                                  launch_data_storage=self.lti_tool_storage)
     launch_url = (self.request.POST.get(self.LAUNCH_URI_PARAMETER)
                   or self.request.GET.get(self.LAUNCH_URI_PARAMETER))
     try:
         return oidc_login.redirect(launch_url)
     except OIDCException as exc:
         # Relying on downstream error messages, attempt to sanitize it up
         # for customer facing errors.
         log.error('LTI OIDC login failed: %s', exc)
         return HttpResponseBadRequest('Invalid LTI login request.')
Esempio n. 3
0
    def _make_oidc_login(self, uuid_val=None, tool_conf_cls=None):
        tool_conf = get_test_tool_conf(tool_conf_cls)
        request = None
        login_data = {}
        if not uuid_val:
            uuid_val = 'test-uuid-1234'

        if self.get_login_data:
            request = FakeRequest(get=self.get_login_data)
            login_data = self.get_login_data.copy()
        elif self.post_login_data:
            request = FakeRequest(post=self.post_login_data)
            login_data = self.post_login_data.copy()

        with patch('django.shortcuts.redirect') as mock_redirect:
            from pylti1p3.contrib.django import DjangoOIDCLogin
            with patch.object(DjangoOIDCLogin, "_get_uuid", autospec=True) as get_uuid:
                get_uuid.side_effect = lambda x: uuid_val  # pylint: disable=unnecessary-lambda
                oidc_login = DjangoOIDCLogin(request, tool_conf)
                mock_redirect.side_effect = lambda x: FakeResponse(x)  # pylint: disable=unnecessary-lambda
                launch_url = 'http://lti.django.test/launch/'
                response = oidc_login.redirect(launch_url)

                # check cookie data
                self.assertEqual(len(response.cookies), 1)
                self.assertTrue(('lti1p3-state-' + uuid_val) in response.cookies)
                self.assertEqual(response.cookies['lti1p3-state-' + uuid_val]['value'], 'state-' + uuid_val)

                # check session data
                self.assertEqual(len(request.session), 1)
                self.assertEqual(request.session['lti1p3-nonce-' + uuid_val], True)

                # check redirect_url
                redirect_url = response.data
                self.assertTrue(redirect_url.startswith(TOOL_CONFIG[login_data['iss']]['auth_login_url']))
                url_params = redirect_url.split('?')[1].split('&')
                self.assertTrue(('nonce=' + uuid_val) in url_params)
                self.assertTrue(('state=state-' + uuid_val) in url_params)
                self.assertTrue(('state=state-' + uuid_val) in url_params)
                self.assertTrue('prompt=none' in url_params)
                self.assertTrue('response_type=id_token' in url_params)
                self.assertTrue(('client_id=' + TOOL_CONFIG[login_data['iss']]['client_id']) in url_params)
                self.assertTrue(('login_hint=' + login_data['login_hint']) in url_params)
                self.assertTrue(('lti_message_hint=' + login_data['lti_message_hint']) in url_params)
                self.assertTrue('scope=openid' in url_params)
                self.assertTrue('response_mode=form_post' in url_params)
                self.assertTrue(('redirect_uri=' + quote(launch_url, '')) in url_params)

        return tool_conf, request, response
Esempio n. 4
0
def login(request):
    cache = caches['default']
    cookies_allowed = str(request.GET.get('cookies_allowed', ''))

    # check cookies and ask to open page in the new window in case if cookies are not allowed
    # https://chromestatus.com/feature/5088147346030592
    # to share GET/POST data between requests we save them into cache
    if cookies_allowed:
        login_unique_id = str(request.GET.get('login_unique_id', ''))
        if not login_unique_id:
            raise Exception('Missing "login_unique_id" param')

        login_data = cache.get(login_unique_id)
        if not login_data:
            raise Exception("Can't restore login data from cache")

        tool_conf = ToolConfJsonFile(get_lti_config_path())
        request_like_obj = DjangoFakeRequest(login_data['GET'],
                                             login_data['POST'],
                                             request.COOKIES, request.session,
                                             request.is_secure())
        oidc_login = DjangoOIDCLogin(request_like_obj, tool_conf)
        target_link_uri = get_launch_url(request_like_obj)
        return oidc_login.redirect(target_link_uri)
    else:
        login_unique_id = str(uuid.uuid4())
        cache.set(
            login_unique_id, {
                'GET': {k: v
                        for k, v in request.GET.items()},
                'POST': {k: v
                         for k, v in request.POST.items()}
            }, 3600)
        return render(
            request, 'check_cookie.html', {
                'login_unique_id': login_unique_id,
                'same_site': getattr(settings, 'SESSION_COOKIE_SAMESITE'),
                'site_protocol': 'https' if request.is_secure() else 'http',
                'page_title': PAGE_TITLE
            })
Esempio n. 5
0
def login(request):
    tool_conf = ToolConfJsonFile(get_lti_config_path())
    oidc_login = DjangoOIDCLogin(request, tool_conf)
    target_link_uri = get_launch_url(request)
    return oidc_login.redirect(target_link_uri)
Esempio n. 6
0
    def _make_oidc_login(self,
                         uuid_val=None,
                         tool_conf_cls=None,
                         secure=False,
                         tool_conf_extended=False,
                         enable_check_cookies=False,
                         cache=False):
        # pylint: disable=too-many-statements
        tool_conf = get_test_tool_conf(tool_conf_cls, tool_conf_extended)
        request = None
        login_data = {}
        if not uuid_val:
            uuid_val = 'test-uuid-1234'

        if self.get_login_data:
            request = FakeRequest(get=self.get_login_data, secure=secure)
            login_data = self.get_login_data.copy()
        elif self.post_login_data:
            request = FakeRequest(post=self.post_login_data, secure=secure)
            login_data = self.post_login_data.copy()

        with patch('django.shortcuts.redirect') as mock_redirect:
            from pylti1p3.contrib.django import DjangoOIDCLogin
            with patch.object(DjangoOIDCLogin, "_get_uuid", autospec=True) as get_uuid,\
                    patch.object(DjangoOIDCLogin, "_generate_nonce", autospec=True) as generate_nonce,\
                    patch.object(DjangoOIDCLogin, 'get_response', autospec=True) as get_response:
                get_uuid.side_effect = lambda x: uuid_val  # pylint: disable=unnecessary-lambda
                generate_nonce.side_effect = lambda x: uuid_val  # pylint: disable=unnecessary-lambda
                get_response.side_effect = lambda y, html: html
                oidc_login = DjangoOIDCLogin(request, tool_conf)

                if cache:
                    oidc_login.set_launch_data_storage(cache)

                mock_redirect.side_effect = lambda x: FakeResponse(x)  # pylint: disable=unnecessary-lambda
                launch_url = 'http://lti.django.test/launch/'

                if enable_check_cookies:
                    response_html = oidc_login.enable_check_cookies().redirect(
                        launch_url)
                    self.assertTrue(
                        '<script type="text/javascript">' in response_html)
                    self.assertTrue('<body>' in response_html)
                    self.assertTrue(
                        'document.addEventListener("DOMContentLoaded", checkCookiesAllowed);'
                        in response_html)

                    login_data['lti1p3_new_window'] = '1'
                    request = FakeRequest(get=login_data, secure=secure)

                    oidc_login = DjangoOIDCLogin(request, tool_conf)
                    oidc_login.enable_check_cookies()

                response = oidc_login.redirect(launch_url)

                # check cookie data
                self.assertEqual(len(response.cookies), 1)
                self.assertTrue(('lti1p3-state-' +
                                 uuid_val) in response.cookies)
                self.assertEqual(
                    response.cookies['lti1p3-state-' + uuid_val]['value'],
                    'state-' + uuid_val)

                # check session data
                if cache:
                    # pylint: disable=protected-access
                    self.assertEqual(
                        len(oidc_login._session_service.data_storage._cache.
                            _data), 1)
                else:
                    self.assertEqual(len(request.session), 1)
                    self.assertEqual(
                        request.session['lti1p3-nonce-' + uuid_val], True)

                # check redirect_url
                redirect_url = response.data
                self.assertTrue(
                    redirect_url.startswith(
                        TOOL_CONFIG[login_data['iss']]['auth_login_url']))
                url_params = redirect_url.split('?')[1].split('&')
                self.assertTrue(('nonce=' + uuid_val) in url_params)
                self.assertTrue(('state=state-' + uuid_val) in url_params)
                self.assertTrue(('state=state-' + uuid_val) in url_params)
                self.assertTrue('prompt=none' in url_params)
                self.assertTrue('response_type=id_token' in url_params)
                self.assertTrue((
                    'client_id=' +
                    TOOL_CONFIG[login_data['iss']]['client_id']) in url_params)
                self.assertTrue(('login_hint=' +
                                 login_data['login_hint']) in url_params)
                self.assertTrue(('lti_message_hint=' +
                                 login_data['lti_message_hint']) in url_params)
                self.assertTrue('scope=openid' in url_params)
                self.assertTrue('response_mode=form_post' in url_params)
                self.assertTrue(('redirect_uri=' +
                                 quote(launch_url, '')) in url_params)
                self.assertTrue(len(response.cookies), 1)
                cookie_key = list(response.cookies)[0]
                cookie_dict = response.cookies[cookie_key]
                if secure:
                    self.assertTrue(cookie_dict['secure'])
                    self.assertEqual(cookie_dict['samesite'], 'None')
                else:
                    self.assertFalse(cookie_dict['secure'])
                    self.assertTrue('samesite' not in cookie_dict)

        return tool_conf, request, response