Embedding Bluescape

Developer information on embedding existing workspaces and scratch workspaces along with autoLogin information and links to additional developer resources.

Introduction

Bluescape is an effective collaboration tool that is great for embedding the essence of what you are collaborating on, whether that’s images, documents, a simple arrangement of notecards, or many other possibilities. When trying to build an experience on top of Bluescape, you might need to have that visual collaboration space embedded inside your application, allowing you to benefit from the full web client and access to all the content that Bluescape already embeds. Enter the Bluescape Embedding API, a simple interface with enormous potential.

Just use an iframe with src="https://client.{instance}/embed/{workspace}", where instance is your instance domain (for the public self-serve instance, this is apps.us.bluescape.com), and where workspace is the id of the workspace you are embedding content. Embedding the My Bluescape interface is not supported; your application should provide workspace browsing as applicable, or you should direct users to the My Bluescape application in a separate window.

Embedding Existing Workspaces

The primary use of the Bluescape embedding API requires that your application renders HTML inside a web engine and that you know the workspace id of the workspace you wish to embed. In most cases, your application already works with specific workspaces before you embed them. Provide the workspace ID in the path after /embed, as below:

 <iframe width=1024 height=768
     src="https://client.apps.us.bluescape.com/embed/cNAcvwY-zFWVpP-djSvf"></iframe>

Bluescape recommends clients set width and height to the maximum size allowable inside your application (without causing the page to scroll). Other recommended attributes are in the code sample in the appendix.

This code allows you to quickly create an embedded Bluescape client and get it working on your web page! This client continues enforcing Bluescape’s authorization rules for workspaces, so you must log in first. The embedded client automatically redirects to a login page if the user is not already logged in and must log in with an account that can view that workspace to load it. Otherwise, the client informs the user that they are not authorized to access that workspace.

Embedding Scratch Workspaces

In cases where you want to embed Bluescape’s functionality but do not have a preexisting workspace, you can use scratch workspaces. Scratch workspaces are a special kind of workspace that allows for quick and easy creation and deletion for embedded scenarios but not long-term use. You might have already seen scratch workspaces when hosting a scheduled meeting in Bluescape, where we create a scratch workspace for your meeting and then delete it if you didn’t use it. But if you did use it, you need to save it as a regular workspace before using it further.

Scratch workspaces have the basic content features of any workspace (premium features excluded) but do not belong to an organization and do not have any access control features. Anyone who knows the id of a scratch workspace is capable of viewing and modifying it. Bluescape does not recommend scratch workspaces for highly sensitive data, and you must claim your scratch workspace for long-term use. After claiming the workspace, Bluescape applies full workspace authorization logic. At this point, you must also associate the workspace with an organization, and any premium features or custom configuration for that organization becomes available.

To use scratch workspaces in an embedded scenario is a multi-step process:

  1. Create a scratch workspace. This API call requires a registered user
    token, most likely one for your application.
REST POST /v3/scratchWorkspaces
GraphQL Mutation.createScratchWorkspace
  1. Embed the scratch workspace (this is identical to the existing workspace scenario, using the id of your newly created scratch workspace).

HTML <iframe src="https://client.{instance}/embed/{id}"></iframe>

  1. Save the scratch workspace. This API call requires you to use the
    same token you used to create the scratch workspace and then associate it with the email of one of the users in the workspace. Once logged into Bluescape (using that email address), the user can claim it and persist the workspace contents for future use.
REST PATCH /v3/scratchWorkspaces/{id}
GraphQL Mutation.updateScratchWorkspace

Note: The email address you save the scratch workspace with does not need to
be a valid user. This allows you to use embedded Bluescape workspaces with users who may not already have a Bluescape account. New users may still sign up if they wish to retain the saved workspace for future use. However, this also means you must guard against typos, as a mistyped email address would be considered a new user.

A complete example of doing this full flow with Bluescape’s REST APIs is present in an appendix.

autoLogin

As scratch workspaces do not have any authorization control, they are automatically available for use by unregistered users (also known as anonymous users, as they do not have a persistent user identity). If your use case intends to embed Bluescape for use with these users, redirecting to the login screen when unauthorized does not help. For this scenario, you can set the autoLogin query parameter to “1,” and it will automatically attempt to log the user in as an unregistered user. This merely requires the user to provide a name for the collaborators list. For example, if you set the src attribute of your iframe to:

https://client.apps.us.bluescape.com/embed/cNAcvwY-zFWVpP-djSvf?autoLogin=1

Then, the prompt would be for a name and not valid user credentials, after which
you would enter the workspace with the id cNAcvwY-zFWVpP-djSvf (if it is a scratch workspace; if not, then you would hit an authorization error screen). Whatever name the user provides will be used in the collaborators list of the workspace, there is no validation.

Note that the autoLogin query parameter will only have an effect if the user is not
already logged in (including the unregistered login performed when the parameter is set). Any existing login session will be used automatically, and you must clear your cookies to reach the login (or name prompt) screen again.

We are interested in feedback as to just what is the most useful behavior for this
flag, with options including (but not limited to):

  • Go to the anonymous login page and prompt for a name (current behavior).
  • Skip the anonymous login page and provide a random name.
  • Skip the anonymous login page and require that a name be passed separately.

We may introduce additional parameters to select the behavior,
depending on user feedback.

Caveats

The example code in the appendix was tested against the 22.08.2 release of Bluescape. The behavior may change over time, in particular, the autoLogin parameter. There are also known issues that we intend to address in future releases.

Authentication Issues

The focus for Browser security for third-party embedding in iframes is on restricting cookie access. Bluescape uses session cookies as a mandatory part of the web client, which can lead to issues with the embedded API. Safari blocks cookies of another domain, even if that domain embeds in an iframe. Authentication inside the iframe may not work at all. In Firefox, where cookies of another domain are present in a separate partition based on the page domain, login inside an iframe may work but is separate from any session outside the iframe. We are working on moving session tracking outside of cookies so that it can work more reliably when embedded in an iframe.

