Identity & Sign-in
Appilot attributes every conversation to an identified user. There is no anonymous usage: the widget will not chat until it knows who the user is. This page explains the identity sources the widget supports, what the panel shows for each configuration, and how to fix the "Sign in to continue" notice.
If your app has user accounts, pass a federation token (data-user-token). If it does not, enable the built-in sign-in (data-user-auth="true"). If you do neither, visitors see a "Sign in to continue" notice and cannot use the assistant.
The three identity sources
| Source | Choose it when | Where it is documented |
|---|---|---|
Federation token (data-user-token) | Your app has its own user accounts (the common case). Your backend mints a short-lived Appilot token for the logged-in user; users never see a second login. | Connecting your users |
Built-in Appilot sign-in (data-user-auth="true", or org-wide via the Backoffice Widget sign-in switch) | Your site has no user accounts, or your users already have Appilot accounts (internal tools). The panel shows Appilot's own login/register form. | Built-in sign-in below |
| Enterprise SSO (OIDC / SAML) | Corporate deployments where members sign in through the company identity provider. Configured per organization. | Enterprise SSO |
The sources combine safely: a federation token always wins when present, and the built-in sign-in only appears when there is no token and no stored session.
What the panel shows
The widget resolves its identity state on every load:
| Configuration | What the user sees |
|---|---|
data-user-token present (or Appilot.setUserToken(...) called) | Straight to the assistant. No sign-in UI at all. |
| Federation token present but rejected (expired, or the user's session in your app ended) | The "Your session has expired" notice: the conversation is kept, and the user is asked to sign in to your app again. The widget also fires an immediate token refresh request, so once you hand it a fresh token (Appilot.setUserToken) the chat returns by itself. |
| No token, built-in sign-in enabled | The Appilot sign-in / register form inside the panel. After signing in, the user chats normally. |
| No token, built-in sign-in disabled (default) | The "Sign in to continue" notice: the assistant is locked, with a short hint for the site owner and a link to this page. |
The Knowledge Base and Settings views stay accessible in every state; only the conversation requires an identity.
Federation tokens are short-lived (about an hour). If you boot the widget with the @betterknow/appilot SDK (bootAppilotWidget), it re-mints the token before expiry and hands it to the live widget automatically, so a tab left open all day stays signed in. If you embed the script tag yourself, re-mint on your side and call Appilot.setUserToken(freshToken); the widget also dispatches appilot:identity-refresh-requested on window whenever it needs a fresh token right now.
Window events your page can listen to
The widget talks to the embedding page through two CustomEvents on window:
| Event | When it fires | event.detail |
|---|---|---|
appilot:identity-refresh-requested | The widget needs a fresh federation token right now (its current one expired or was rejected). Answer by re-minting and calling Appilot.setUserToken(freshToken). | none |
appilot:auth-invalidated | The widget's own Appilot credential was rejected mid-session. The widget already handles this itself (the "Your session has expired" notice); the event is informational. | { source: 'appilot-widget', reason?: 'expired' } (the browser extension emits source: 'appilot-extension') |
If your app happens to use the same appilot:auth-invalidated event name for
its own session handling, always check detail.source and ignore any event
whose source starts with appilot-: those events describe the widget's
credential, and your app's session is still valid. The embedded surfaces do the
mirror-image filtering, so events your app emits (without an appilot-*
source) never sign the widget out.
Fixing the "Sign in to continue" notice
The notice means the widget booted with no identity source: no federation token was passed, and the built-in sign-in is not enabled. Pick the fix that matches your setup:
Your app has user accounts → pass a federation token
After your user logs in to your app, your backend exchanges your widget key + server secret + the user's id for a short-lived Appilot token, and you render it into the embed:
<script type="module" src="https://cdn.appilot.com/widget/v1/appilot.esm.js"
data-user-token="<token minted by your backend>"></script>
<script nomodule src="https://cdn.appilot.com/widget/v1/appilot.js"
data-user-token="<token minted by your backend>"></script>
The full handshake (with the POST /widget/token call and security notes) is in Connecting your users. If your app authenticates after the page loads, init without the token and set it later with Appilot.setUserToken(token).
Your site has no user accounts → enable the built-in sign-in
<script type="module" src="https://cdn.appilot.com/widget/v1/appilot.esm.js"
data-user-auth="true"></script>
<script nomodule src="https://cdn.appilot.com/widget/v1/appilot.js"
data-user-auth="true"></script>
The panel now shows Appilot's own sign-in / register form instead of the notice. Alternatively, an organization admin can enable the form for all embeds of the organization from the Backoffice Widget Keys page (the Widget sign-in switch), with no embed change needed; either switch is sufficient.
Corporate identity provider → Enterprise SSO
Your organization connects its OIDC / SAML provider so members sign in via corporate SSO. See Enterprise SSO.
Built-in sign-in (data-user-auth)
When enabled, the panel renders Appilot's login/register form for users without a session. Two things to know before choosing it:
- The user signs in with an Appilot account, not an account on your site. Users who do not have one can register from the same form.
- The account must belong to your organization. A signed-in user is accepted only while they are an active member of the organization that owns the widget. This makes the built-in sign-in a great fit for internal tools and member portals, and a poor fit for anonymous public visitors (use federation for those, so your app vouches for the user).
Conversations started after the built-in sign-in appear in the user's My Account history, exactly like conversations from the Chrome extension.
Configuration reference
| Attribute | JS API | Default | Effect |
|---|---|---|---|
data-user-token | userToken | n/a | Federation token minted by your backend. Sent as Authorization: Bearer on every turn. |
data-user-auth | userAuth | false | "true" shows the built-in Appilot sign-in when no identity is present. Any other value keeps it off. An org admin can also enable the form organization-wide from the Backoffice (Widget Keys → Widget sign-in); the two switches are OR-ed. |
data-docs-base-url | docsBaseUrl | https://docs.appilot.de | Documentation root used by in-panel help links (including the link on the "Sign in to continue" notice). Override it for on-premise deployments that self-host these docs. |
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Panel shows "Sign in to continue" with no form | No data-user-token and built-in sign-in disabled | Pick an identity source above |
API returns 401 WIDGET_IDENTITY_REQUIRED | A message was sent without a valid identity | Same as above; if you pass a token, check it is not expired (re-mint and call Appilot.setUserToken) |
| Built-in sign-in succeeds but the assistant still refuses | The account is not a member of the organization that owns the widget | Invite the user to your organization, or use federation so your app asserts the identity |
| Sign-in form appears even though you pass a token | The token is rendered into only one of the two script tags | Put the same data-* attributes on both the type="module" and the nomodule lines |