Esempio n. 1
0
def launch():
    tool_conf = ToolConfJsonFile(get_lti_config_path())
    flask_request = FlaskRequest()
    launch_data_storage = get_launch_data_storage()
    message_launch = ExtendedFlaskMessageLaunch(
        flask_request, tool_conf, launch_data_storage=launch_data_storage)
    message_launch_data = message_launch.get_launch_data()
    pprint.pprint(message_launch_data)
    tpl_kwargs = {
        'page_title': PAGE_TITLE,
        'is_deep_link_launch': message_launch.is_deep_link_launch(),
        'launch_data': message_launch.get_launch_data(),
        'launch_id': message_launch.get_launch_id(),
        'curr_user_name': message_launch_data.get('name', '')
    }

    learn_url = message_launch_data[
        'https://purl.imsglobal.org/spec/lti/claim/tool_platform'][
            'url'].rstrip('/')

    params = {
        'redirect_uri': Config.config['app_url'] + '/authcode/',
        'response_type': 'code',
        'client_id': Config.config['learn_rest_key'],
        'scope': '*',
        'state': str(uuid.uuid4())
    }

    encodedParams = urllib.parse.urlencode(params)

    get_authcode_url = learn_url + '/learn/api/public/v1/oauth2/authorizationcode?' + encodedParams

    print("authcode_URL: " + get_authcode_url)

    return (redirect(get_authcode_url))
Esempio n. 2
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. 3
0
def launch(request):
    cache = caches['default']
    launch_unique_id = str(request.GET.get('launch_id', ''))

    # reload page in case if session cookie is unavailable (chrome samesite issue):
    # https://chromestatus.com/feature/5088147346030592
    # to share GET/POST data between requests we save them into cache
    if not request.session.session_key and not launch_unique_id:
        launch_unique_id = str(uuid.uuid4())
        cache.set(
            launch_unique_id, {
                'GET': {k: v
                        for k, v in request.GET.items()},
                'POST': {k: v
                         for k, v in request.POST.items()}
            }, 3600)
        current_url = request.build_absolute_uri()
        if '?' in current_url:
            current_url += '&'
        else:
            current_url += '?'
        current_url = current_url + 'launch_id=' + launch_unique_id
        return HttpResponse(
            '<script type="text/javascript">window.location="%s";</script>' %
            current_url)

    request_like_obj = None
    if request.method == "GET":
        launch_data = cache.get(launch_unique_id)
        if not launch_data:
            raise Exception("Can't restore launch data from cache")
        request_like_obj = DjangoFakeRequest(launch_data['GET'],
                                             launch_data['POST'],
                                             request.COOKIES, request.session,
                                             request.is_secure())

    tool_conf = ToolConfJsonFile(get_lti_config_path())
    message_launch = ExtendedDjangoMessageLaunch(
        request_like_obj if request_like_obj else request, tool_conf)
    message_launch_data = message_launch.get_launch_data()
    pprint.pprint(message_launch_data)

    return render(
        request, 'game.html', {
            'page_title':
            PAGE_TITLE,
            'is_deep_link_launch':
            message_launch.is_deep_link_launch(),
            'launch_data':
            message_launch.get_launch_data(),
            'launch_id':
            message_launch.get_launch_id(),
            'curr_user_name':
            message_launch_data.get('name', ''),
            'curr_diff':
            message_launch_data.get(
                'https://purl.imsglobal.org/spec/lti/claim/custom', {}).get(
                    'difficulty', 'normal')
        })
Esempio n. 4
0
    def __init__(self):
        for setting in dir(app_config):
            setattr(self, setting, getattr(app_config, setting))

        path = Path(__file__).absolute().parent

        setattr(self, "LTI_TOOL_CONFIG",
                ToolConfJsonFile(path / "tool_config.json"))
