Comparing API Key vs OAuth vs Signed Token Auth for Healthcare Triage Bots Built with Next.js and React

Compare API keys, OAuth, and signed tokens for Next.js/React healthcare triage bots, with secure realtime session auth patterns.
Introduction
If you are building a healthcare triage bot in Next.js and React, auth is not a footnote. It determines whether your frontend can safely start a live session, whether your backend can mint scoped credentials, and whether an attacker can replay a token or impersonate a patient-facing assistant. With realtime voice and video in the mix, the choice between API keys, OAuth, and signed tokens affects both your security boundary and your deployment shape.
This article compares those three approaches in the specific context of a triage bot: a browser UI in React, server endpoints in Next.js, and a realtime agent that may stream audio, text, and a talking avatar. By the end, you should be able to choose an auth model, place the trust boundary correctly, and avoid the usual mistakes that show up when “it works locally” meets regulated-ish production workflows.
Start with the question: who is allowed to do what?
Before comparing mechanisms, define the actions in your system. For a triage bot, the common ones are:
Start a user session from the web app.
Let a backend create or update an agent configuration.
Allow a browser client to join a live conversation session.
Allow the agent to call downstream services: EHR lookup, scheduling, symptom routing, transcript storage.
Those are not all the same trust level. A browser can be trusted to present a user experience, but not to hold long-lived secrets. A backend can hold secrets, but should still minimize them. A third-party identity provider can assert who the user is, but not necessarily what your internal triage service should do on their behalf.
API keys: simplest for server-to-server, worst for browsers
An API key is a static credential that identifies your application. In practice, it is the easiest way to let your backend call a vendor API from a trusted server environment. For example, if your Next.js route handler needs to create a realtime session on behalf of your app, an API key is appropriate because the key never leaves the server.
The strengths are straightforward:
Very simple implementation.
No user consent flow required.
Works well for server-to-server automation and background jobs.
The weaknesses matter more in healthcare:
Static and high-value; leakage is catastrophic.
Usually too broad unless the vendor supports scoped keys.
Cannot safely live in a browser or mobile app.
A typical Next.js route handler might look like this:
That pattern is fine because the key stays server-side. It is not fine if you embed it in React props, environment variables exposed with a client prefix, or a public iframe query string.
OAuth: best when a human needs to authorize an external system
OAuth is often discussed as “login with Google,” but the real point is delegated authorization. A user signs in with an identity provider, your app receives an access token, and your backend exchanges that identity for your own session or internal permissions. For healthcare triage, OAuth is useful when the bot needs to act on behalf of a staff member, or when the application integrates with an external system that already speaks OAuth.
OAuth is not a replacement for your application authorization model. It answers “who is the user and what did they consent to?” not “should this particular triage action be allowed?” You still need role checks, tenant checks, and sometimes per-patient access controls in your own backend.
Use OAuth when:
The user is an operator, clinician, or administrator signing into your app.
You need third-party identity, SSO, or delegated access.
You are integrating with platforms that expect OAuth grants.
OAuth is usually overkill for anonymous patients starting a simple symptom checker. It adds redirect handling, token storage, refresh logic, and the possibility of confusing identity with authorization. In a Next.js app, that complexity is manageable, but you should only pay it when the problem actually needs delegated identity.
For React clients, the main rule is still the same: the browser should hold only short-lived access tokens, never client secrets. The backend should validate the identity provider token, then mint its own session or accept the user into a scoped workspace.
Signed tokens: the practical choice for browser sessions and realtime joins
Signed tokens are the workhorse for “I need the browser to prove it can join this exact session, for this exact time, with this exact scope.” They are compact, time-limited, and issued by your backend after it evaluates whatever policy you care about.
In a triage bot, signed tokens are especially useful for:
Joining a WebRTC or WebSocket session from the browser.
Authorizing a single patient conversation rather than your whole account.
Encoding expiration, audience, and session identifiers.
The general flow is:
User opens the Next.js app.
Your backend authenticates the user with your normal app auth, which may or may not be OAuth.
The backend checks whether the user can start a triage session.
The backend mints a short-lived signed token containing only the claims needed to join that one session.
The React client uses that token to connect to the realtime service.
This is a better fit than an API key because the browser never sees the long-lived secret. It is a better fit than OAuth for the actual session join because the token can be narrowly scoped and short-lived. For realtime media, that matters: the session authorization should expire on the same order of magnitude as the interaction, not on the order of days.
A practical token should include at least:
Subject or session identifier.
Audience or service name.
Expiration time.
Optional tenant or case identifier.
Do not overstuff it with PHI. A signed token is an authorization artifact, not a transport for clinical data.
How this maps to a Next.js and React triage bot
For a healthcare triage bot, a clean split usually looks like this:
Next.js backend: authenticates the user, enforces app rules, talks to internal systems, and mints short-lived tokens.
React frontend: requests a session, displays UI state, and uses the token to connect to realtime services.
External identity provider: optional, for staff login or enterprise SSO.
If the bot is patient-facing and anonymous, you can skip OAuth entirely and use your own session creation flow plus signed tokens. If staff are reviewing triage outcomes, OAuth becomes useful for login and role mapping. If your backend is simply creating sessions against a vendor API, an API key stays on the server and does the job well.
The biggest implementation mistake is letting the frontend do too much. A browser should not call your vendor API with a static credential, and it should not contain logic that decides whether a user can create a new session without a server-side check. In healthcare, even “low risk” shortcuts tend to become audit findings later.
Where Protoface fits: server-side session creation, not browser secrets
This is where Protoface fits cleanly into the architecture. Its REST API is authenticated with API keys, so your Next.js backend can create avatars and realtime sessions without exposing long-lived credentials to React. That makes it a reasonable building block when your triage bot needs a synchronized talking face attached to a voice agent.
For a server-side session creation flow, the pattern is the same as any other trusted backend integration:
If you are wiring the avatar into a voice agent, the LiveKit plugin keeps the auth boundary in the backend as well. The agent process uses the plugin, and the browser only receives whatever short-lived session material it needs to connect. See the plugin repository for examples: GitHub repo if you are using Pipecat, or the package page and docs for the LiveKit path. For implementation details, the authoritative reference is still the docs.
The important point is not the brand name of the auth mechanism. It is that the long-lived secret stays in the backend, while the browser gets only a session-scoped credential with a short TTL.
Common gotchas
Do not conflate authentication with authorization. OAuth tells you who the user is; your app still decides whether they can start, observe, or edit a triage session.
Do not embed API keys in React. If the browser can read it, assume it will leak eventually.
Do not make signed tokens long-lived. Realtime join tokens should expire quickly and be auditable.
Do not put PHI in client-visible claims unless you must. Keep tokens minimal.
Do not skip server-side checks just because a user has an identity provider token. Identity is not access.
Also remember that realtime systems have timing issues. Token expiry, reconnection, and retry behavior need to be designed together. If the token expires mid-session, your client should know whether to refresh, reconnect, or fail closed.
Conclusion
For a healthcare triage bot, the auth choice is usually not “one mechanism everywhere.” It is a layered design:
API keys for backend-to-backend calls.
OAuth for human login and delegated access when you need enterprise identity.
Signed tokens for short-lived browser access to a specific realtime session.
If you get those boundaries right, the rest of the system becomes simpler: your Next.js backend stays in control, your React app stays credential-light, and your realtime agent can join sessions without turning the browser into a secret store.
For implementation details and integration examples, start with the docs and the relevant quickstarts in the linked repositories. Then test your flow the way an attacker would: inspect the browser, replay a token, refresh a session, and make sure the system fails closed.