Additionally, SAML SSO authentication may not be possible in an iframe, depending on the settings of the IDP. We do not recommend using the embedded Bluescape client with SAML SSO users.

Scratch Workspace Delete

To delete a scratch workspace created via the API, you must first set the email to the user who created it before calling the delete API (as the user who created it). This may lead to it showing up in the user’s My Bluescape page if they view the page between those two operations. In the future, unsaved scratch workspaces are deleted automatically, so no manual delete is required if you don’t want it to show up to the user. Unsaved scratch workspaces do not count against any user’s quota, so there is no cost to the user to wait for the automatic deletion.

Appendix

Example Code

index.html

<html>
   <head>
      <title>iFrame Test Page</title>
      <script src="index.js"></script>
   </head>
   <body>
      <p>Embedded Bluescape Example</p>
      <!-- Replace the workspace id "cNAcvwY-zFWVpP-djSvf" with the id of a workspace your users may have access to. An authorized user login is required, except for scratch workspaces -->
      <iframe width=1024 height=768 id="iframe-bluescape" src="https://client.apps.us.bluescape.com/embed/cNAcvwY-zFWVpP-djSvf" crossorigin="use-credentials" title="Bluescape Workspace" allow="clipboard-read *; clipboard-write"></iframe><br />
      <input type="button" onclick="login()" value="Log in to Bluescape"/>For below actions only<br />
      <input type="button" onclick="createWs()" value="Create Scratch Workspace"/> <br />
      <input type="button" onclick="saveWs()" value="Save Scratch Workspace"/> <input type="text" id="emailInput" /> <br />
      <!-- If we came to the page after being redirected back from the OAuth log in page, identify that and save the token -->
      <script>respondToLogin();</script>
   </body>
</html>

index.js

// If you have your deployment of Bluescape, you may need to change the instance domain here:
const bluescapeEmbedBase = ’https://client.apps.us.bluescape.com/embed’;

// Set this to the parameters of your application to load a token by the OAuth redirect flow.
// See https://community.bluescape.com/t/api-application-authorization/2025 for more details
// Alternatively, if you have a valid token already, you may input it directly below.
const clientId = ’{insert clientId}’;
const redirectUri = ’http://localhost:8080’;

// Set this to a valid Bluescape access token for your application, see https://community.bluescape.com/t/api-application-authorization/2025 on how to obtain a token.
// Alternatively, if you have an application registration you may input it above.
var bluescapeToken = ’’;

var scratchWsId;

var createWs = function () {
// First we create a scratch workspace using the api: https://api.apps.us.bluescape.com/docs/doc/us/isam#/Scratch%20Workspace/ScratchWorkspaceController_createScratchWorkspace
const wsReq = new XMLHttpRequest();
wsReq.open(’POST’, ’https://api.apps.us.bluescape.com/v3/scratchWorkspaces’);
wsReq.setRequestHeader(’Authorization’, ‘Bearer ${bluescapeToken}‘);
wsReq.addEventListener(’load’, function () {
if (this.status != 201) {
console.error(‘Error creating scratch workspace: ${this.responseText}‘);
return;
}
const res = JSON.parse(this.responseText);
const wsId = res.id;
scratchWsId = wsId;
/* Now we set the iframe to display the new workspace. This requires setting the iframe src to the embed client route with the workspace id.
* The autoLogin parameter lets you try to log in as an anonymous user.
* In future versions, it may log you in as an anonymous user automatically, or allow bypassing the UI by setting name/email in query parameters
*/
document.getElementById(’iframe-bluescape’).src = ‘${bluescapeEmbedBase}/${wsId}?autoLogin=1‘;
});
wsReq.send();
}

var saveWs = function () {
if(!scratchWsId) {
console.error(’No scratch workspace to save’);
return;
}

const email = document.getElementById(’emailInput’).value;

if(!email) {
console.error(’No email to save to’);
// Scratch workspaces must first be associated with an email, allowing the user who logs in with that email to save it permanently.
// This ensures workspaces will show up in an appropriate user's My Bluescape page, even if the workspace was created by an app.
return;
}

// The API doc is https://api.apps.us.bluescape.com/docs/doc/us/isam#/Scratch%20Workspace/ScratchWorkspaceController_updateScratchWorkspace
const saveReq = new XMLHttpRequest();
saveReq.open(’PATCH’, ‘https://api.apps.us.bluescape.com/v3/scratchWorkspaces/${scratchWsId}‘);
saveReq.setRequestHeader(’Authorization’, ‘Bearer ${bluescapeToken}‘);
saveReq.setRequestHeader(’Content-Type’, ’application/json’);
saveReq.addEventListener(’load’, function () {
console.log(this.responseText); // We don’t really need the response, unless we’re checking for errors
});
saveReq.send(JSON.stringify({email, ’name’: ’Embedded Example’}));
// Note that an email will not be sent automatically. You will need to inform users to check My Bluescape for the workspace.
}

var login = function () {
if (bluescapeToken) {
alert(’Example app has a token already, not logging in!’);
return;
}
const loginUri = ‘https://api.apps.us.bluescape.com/authorize?response_type=token&client_id=${clientId}&redirect_uri=${redirectUri}‘;
window.location.href = loginUri;
}

var respondToLogin = function () {
const values = new URLSearchParams(window.location.hash.slice(1));
console.log(window.location.hash)
console.log(values)
if (values.has(’access_token’))
bluescapeToken = values.get(’access_token’);
}

Where to Next?

Not what you were looking for? Reply below or Search the community and discover more Bluescape.

1 Like