Esempio n. 5
0
def score(launch_id, earned_score, time_spent):
    tool_conf = ToolConfJsonFile(get_lti_config_path())
    flask_request = FlaskRequest()
    launch_data_storage = get_launch_data_storage()
    message_launch = ExtendedFlaskMessageLaunch.from_cache(
        launch_id,
        flask_request,
        tool_conf,
        launch_data_storage=launch_data_storage)

    resource_link_id = message_launch.get_launch_data() \
        .get('https://purl.imsglobal.org/spec/lti/claim/resource_link', {}).get('id')

    if not message_launch.has_ags():
        raise Forbidden("Don't have grades!")

    sub = message_launch.get_launch_data().get('sub')
    timestamp = datetime.datetime.utcnow().isoformat() + 'Z'
    earned_score = int(earned_score)
    time_spent = int(time_spent)

    grades = message_launch.get_ags()
    sc = Grade()
    sc.set_score_given(earned_score) \
        .set_score_maximum(100) \
        .set_timestamp(timestamp) \
        .set_activity_progress('Completed') \
        .set_grading_progress('FullyGraded') \
        .set_user_id(sub)

    sc_line_item = LineItem()
    sc_line_item.set_tag('score') \
        .set_score_maximum(100) \
        .set_label('Score')
    if resource_link_id:
        sc_line_item.set_resource_id(resource_link_id)

    grades.put_grade(sc, sc_line_item)

    tm = Grade()
    tm.set_score_given(time_spent) \
        .set_score_maximum(999) \
        .set_timestamp(timestamp) \
        .set_activity_progress('Completed') \
        .set_grading_progress('FullyGraded') \
        .set_user_id(sub)

    tm_line_item = LineItem()
    tm_line_item.set_tag('time') \
        .set_score_maximum(999) \
        .set_label('Time Taken')
    if resource_link_id:
        tm_line_item.set_resource_id(resource_link_id)

    result = grades.put_grade(tm, tm_line_item)

    return jsonify({'success': True, 'result': result.get('body')})
Esempio n. 6
0
def launch():
    tool_conf = ToolConfJsonFile(get_lti_config_path())
    flask_request = FlaskRequest()
    launch_data_storage = get_launch_data_storage()
    message_launch = ExtendedFlaskMessageLaunch(
        flask_request, tool_conf, launch_data_storage=launch_data_storage)
    message_launch_data = message_launch.get_launch_data()
    pprint.pprint(message_launch_data)

    tpl_kwargs = {
        'page_title': PAGE_TITLE,
        'is_deep_link_launch': message_launch.is_deep_link_launch(),
        'launch_data': message_launch.get_launch_data(),
        'launch_id': message_launch.get_launch_id(),
        'curr_user_name': message_launch_data.get('name', '')
    }
    """ 
    We could do the launch to the external page here. The following which does the 3LO with REST APIs
    back to the Learn system is not necessary. It's an artifact of project this one was leveraged from.
    We left it here for the most part to demonstrate how one can pass data through the 3LO process
    using the state parameter. The state is an opaque value that doesn't get modified by the 
    developer portal or by Learn. We take the external URL that will be launched to and include it as
    a portion of the state to be pulled out on the other side of 3LO. It's the only way across. 
    Attempts to pass the data by adding an additional parameter to the request for a authroization code
    will fail because those will be dropped. I.E setting your redirect_uri to .../authcode/?launch_url=URL
    does not work.
    https://stackabuse.com/encoding-and-decoding-base64-strings-in-python/
    """

    learn_url = message_launch_data[
        'https://purl.imsglobal.org/spec/lti/claim/tool_platform'][
            'url'].rstrip('/')
    # MUST include a custom parameter like 'external_url=https://www.foodies.com' in the custom params
    external_url = message_launch_data[
        'https://purl.imsglobal.org/spec/lti/claim/custom'][
            'external_url'].rstrip('/')
    state = str(uuid.uuid4()) + f'&launch_url={external_url}'
    message_bytes = state.encode('ascii')
    base64_bytes = base64.b64encode(message_bytes)
    base64_message = base64_bytes.decode('ascii')

    params = {
        'redirect_uri': Config.config['app_url'] + '/authcode/',
        'response_type': 'code',
        'client_id': Config.config['learn_rest_key'],
        'scope': '*',
        'state': base64_message
    }

    encodedParams = urllib.parse.urlencode(params)

    get_authcode_url = learn_url + '/learn/api/public/v1/oauth2/authorizationcode?' + encodedParams

    print("authcode_URL: " + get_authcode_url, flush=True)

    return (redirect(get_authcode_url))
