The idea of Stateless SSO is simple: Each time the embeds loads, you will send current user's data in the following attributes:
sso-user
: User's data in base64 encoded JSON formatsso-hash
:
HMAC hash
of sso-user
, created using your SSO Private key. Used to validate the
authenticity of the user data.The following embeds support those attributes:
<hyvor-talk-comments>
<hyvor-talk-newsletter>
<hyvor-talk-memberships>
<hyvor-talk-comment-count>
If you have a login popup instead of a URL, keep the login URL empty, and use the auth:login:clicked event to open the popup.
To set up Stateless SSO, you have to set the sso-user
and sso-hash
attributes
in the embed. Here is an example with a comment embed:
<hyvor-talk-comments
...other-props
sso-user="base-64 encoded, JSON-encoded user data"
sso-hash="HMAC hash"
></hyvor-talk-comments>
Or, using Javascript:
const comments = document.createElement("hyvor-talk-comments");
comments.setAttribute('sso-user', "base-64 encoded, JSON-encoded user data");
comments.setAttribute('sso-hash', "HMAC hash");
If your website is rendered using templates with back-end processing (for example, using PHP templates), you can calculate the data and hash at the time of template rendering, and then print them directly in the HTML code
<hyvor-talk-comments
...other-props
sso-user="<?= $userData ?>"
sso-hash="<?= $hash ?>"
></hyvor-talk-comments>
If you have a Single-Page application, you will need to create a new API endpoint (ex: /hyvor-talk-sso) to generate the data and hash in your backend. Then, call that endpoint to get the hash and then render the embed asynchronously.
const comments = document.createElement("hyvor-talk-comments");
const ssoData = await fetch('/hyvor-talk-sso')
.then(res => res.json());
comments.ssoUser = ssoData.user;
comments.ssoHash = ssoData.hash;
// finally add the element to DOM
document.body.appendChild(comments);
The following examples are written in Javascript/Node.
if (isUserLoggedIn()) {
}
Handling unauthenticated users:
If the user is not logged in, you can stop doing any other processing. In the components, set sso-user and sso-hash to empty values:
sso-user=""
in HTMLcomments.setAttribute('sso-user', null)
in Javascript (or any other empty value)Usually, you have a representation of the user in your system as an object or a model. Now, convert it to an object (or dictionary) that Hyvor Talk can 'understand'.
// this is your system's user
const user = getUser();
// create an object that Hyvor Talk understands
let userData = {
timestamp: Math.floor(Date.now() / 1000),
id: user.id,
name: user.fullname,
email: user.email,
picture_url: user.picture,
website_url: user.website,
bio: user.bio,
location: user.location,
badge_ids: [1,2]
}
timestamp
*integer
id
*integer
or string
name
*string
email
*string
picture_url
string
website_url
string
bio
string
location
string
badge_ids
integer[]
* Required
id
, email
, picture_url
, and website_url
should not exceed the maximum length. This will show an error message and prevent the embed from
loading. If name
, bio
, or location
exceeds the maximum
length, they will be trimmed.name
, picture_url
, website_url
, bio
,
and location
will be shown publicly. The email
will only be used
to send email notifications on replies and mentions. If you do not want us to send email
notifications, set the email
to a dummy (but unique) value like [id]@yourcompany.org.
Then, disable email notifications in the Console.First, convert the user object to a JSON string. Then, encode it to base64.
// 1. JSON encoding
userData = JSON.stringify(userData);
// 2. Base64 encoding
userData = Buffer.from(userData).toString('base64');
The next step is to generate an HMAC hash from userData. For this, we need the private key you received when setting up Stateless SSO in the Console. We use HMAC SHA 256.
Here we will use the crypto-js
Javascript library. However, most programming
languages have HMAC hashing functions built-in. Make sure to replace
YOUR_PRIVATE_KEY
with your own private key from Console → Settings → Single Sign-on.
const CryptoJS = require('crypto-js');
const hash = CryptoJS.HmacSHA256(userData, YOUR_PRIVATE_KEY);
timestamp
in the user object?Here's the complete code in JS (Node):
if (isUserLoggedIn()) {
// this is your system's user
const user = getUser();
// create an object that Hyvor Talk understands
let userData = {
id: user.id,
name: user.fullname,
email: user.email,
picture_url: user.picture,
website_url: user.website
}
// 1. JSON encoding
userData = JSON.stringify(userData);
// 2. Base64 encoding
userData = Buffer.from(userData).toString('base64');
// HMAC SHA256 hash
const CryptoJS = require('crypto-js');
const hash = CryptoJS.HmacSHA256(userData, YOUR_PRIVATE_KEY);
return {
user: userData, // sso-user attribute
hash: hash.toString() // sso-hash attribute
}
}
The last step is to set the attributes in the component:
sso-user
to the userData
variablesso-hash
to the hash
variableSee Sync vs Async initialization for how to set these attributes in different scenarios.
.env
or a key storage. Do not commit it to source
control.POST
HTTP
method, without any caching.You can also set up Stateless SSO without the hash, but read the following carefully:
Keyless Stateless SSO does not validate the authenticity of the user data. This means that if a user ID was compromised, an attacker can impersonate any user. This option should only be used if:
If you have an authentication provider that supports the OpenID Connect protocol, use OpenID Connect SSO instead.
To get started, enable the Keyless option in SSO settings in the Console.
Then, you can set the
sso-user
attribute to a JSON string. Here is an example:
const comments = document.querySelector('hyvor-talk-comments');
comments.setAttribute('sso-user', JSON.stringify({
timestamp: Math.floor(Date.now() / 1000),
id: 'user-id',
name: 'user-name',
email: 'user-email',
picture_url: 'user-picture-url',
website_url: 'user-website-url',
}))
See the User Data Object Properties for the properties you can set.