--- title: "Fix a signed-in customer who shows as a guest | Busymate AI" description: "Match your exact symptom to its cause and the conformance-checker cell that proves it, including the WebView-loads-your-own-page case." --- # Fix a signed-in customer who shows as a guest | Busymate AI Source: https://busymate.ai/hi/docs/guides/identity-troubleshooting Busymate AI shows almost the same symptom for every identity mistake: a customer you know is signed in shows up in the chat as a guest. This page starts from what you see, names the layer that actually broke, and identifies the exact cell in the conformance checker that will confirm the fix — instead of guessing across your website, your app and your backend at once. ## 1. Match your symptom to a cause | You see | The likely cause | What proves it | |---|---|---| | Signed in on the site, the chat still offers Sign in | Your bridge answered nothing on the first ask — often because it registered after the page had already loaded and asked once | The [Identity check](https://busymate.ai/developers/identity-check)'s first-launch cell | | The first message is identified, every one after is a guest | Your app's WebView loads your OWN page rather than the assistant directly, and that page only answers the very first ask | See "Your app's WebView loads your own page" below | | The customer signs out; the chat still shows their name | The sign-out call was never wired, so the previous session survives until the view is destroyed | The checker's logout cell | | It works on one native platform, fails on the other | The two bridges answer at the wire level differently — one can deliver a JSON string where the other delivers a real object, and a string with no `type` field is silently dropped | Run the checker against each platform on its own | | A launch that worked a moment ago is refused as expired, or as not-yet-valid | Your server's clock has drifted past the verifier's tolerance | The CLI's clock-skew cell reads your `iat` against server time | | A sign-in works once, then every later ask is refused | A launch proof is single-use; something cached the pair and answered a second ask with it | The checker's token-expiry cell mints twice and expects two different answers | ## 2. When your app's WebView loads a page you built The shape that hides an otherwise-correct integration: your app's WebView does not load the assistant directly — it loads a page you built, and that page embeds the assistant. The assistant then asks its parent, which is your own page, and your page has no session of its own; the customer is signed in *natively*, one layer further out. A token on the launch URL answers the first ask and nothing after it, so a resume, a reconnect, an expiry and a restart each quietly fall back to no session there. The fix has two halves, and both are required: keep the native bridge from [Recognize signed-in customers](https://busymate.ai/hi/docs/guides/identified-visitors) installed in the app, and give your own page the small asker that forwards later questions to it — `https://busymate.ai/sdk/v1/kit/web/native-identity.js`. Installing only the bridge leaves it correct and unreachable. ## 3. Read the exact missing step, do not guess it Two checks, one set of rules. The [Identity check](https://busymate.ai/developers/identity-check) runs the lifecycle half against a page of yours and grades what comes back: a token that was not fresh, a sign-out that changed nothing, a bridge that answered late. The CLI — `node v2/scripts/identity-conformance.mjs --host --json` — runs the half a browser cannot reach: JWKS reachability, key and algorithm agreement, claim shape, clock skew, and the CORS rules of your own endpoint. Each prints pass, fail, or could-not-observe per cell, together with the step it is missing, rather than a bare "identity broken". ## Verify 1. Run the browser check and the CLI against the same host; note any cell that fails or comes back unobserved. 2. Fix the named step, not the whole integration — one obligation from [Recognize signed-in customers](https://busymate.ai/hi/docs/guides/identified-visitors) is usually the entire gap. 3. Re-run both. A clean pass on every cell, not a green first screen, is what "fixed" means here. 4. In Console → Identity health, the same picture appears per platform — the fastest way to tell whether the fix reached every customer, not only the one browser you tested from. ### Do I need to know which layer is broken before I run the checker? No. Point it at your host and it names the layer itself — a page, a bridge, or your signing endpoint — instead of asking you to guess between them. ### What if the CLI cannot reach my identity endpoint at all? It reports that cell as could-not-observe, not as a pass. An unreachable endpoint is never counted as working; fix reachability, then re-run. ### The browser check and the CLI disagree — which one is right? Neither overrides the other. The browser proves the lifecycle a real page produces; the CLI proves what a browser cannot see, your endpoint's own response. A real integration passes both. ### Does either check keep or send on a real token? No. Both record shapes — whether two mints differ, whether a claim is present — never the token, the nonce, or a claim's value. ### My symptom is not on this page — where do I look next? Start at [Recognize signed-in customers](https://busymate.ai/hi/docs/guides/identified-visitors)'s four obligations; nearly every guest-when-signed-in report traces back to one of them. ## Next - **[Recognize signed-in customers](https://busymate.ai/hi/docs/guides/identified-visitors)** — the contract every platform below implements. - **[Sign identity tokens from your backend](https://busymate.ai/hi/docs/guides/identity-backend-signing)** — the endpoint every check above talks to. - **[In-app AI support for iOS and Android](https://busymate.ai/hi/docs/guides/mobile-in-app-support)** — the native bridge this page's WebView case depends on.