Esempio n. 7
0
def scoreboard(launch_id):
    tool_conf = ToolConfJsonFile(get_lti_config_path())
    flask_request = FlaskRequest()
    launch_data_storage = get_launch_data_storage()
    message_launch = ExtendedFlaskMessageLaunch.from_cache(
        launch_id,
        flask_request,
        tool_conf,
        launch_data_storage=launch_data_storage)

    resource_link_id = message_launch.get_launch_data() \
        .get('https://purl.imsglobal.org/spec/lti/claim/resource_link', {}).get('id')

    if not message_launch.has_nrps():
        raise Forbidden("Don't have names and roles!")

    if not message_launch.has_ags():
        raise Forbidden("Don't have grades!")

    ags = message_launch.get_ags()

    score_line_item = LineItem()
    score_line_item.set_tag('score') \
        .set_score_maximum(100) \
        .set_label('Score')
    if resource_link_id:
        score_line_item.set_resource_id(resource_link_id)

    scores = ags.get_grades(score_line_item)

    time_line_item = LineItem()
    time_line_item.set_tag('time') \
        .set_score_maximum(999) \
        .set_label('Time Taken')
    if resource_link_id:
        time_line_item.set_resource_id(resource_link_id)

    times = ags.get_grades(time_line_item)

    members = message_launch.get_nrps().get_members()
    scoreboard_result = []

    for sc in scores:
        result = {'score': sc['resultScore']}
        for tm in times:
            if tm['userId'] == sc['userId']:
                result['time'] = tm['resultScore']
                break
        for member in members:
            if member['user_id'] == sc['userId']:
                result['name'] = member.get('name', 'Unknown')
                break
        scoreboard_result.append(result)

    return jsonify(scoreboard_result)
Esempio n. 8
0
def launch():
    launch_unique_id = str(request.args.get('launch_id', ''))

    # reload page in case if session cookie is unavailable (chrome samesite issue):
    # https://chromestatus.com/feature/5088147346030592
    # to share GET/POST data between requests we save them into cache
    session_key = request.cookies.get(app.config['SESSION_COOKIE_NAME'], None)
    if not session_key and not launch_unique_id:
        launch_unique_id = str(uuid.uuid4())
        cache.set(launch_unique_id, {
            'GET': request.args.to_dict(),
            'POST': request.form.to_dict()
        }, 3600)
        current_url = request.base_url
        if '?' in current_url:
            current_url += '&'
        else:
            current_url += '?'
        current_url = current_url + 'launch_id=' + launch_unique_id
        return '<script type="text/javascript">window.location="%s";</script>' % current_url

    launch_request = FlaskRequest()
    if request.method == "GET":
        launch_data = cache.get(launch_unique_id)
        if not launch_data:
            raise Exception("Can't restore launch data from cache")
        request_params_dict = {}
        request_params_dict.update(launch_data['GET'])
        request_params_dict.update(launch_data['POST'])
        launch_request = FlaskRequest(request_data=request_params_dict)

    tool_conf = ToolConfJsonFile(get_lti_config_path())
    message_launch = ExtendedFlaskMessageLaunch(launch_request, tool_conf)
    message_launch_data = message_launch.get_launch_data()
    pprint.pprint(message_launch_data)

    tpl_kwargs = {
        'page_title':
        PAGE_TITLE,
        'is_deep_link_launch':
        message_launch.is_deep_link_launch(),
        'launch_data':
        message_launch.get_launch_data(),
        'launch_id':
        message_launch.get_launch_id(),
        'curr_user_name':
        message_launch_data.get('name', ''),
        'curr_diff':
        message_launch_data.get(
            'https://purl.imsglobal.org/spec/lti/claim/custom',
            {}).get('difficulty', 'normal')
    }
    return render_template('game.html', **tpl_kwargs)
Esempio n. 9
0
def launch(request):
    tool_conf = ToolConfJsonFile(get_lti_config_path())
    message_launch = ExtendedDjangoMessageLaunch(request, tool_conf)
    message_launch_data = message_launch.get_launch_data()
    pprint.pprint(message_launch_data)

    return render(request, 'game.html', {
        'page_title': PAGE_TITLE,
        'is_deep_link_launch': message_launch.is_deep_link_launch(),
        'launch_data': message_launch.get_launch_data(),
        'launch_id': message_launch.get_launch_id(),
        'curr_user_name': message_launch_data.get('name', ''),
        'curr_diff': message_launch_data.get('https://purl.imsglobal.org/spec/lti/claim/custom', {})
                  .get('difficulty', 'normal')})
Esempio n. 10
0
def login():
    tool_conf = ToolConfJsonFile(get_lti_config_path())
    launch_data_storage = get_launch_data_storage()

    flask_request = FlaskRequest()
    target_link_uri = flask_request.get_param('target_link_uri')
    
    if not target_link_uri:
        raise Exception('Missing "target_link_uri" param')

    oidc_login = FlaskOIDCLogin(flask_request, tool_conf, launch_data_storage=launch_data_storage)
    return oidc_login\
        .enable_check_cookies()\
        .redirect(target_link_uri)
