Skip to main content

3 posts tagged with "uef"

View All Tags

· 5 min read

In testing with the Google Canary Chrome Browser, one of our clients discovered an issue that was blocking users from logging in to their Learn instance. After much troubleshooting, we discovered a multi-layer issue that brings us to, you guessed it, cookies.

This affects clients in SaaS with Ultra Base Navigation enabled using Ultra integrations that rely on UEF

Here is a brief description of the contributing factors:

First, the client had built a custom Ultra login page. The page included code designed to ensure that Learn login pages would never render inside of an iframe within Learn. It looks like this:

if ( top != self )
    top.location.replace( self.location.href );

In and of itself there's nothing wrong with it. We, at Anthology, have removed it from the default Ultra login page, but many clients use it in Original login pages, and so it's moved with them into Ultra.

If you are unsure whether you have a custom login page, visit for more information.

Secondly, when a user logged in, Ultra Extensions automatically fired off an LTI launch to UEF-enabled tools. The way UEF works is: after the LTI launch is validated, the tool redirects to the Learn REST endpoint to initiate a UserAuth flow. In our documentation, we call this a Three-Legged OAuth or 3LO. In most cases, it's a process that relies on a session cookie to hold everything together. This impending release of Chrome (and other browsers) will block this cookie because everything is happening across domains and involves the use of iframes.

So what happens is that, even though the integration is configured in Learn to not force the end-user to authorize the integration, the lack of the session cookie means that Learn has no idea that this user is logged in, so it pops open the login page.

Remember that code snippet above in the custom login page? Well, that takes over the entire browser page with the Learn login. And when the user logs in again, it renders the JavaScript meant for the UEF iframe into the page. In other words, it overtakes your Learn browser session. There is no way to actually get past that screen.

Related, this same issue affects Safari users when cross-site tracking is disabled.

So what can you do?‚Äč

Well, that depends upon who is reading this blog. If you are an administrator trying to get your users back in Learn, the most immediate fix is to remove that snippet from your login page. It won't fix your broken UEF integration, but it will at least let your users log in and interact with Learn.

If you are a developer that has built a UEF integration, we actually implemented a fix for this in April: a way to bypass the need for a session cookie in this process. In the LTI launch, we now provide what is called a one-time session cookie. This is present in both LTI 1.1 and 1.3 launches.

If you are using LTI 1.3, there's a small bug in this. I will share a workaround that will both get around this bug, but not fail when the bug is fixed.

This one-time session cookie is added to the claims in the LTI 1.3 JWT and the form POST parameters in LTI 1.1. You can grab that value from the LTI launch, return it as a parameter in your 3LO authorization code request, and your problem will be solved.


In LTI 1.3, you will see the value in the claim. This token is made up of a specially generated token value. It should also be followed by a comma and the user's UUID. The bug is that the comma is missing. Luckily, the user's UUID is the sub token in the same set of LTI claims. We intend to fix this, but to ensure your code works both now and after the fix, you can simply look for the comma. If it's not there, append it and the sub and you will be off and running. Here's a Python 3 code snippet to illustrate how this might look. We will be updating our UEF sample code, but at the time of this writing, we have not done so.

    # Get the value of the one time session token from the LTI claim
    one_time_session_token  = message_launch_data['']

    # 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']

    # Add the one_time_session_token to the query parameters to send to the Authorization Code endpoint
    params = {
        'redirect_uri' : Config.config['app_url'] + '/authcode/',
        'response_type' : 'code',
        'client_id' : Config.config['learn_rest_key'],
        'one_time_session_token' : one_time_session_token,
        'scope' : '*',
        'state' : str(uuid.uuid4())

    # Encode the parameters
    encoded_params = urllib.parse.urlencode(params)

    # Redirect the successful LTI validation to the Authorization Code endpoint
    return(redirect(learn_url + '/learn/api/public/v1/oauth2/authorizationCode?' + encoded_params))


By now, I hope you are using LTI 1.3, but I know many are not. As a result, we also added a one-time session token to LTI 1.1 launches. This will come in the form POST parameter ext_one_time_session_token. Just like in the 1.3 example, your application should take this value from the LTI launch, append it to the authorization code request endpoint as one_time_session_token=that_token and redirect them to the authorization code endpoint.


We have validated this fix with one of the partners that was affected. If you are a developer, please fix the issue immediately! If you are an administrator of a Learn SaaS instance using Ultra, and you have UEF integrations, make sure you do not have that JavaScript snippet on your login page. And if you do, please remove it. Then let your UEF integration partners and developers know that this fix must be made as soon as possible.

Regardless of whether you are an administrator or a developer, please feel free to reach out to us at with any questions.

Happy coding!

· 2 min read

Today we launched two new sections of developer documentation - Ally as a Service (AaaS) and the [Learn Ultra Extension Framework](/rest-apis/learn (UEF). These new APIs give you access to integration points and functionality that allows you to bring the power of Blackboard into your applications, and ultimately, your user's experience.

Ally as a Service is a standalone, separately licensed API to apply specific components of Ally's approach to content within your application. In its initial form, you are able to upload files, process them through Ally's accessibility checklist, and retrieve data that tells you what can be improved. This is only the tip of the iceberg, so make sure you continue to monitor this amazing capability for enhancements moving forward. For more information, including a conversation about pricing, reach out to your Account Executive.

The Ultra Extension Framework Premium APIs allow an integration to subscribe to events happening real-time in the Ultra UI, and respond to those events by interacting directly with the UI to do things like open panels, display modals, show messages and notifications, and augment the help system in Learn. Partners will need to be at a bronze level or higher to access these Premium APIs. See the partnership team for more information. If you are not a partner, check out how to become a partner. Licensed clients need only request access. Access is granted to your group in the developer portal, much like rate limits. Just open a case on Behind the Blackboard to get started!

As always, let us know if you have any questions!

Happy Coding!