Authenticating Embedded Users
When you embed a Superblocks app into your website, you have several options for authentication:
- Public: anyone can view your app, no login required
- Private: users log in to Superblocks directly and must have
apps:view
permission to the application - SSO: use your application's existing login flow so users only have to log in once to access the embedded Superblocks app
Public and Private embeds have no added set up. Follow instructions below to configure SSO.
SSO Authentication flow
With SSO embedding, users access your embedded app without needing a separate Superblocks login. Instead, you'll log users in with your app's existing auth and issue them a Superblocks session token for embedded auth. Using the Superblocks session token, your user's identity, level of access, and metadata are securely transmitted to Superblocks so they can't be modified by users client-side.
The following diagram illustrates the authentication flow for SSO embed users:
Set up embedded SSO
Use the following instructions to have your application authenticate users with Superblocks.
Step 1. Generate an access token
Only organization Admins can create Embed access tokens.
To get Superblocks session tokens for your embed users, you'll need to create an Embed access token. Follow the instructions below to create an access token, or learn more about Access tokens.
-
Click your avatar in the upper-left corner of the home page and click Organization Settings
-
In the left sidebar, click Access Tokens
-
Click +Create token
-
In the Name field give your token a descriptive name
-
Select an Expiration date, or use the default 90 day expiration.
-
Select Embed as the token type
-
Click Create
Your access token is visible one time, immediately after you create it. If you leave or refresh the page where the token is displayed, it will be obscured and no longer visible. You must copy and store new access tokens somewhere secure before you leave the creation page, or you will lose access to the token.
Step 2. Add token endpoint to your web-server
Add an endpoint to your web-server that requests user session tokens from Superblocks. You can add this as a new endpoint, or to your existing authentication flow.
- Node.js (Express)
- Python (Flask)
- Django
// Get user session token from Superblocks API
app.get('/api/superblocks/token', checkAuthentication, async (req, res) => {
// Assuming getUser returns the currently authenticated user
const user = getUser(req);
const config = {
url: `https://app.superblocks.com/api/v1/public/token`,
method: 'post',
headers: {
'Authorization': `Bearer ${YOUR_ACCESS_TOKEN_HERE}`,
'Content-Type': 'application/json',
},
data: {
email: user.email,
name: `${user.firstName} ${user.lastName}`,
metadata: {
externalUserId: user.id,
externalOrgId: user.organization.id
}
}
};
// Call endpoint to request a Superblocks session token on-behalf-of the authenticated user
axios(config)
.then((response) => {
if (response.status === 200) {
res.json(response.data);
} else {
throw new Error('Could not authenticate user with Superblocks');
}
})
.catch((error) => {
res.status(401).json({ error: 'unathorized', message: error.message });
});
});
from flask import jsonify
import requests
@app.route('/api/superblocks/token', methods=['GET'])
def superblocks_auth():
# Assuming getUser() returns the currently authenticated user
user = getUser()
# Call /token endpoint to request a session on-behalf-of the authenticated user
response = requests.post(
"https://app.superblocks.com/api/v1/public/token",
headers={
'Authorization': f'Bearer {YOUR_ACCESS_TOKEN_HERE}',
'Content-Type': 'application/json'
},
json={
'email': user.email,
'name': f'{user.firstName} {user.lastName}',
'metadata': {
'externalUserId': user.id,
'externalOrgId': user.organization.id
}
}
)
if response.status_code == 200:
data = response.json()
return jsonify(data)
else:
return jsonify({
'error': 'unauthorized',
'error_description': 'Could not authenticate user with Superblocks'
}), 401
from django.http import JsonResponse
from django.views import View
from django.contrib.auth.mixins import LoginRequiredMixin
import requests
class SuperblocksAuth(LoginRequiredMixin, View):
def get(self, request):
user = request.user
# Call /token endpoint to request a session on-behalf-of the authenticated user
response = requests.post(
"https://app.superblocks.com/api/v1/public/token",
headers={
'Authorization': f'Bearer {YOUR_ACCESS_TOKEN_HERE}',
'Content-Type': 'application/json'
},
json={
'email': user.email,
'name': f'{user.firstName} {user.lastName}',
'metadata': {
'externalUserId': user.id,
'exgernalOrgId': user.organization.id
}
}
)
if response.status_code == 200:
data = response.json()
return JsonResponse(data)
else:
return JsonResponse({
'error': 'unauthorized',
'error_description': 'Could not authenticate user with Superblocks'
}, status=401)
Make sure to replace the payload with information for the currently authenticated user.
Make sure your web server has CORS enabled if it's running on a different domain than your host application.
For a detailed explanation of the parameters, request format, and response format for the /token
endpoint, please refer to the full API specification below.
Step 3. Request token client-side
Add code to your web application to request a session token from the token endpoint you just added to your application's web server.
- React
- JavaScript
export const getSBToken = () => {
return fetch(`https://${YOUR_API_DOMAIN}/api/superblocks/token`).then(
res => res.json()
).then(
data => data.access_token
).catch(
err => {
throw new Error('Superblocks Auth Error');
}
);
}
function getSBToken () {
return fetch(`https://${YOUR_API_DOMAIN}/api/superblocks/token`).then(
res => res.json()
).then(
data => data.access_token
).catch(
err => {
throw new Error('Superblocks Auth Error');
}
);
}
Step 4. Pass the token to your embed
- React
- JavaScript
import React, { useState, useEffect } from 'react';
import { SuperblocksEmbed } from '@superblocksteam/embed-react';
import { getSBToken } from '../utils';
const PageWithEmbed = () => {
const [token, setToken] = useState(null);
useEffect(() => {
getSBToken()
.then((token) => setToken(token))
.catch(err => console.log('Failed to get Superblocks auth token'));
}, []);
const handleFailedAuth = (err) => {
console.log('Superblocks auth token invalid');
}
return <>
{ token ?
<SuperblocksEmbed
src='https://app.superblocks.com/embed/applications/<APP_ID>'
token={token}
onAuthError={handleFailedAuth}
/> :
<div>Loading...</div>
}
</>;
}
<script>
const token = await getSBToken();
const sbApp = Superblocks.createSuperblocksEmbed({
id: "sb-app",
src: 'https://app.superblocks.com/embed/applications/<APP_ID>',
token: token
});
document.body.appendChild(sbApp);
</script>
Manage user access
Embed users must have the apps:view
permission to the Superblocks app they're trying to access.
Grant users access by associating them with a Group with the necessary access level. To associate an embed user with a group:
-
Click your avatar in the upper-left corner of the home page
-
In the menu, click Organization Settings
-
In the left sidebar, click Groups
-
Either select + Add group or click into an existing group
-
On the Apps, Workflows & Jobs tab, enable View access for apps you want the user(s) to have access to
![Cash App Customer user group with view access to "Credit Card Application Processing" tool](/img/applications/embedding/group-permissions.png "Cash App Customer user group with view access to "Credit Card Application Processing" tool")
-
Go back to the Groups page and copy the group's ID by selecting ... → Copy group ID
-
Update your server endpoint by adding a list of
groupIds
you want users to be associated with.
- Node.js (Express)
- Python (Flask)
- Django
fetch("https://app.superblocks.com/api/v1/public/token", {
...
body: JSON.stringify({
'email': user.email,
'name': `${user.firstName} ${user.lastName}`,
// Superblocks Group IDs which grant view access to apps embedded in this website
'groupIds': [
'cc07e026-02c7-4ab5-b33b-232d57e7c804'
]
})
});
response = requests.post(
"https://app.superblocks.com/api/v1/public/token",
...
json={
'email': user.email,
'name': 'name': f'{user.firstName} {user.lastName}',
# Superblocks Group IDs which grant view access to apps embedded in this website
'groupIds': [
'cc07e026-02c7-4ab5-b33b-232d57e7c804'
]
}
)
# Call /token endpoint to request a session on-behalf-of the authenticated user
response = requests.post(
"https://app.superblocks.com/api/v1/public/token",
...
json={
'email': user.email,
'name': 'name': f'{user.firstName} {user.lastName}',,
# Superblocks Group IDs which grant view access to apps embedded in this website
'groupIds': [
'cc07e026-02c7-4ab5-b33b-232d57e7c804'
]
}
)
Embed users aren't permanent members of groups and won't show up on the Members tab of groups. They are associated with the group for permissions purposes for the duration of the token's session.
Customize user metadata
User metadata lets you attach additional information to a user beyond the standard attributes. This can be useful for storing extra data relevant to your application or business logic.
To customize user metadata, include a metadata
field in your request payload with JSON representing the metadata you want to add. For example:
- Node.js (Express)
- Python (Flask)
- Django
fetch("https://app.superblocks.com/api/v1/public/token", {
method: 'POST',
...
body: JSON.stringify({
'email': user.email,
'name': `${user.firstName} ${user.lastName}`,
'metadata': {
'externalUserId': user.id,
'externalOrgId': user.organization.id,
// Additional user metadata to customize app behavior
// Access in Superblocks using {{ Global.user.metadata }}
'isAdmin': user.roles.includes('Admin')
}
})
});
response = requests.post(
"https://app.superblocks.com/api/v1/public/token",
...
json={
'email': user.email,
'name': f'{user.firstName} {user.lastName}',
'metadata': {
'externalUserId': user.id,
'externalOrgId': user.organization.id,
# Additional user metadata to customize app behavior
# Access in Superblocks using {{ Global.user.metadata }}
'isAdmin': 'Admin' in user.roles
}
}
)
# Call /token endpoint to request a session on-behalf-of the authenticated user
response = requests.post(
"https://app.superblocks.com/api/v1/public/token",
...
json={
'email': user.Email,
'name': f'{user.firstName} {user.lastName}',
'metadata': {
'externalUserId': user.id,
'externalOrgId': user.organization.id
# Additional user metadata to customize app behavior
# Access in Superblocks using {{ Global.user.metadata }}
'isAdmin': 'Admin' in user.roles
}
}
)
Metadata can be accessed using {{ Global.user.metadata }}
.
Metadata is associated with the user's current session and encoded in the session JWT as custom claims. This ensures that the metadata cannot be modified client-side, providing an additional layer of protection against unauthorized tampering.
Token API specification
POST /api/v1/public/token
Use this endpoint to request a session token for an embedded user.
Request parameters
application/json
Parameter | Required | Type | Description |
---|---|---|---|
email | ✓ | String | The user's email address, which uniquely identifies them in Superblocks. |
name | String | The user's full display name. | |
groupIds | Array | Superblocks Group IDs to associate the embed user with. | |
metadata | Object | Object containing additional metadata about the user. | |
isSuperblocksUser | Boolean | If TRUE , the token will be associated with the Superblocks platform user with the email specified. If no platform user exists with that email, the user will get an Unauthorized error. |
- cURL
- Node.js
- Python
curl --request POST
--url 'https://{REGION}.superblocks.com/api/v1/public/token' \
--header 'authorization: Bearer {YOUR_ACCESS_TOKEN_HERE}' \
--header 'content-type: application/json' \
--data-raw '{
"email":"jane.wind@company.com",
"name": "Jane Wind",
"metadata": {
"externalUserId": "d942c6...72f362",
"externalOrgId": "c32979...acf711"
}
}'
const axios = require('axios');
const config = {
url: `https://${REGION}.superblocks.com/api/v1/public/token`,
method: 'post',
headers: {
'Authorization': \`Bearer ${YOUR_ACCESS_TOKEN_HERE}`,
'Content-Type': 'application/json',
},
data: {
"email": "jane.wind@company.com",
"name": "Jane Wind",
"metadata": {
"externalUserId": "d942c6...72f362",
"externalOrgId": "c32979...acf711"
}
}
};
axios(config)
.then((response) => {
if (response.status === 200) {
res.json(response.data);
} else {
throw new Error('Could not authenticate user with Superblocks');
}
})
.catch((error) => {
res.status(401).json({ error: 'unathorized', message: error.message });
});
import requests
import json
url = "https://{REGION}.superblocks.com/api/v1/public/token"
payload = {
"email": "jane.wind@company.com",
"name": "Jane Wind",
"metadata": {
"externalUserId": "d942c6...72f362",
"externalOrgId": "c32979...acf711"
}
}
headers = {
'authorization': 'Bearer {YOUR_ACCESS_TOKEN_HERE}',
'content-type': 'application/json'
}
response = requests.request("POST", url, headers=headers, json=payload)
print(response.text)
Response Sample
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token":"eyJz93a...k4laUWw",
"token_type":"Bearer",
"expires_in":86400
}