Esempio n. 11
0
def launch():
    tool_conf = ToolConfJsonFile(get_lti_config_path())
    flask_request = FlaskRequest()
    launch_data_storage = get_launch_data_storage()
    message_launch = ExtendedFlaskMessageLaunch(
        flask_request, tool_conf, launch_data_storage=launch_data_storage)
    message_launch_data = message_launch.get_launch_data()
    pprint.pprint(message_launch_data)
    jsonData = dict(message_launch_data)
    app.logger.info(jsonData)
    #return redirect('/predict')
    return render_template(
        'camera.html',
        jsonData=jsonData[
            'https://purl.imsglobal.org/spec/lti/claim/tool_platform']['name'])
Esempio n. 12
0
def configure(request, launch_id, difficulty):
    tool_conf = ToolConfJsonFile(get_lti_config_path())
    message_launch = ExtendedDjangoMessageLaunch.from_cache(launch_id, request, tool_conf)

    if not message_launch.is_deep_link_launch():
        return HttpResponseForbidden('Must be a deep link!')

    launch_url = request.build_absolute_uri(reverse('game-launch'))

    resource = DeepLinkResource()
    resource.set_url(launch_url)\
        .set_custom_params({'difficulty': difficulty})\
        .set_title('Breakout ' + difficulty + ' mode!')

    html = message_launch.get_deep_link().output_response_form([resource])
    return HttpResponse(html)
Esempio n. 13
0
def score(request, launch_id, earned_score, time_spent):
    tool_conf = ToolConfJsonFile(get_lti_config_path())
    message_launch = ExtendedDjangoMessageLaunch.from_cache(
        launch_id, request, tool_conf)

    if not message_launch.has_ags():
        return HttpResponseForbidden("Don't have grades!")

    sub = message_launch.get_launch_data().get('sub')
    timestamp = datetime.datetime.utcnow().isoformat()
    earned_score = int(earned_score)
    time_spent = int(time_spent)

    grades = message_launch.get_ags()
    sc = Grade()
    sc.set_score_given(earned_score)\
        .set_score_maximum(100)\
        .set_timestamp(timestamp)\
        .set_activity_progress('Completed')\
        .set_grading_progress('FullyGraded')\
        .set_user_id(sub)

    sc_line_item = LineItem()
    sc_line_item.set_tag('score')\
        .set_score_maximum(100)\
        .set_label('Score')

    grades.put_grade(sc, sc_line_item)

    tm = Grade()
    tm.set_score_given(time_spent)\
        .set_score_maximum(999)\
        .set_timestamp(timestamp)\
        .set_activity_progress('Completed')\
        .set_grading_progress('FullyGraded')\
        .set_user_id(sub)

    tm_line_item = LineItem()
    tm_line_item.set_tag('time')\
        .set_score_maximum(999)\
        .set_label('Time Taken')

    result = grades.put_grade(tm, tm_line_item)

    return JsonResponse({'success': True, 'result': result.get('body')})
Esempio n. 14
0
def launch():
    tool_conf = ToolConfJsonFile(get_lti_config_path())
    flask_request = FlaskRequest()
    launch_data_storage = get_launch_data_storage()
    message_launch = ExtendedFlaskMessageLaunch(
        flask_request, tool_conf, launch_data_storage=launch_data_storage)
    message_launch_data = message_launch.get_launch_data()
    pprint.pprint(message_launch_data)
    tpl_kwargs = {
        'page_title': PAGE_TITLE,
        'is_deep_link_launch': message_launch.is_deep_link_launch(),
        'launch_data': message_launch.get_launch_data(),
        'launch_id': message_launch.get_launch_id(),
        'curr_user_name': message_launch_data.get('name', '')
    }

    learn_url = message_launch_data[
        'https://purl.imsglobal.org/spec/lti/claim/tool_platform'][
            'url'].rstrip('/')

    # Rererence: https://docs.blackboard.com/blog/2021/05/10/use-one-time-session-tokens-instead-of-cookies-for-UEF-authentication.html
    # Get the value of the one time session token from the LTI claim
    one_time_session_token = message_launch_data[
        'https://blackboard.com/lti/claim/one_time_session_token']

    # If there is no comma in the value, we've hit the bug. Add it and the user's UUID
    if "," not in one_time_session_token:
        one_time_session_token += "," + message_launch_data['sub']

    params = {
        'redirect_uri': Config.config['app_url'] + '/authcode/',
        'response_type': 'code',
        'client_id': Config.config['learn_rest_key'],
        'scope': '*',
        'state': str(uuid.uuid4()),
        'one_time_session_token': one_time_session_token
    }

    encodedParams = urllib.parse.urlencode(params)

    get_authcode_url = learn_url + '/learn/api/public/v1/oauth2/authorizationcode?' + encodedParams

    print("authcode_URL: " + get_authcode_url, flush=True)

    return (redirect(get_authcode_url))
