SSOing into your App from within Duda.

When users access your UI via an iframe in Duda's editor, Duda will render an iframe to the URL specified in the manifest under base_sso_url with additional query parameters to allow you to authenticate the user into your App.

The URL format is: {{base_sso_url}}?site_name={{site name}}&timestamp={{time stamp}}&lang={{use langauge code}}&is_white_label={{false}}&editor_origin={{}}&sdk_url={{SDK URL}}&current_user_uuid={{user uuid}}&secure_sig={{signature}}&editor_origin={{}}

There are two types of parameters that Duda attaches here:

SSO Parameters

timestampThe timestamp on Dudas servers that was used to generate the SSO Signature.
site_nameThe unique site_name that is being logged into. You should already have created access once the App was installed for this website.
sdk_urlThe URL of the JS SDK that can be used to interact with the Duda editor.
secure_sigThe signature that was signed by the private key, stored within Duda. You can decode this using the public key.

Informational Query Parameters:

langLanguage of the active user in the Duda platform.
is_white_labelA flag indicating if the user is considered white labeled (does not see Duda branding).
current_user_uuidThe current user's UUID within the Duda platform.
editor_originThe origin (protocol + host) of the parent URL where the user was logged into. Since Duda is white-labeled, this can be any domain.

Duda passes a signature signed by the app-specific private key (which Duda stores). You should verify the SSO signature to validate that the user should be allowed to log in. Use the public key in your app's manifest to verify the signature by decrypting it.

Duda formats our keys using PKCS#1 (default for RSA) with a 2048 bit key length. Duda URL encodes the entire URL string before redirecting the user to that URL, so you should be sure to URL decode each value passed. This is the same as: RFC3986.

You should verify the data by concatenating the site_name, sdk_url, and timestamp with a colon between each. See the following examples:

async function authenticateAPI(payload: AuthDudaInterface): Promise<boolean> {
  if (
    !payload?.sdkUrl ||
    !payload?.timestamp ||
    !payload?.secureSig ||
  ) {
    throw new Error('Bad User Input: all fields are mandatory');
  const { sdkUrl, secureSig, siteName, timestamp } = payload;
  const decodedSignature = decodeURIComponent(secureSig);
  const decodedSdkUrl = decodeURIComponent(sdkUrl);
  const decodedSiteName = decodeURIComponent(siteName);
  const sigDataToVerify = `${decodedSiteName}:${decodedSdkUrl}:${timestamp}`;
 	const publicKey = process.env.DUDA_PUBLIC_KEY; // originally from App Manifest

	const decryptedSig = crypto
        '-----BEGIN PUBLIC KEY-----\n' +
          publicKey +
          '\n-----END PUBLIC KEY-----',
        Buffer.from(decodedSignature, 'base64'),
  // return true false if successfully verified
  return decryptedSig === sigDataToVerify

Additionally, Duda encodes the Signature in Base64 before sending it, so you should decode it as well. Most RSA/Crypto libraries have support for base64 decoding as part of the process.

Time Validity of SSO Links

Apps are expected to refuse SSO links with a timestamp older than 120 seconds before the SSO link HTTP request is received by the App.

Duda cannot technically enforce such a policy. However, Duda will, from time to time, test if Apps comply with this policy.

User Language

Duda passes the language of the active user in the lang query parameter of the SSO link. App's iframe should localize according to this parameter. Note that for each Duda site there can be several users working on different languages, so this should be done at time of SSO.

The full list of languages in the Duda editor can be found here.

Cookie Management

You need to set both SameSite=None and Partitioned flags on your authentication cookies when authenticating a user from the Duda App Store.

Same Site Cookie Flag

Since your App will load in an iframe by default, web browsers treat your SSO URL as a 3rd party context. In order for you to properly be able to set cookies, you need to make sure that you configure your cookie to properly work in a 3rd party context by setting the SameSite attribute to None. This informs browsers that the cookie is not from the same parent side and allows it to be set. We recommend reading the MDN documentation on the SameSite attribute.

This flag is being phased out, in favor of PartitionedCookies & the related CHIPS feature. It's still a good idea to set it, for browsers that don't support Partitioned yet.

Partitioned Cookies

Starting in 2024, Chrome is starting to deprecate 3rd party cookies (mostly against Ads, not authentication cookies). To support use cases like Duda's App Store, Google has released their Cookies Having Independent Partitioned State (CHIPS) support. This allows developers to set cookies in a 3rd party context, but they remain scoped to the parent (top-level) domain.

To use this in the Duda context, you simply need to set the Partitioned cookie flag (similar to SameSite, discussed above).