Esempio n. 15
0
def configure(launch_id, difficulty):
    tool_conf = ToolConfJsonFile(get_lti_config_path())
    flask_request = FlaskRequest()
    message_launch = ExtendedFlaskMessageLaunch.from_cache(
        launch_id, flask_request, tool_conf)

    if not message_launch.is_deep_link_launch():
        raise Forbidden('Must be a deep link!')

    launch_url = url_for('launch', _external=True)

    resource = DeepLinkResource()
    resource.set_url(launch_url) \
        .set_custom_params({'difficulty': difficulty}) \
        .set_title('Breakout ' + difficulty + ' mode!')

    html = message_launch.get_deep_link().output_response_form([resource])
    return html
Esempio n. 16
0
def deepLink():
    tool_conf = ToolConfJsonFile(get_lti_config_path())
    flask_request = FlaskRequest()
    launch_data_storage = get_launch_data_storage()
    message_launch = ExtendedFlaskMessageLaunch(
        flask_request, tool_conf, launch_data_storage=launch_data_storage)
    message_launch_data = message_launch.get_launch_data()

    resource = DeepLinkResource()
    resource.set_url('https://inviguluscanvas.online/launch/') \
        .set_custom_params({'text': 'Invigulus'}) \
        .set_title('LTI Launch Invigulus')

    html = message_launch.get_deep_link().output_response_form([resource])
    app.logger.info(html)
    return html

    pprint.pprint(message_launch_data)
Esempio n. 17
0
def scoreboard(request, launch_id):
    tool_conf = ToolConfJsonFile(get_lti_config_path())
    message_launch = ExtendedDjangoMessageLaunch.from_cache(
        launch_id, request, tool_conf)

    if not message_launch.has_nrps():
        return HttpResponseForbidden("Don't have names and roles!")

    if not message_launch.has_ags():
        return HttpResponseForbidden("Don't have grades!")

    ags = message_launch.get_ags()

    score_line_item = LineItem()
    score_line_item.set_tag('score') \
        .set_score_maximum(100) \
        .set_label('Score')
    scores = ags.get_grades(score_line_item)

    time_line_item = LineItem()
    time_line_item.set_tag('time') \
        .set_score_maximum(999) \
        .set_label('Time Taken')
    times = ags.get_grades(time_line_item)

    members = message_launch.get_nrps().get_members()
    scoreboard_result = []

    for sc in scores:
        result = {'score': sc['resultScore']}
        for tm in times:
            if tm['userId'] == sc['userId']:
                result['time'] = tm['resultScore']
                break
        for member in members:
            if member['user_id'] == sc['userId']:
                result['name'] = member.get('name', 'Unknown')
                break
        scoreboard_result.append(result)

    return JsonResponse(scoreboard_result, safe=False)
Esempio n. 18
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. 19
0
def launch():
    tool_conf = ToolConfJsonFile(get_lti_config_path())
    flask_request = FlaskRequest()
    launch_data_storage = get_launch_data_storage()
    message_launch = ExtendedFlaskMessageLaunch(
        flask_request, tool_conf, launch_data_storage=launch_data_storage)
    message_launch_data = message_launch.get_launch_data()
    pprint.pprint(message_launch_data)

    difficulty = message_launch_data.get('https://purl.imsglobal.org/spec/lti/claim/custom', {}) \
        .get('difficulty', None)
    if not difficulty:
        difficulty = request.args.get('difficulty', 'normal')

    tpl_kwargs = {
        'page_title': PAGE_TITLE,
        'is_deep_link_launch': message_launch.is_deep_link_launch(),
        'launch_data': message_launch.get_launch_data(),
        'launch_id': message_launch.get_launch_id(),
        'curr_user_name': message_launch_data.get('name', ''),
        'curr_diff': difficulty
    }
    return render_template('game.html', **tpl_kwargs)
Esempio n. 20
0
def login():
    cookies_allowed = str(request.args.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.args.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_params_dict = {}
        request_params_dict.update(login_data['GET'])
        request_params_dict.update(login_data['POST'])

        oidc_request = FlaskRequest(request_data=request_params_dict)
        oidc_login = FlaskOIDCLogin(oidc_request, tool_conf)
        target_link_uri = request_params_dict.get('target_link_uri')
        return oidc_login.redirect(target_link_uri)
    else:
        login_unique_id = str(uuid.uuid4())
        cache.set(login_unique_id, {
            'GET': request.args.to_dict(),
            'POST': request.form.to_dict()
        }, 3600)
        tpl_kwargs = {
            'login_unique_id': login_unique_id,
            'same_site': app.config['SESSION_COOKIE_SAMESITE'],
            'site_protocol': 'https' if request.is_secure else 'http',
            'page_title': PAGE_TITLE
        }
        return render_template('check_cookie.html', **tpl_kwargs)
Esempio n. 21
0
def get_jwks():
    tool_conf = ToolConfJsonFile(get_lti_config_path())
    return jsonify({'keys': tool_conf.get_jwks()})
Esempio n. 22
0
def get_tool_conf():
    tool_conf = ToolConfJsonFile(get_lti_config_path())
    return tool_conf
Esempio n. 23
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. 24
0
def launch():
    launch_unique_id = str(request.args.get('launch_id', ''))
    
    print("launch_unique_id: " + launch_unique_id)
    
    # reload page in case if session cookie is unavailable (chrome samesite issue):
    # https://chromestatus.com/feature/5088147346030592
    # to share GET/POST data between requests we save them into cache
    session_key = request.cookies.get(app.config['SESSION_COOKIE_NAME'], None)
    
    if not session_key:
        print("session_key: None")
    else:
        print("session_key: " + session_key)

    if not session_key and not launch_unique_id:
        launch_unique_id = str(uuid.uuid4())
        cache.set(launch_unique_id, {
            'GET': request.args.to_dict(),
            'POST': request.form.to_dict()
        }, 3600)
        current_url = request.base_url

        parsed_url = urlparse(current_url)
        parsed_url = parsed_url._replace(scheme='https')

        current_url = parsed_url.geturl() 

        if '?' in current_url:
            current_url += '&'
        else:
            current_url += '?'
        current_url = current_url + 'launch_id=' + launch_unique_id

        return '<script type="text/javascript">window.location="%s";</script>' % current_url
        
    launch_request = FlaskRequest()
    if request.method == "GET":
        launch_data = cache.get(launch_unique_id)
        print("launch_data: " + str(launch_data))
        if not launch_data:
            raise Exception("Can't restore launch data from cache")
        request_params_dict = {}
        request_params_dict.update(launch_data['GET'])
        request_params_dict.update(launch_data['POST'])
        print("request_params_dict: " + str(request_params_dict))
        launch_request = FlaskRequest(request_data=request_params_dict)

    print("launch_request: " + str(launch_request))
    tool_conf = ToolConfJsonFile(get_lti_config_path())
    print("tool_conf: " + str(tool_conf))
    message_launch = ExtendedFlaskMessageLaunch(launch_request, tool_conf)
    print("message_launch: " + str(message_launch))
    message_launch_data = message_launch.get_launch_data()
    pprint.pprint(message_launch_data)

    learn_url = message_launch_data['https://purl.imsglobal.org/spec/lti/claim/tool_platform']['url'].rstrip('/')

    tpl_kwargs = {
        'page_title': PAGE_TITLE,
        'is_deep_link_launch': message_launch.is_deep_link_launch(),
        'launch_data': message_launch.get_launch_data(),
        'launch_id': message_launch.get_launch_id(),
        'family_name': message_launch_data.get('family_name', ''),
        'given_name': message_launch_data.get('given_name', ''),
        'user_email': message_launch_data.get('email', ''),
        'user_uuid': message_launch_data.get('sub', ''),
        'learn_url': learn_url

    }

    print("tpl_kwargs: " + str(tpl_kwargs))

    params = {
        'redirect_uri' : 'https://ask-an-expert.herokuapp.com/authcode/',
        'response_type' : 'code',
        'client_id' : Config.config['learn_rest_key'],
        'scope' : '*',
        'state' : str(uuid.uuid4())
    }

    encodedParams = urllib.parse.urlencode(params)

    get_authcode_url = learn_url + '/learn/api/public/v1/oauth2/authorizationcode?' + encodedParams

    return(redirect(get_authcode_url))