Back to notes
Realtime securityChecklist5 min

Use ephemeral client secrets for browser Realtime sessions

A secure browser pattern for starting Realtime sessions without exposing your OpenAI API key.

Open source doc

Real workflow example

A browser-based voice intake screen needs to connect directly to a realtime model for low-latency audio. The tempting shortcut is to put the OpenAI API key in a client environment variable and connect from the browser. That works in a demo and fails as a security design.

The proper pattern is server-issued ephemeral credentials. The browser asks your app server to start a session. The server authenticates the user, checks workflow access, creates the scoped realtime session, and returns only a short-lived client secret.

Implementation approach

Treat session creation as a protected backend action. The server should know who is starting the session, which organization or workspace they belong to, what workflow they are allowed to run, and what session policy applies.

The browser should receive only the temporary credential and the minimal connection details it needs. Business actions still go through server routes or tools that validate authorization. When the call ends, clear local session state and mark the intake as complete, abandoned, or escalated.

Code or config snippet

// app/api/realtime/session/route.ts
export async function POST(request: Request) {
  const user = await requireUser(request);
  const body = await request.json();

  await assertCanStartVoiceIntake(user.id, body.workspaceId);

  const session = await openai.realtime.sessions.create({
    model: "gpt-4o-realtime-preview",
    voice: "alloy",
    instructions:
      "Collect intake facts. Do not make pricing commitments. Escalate when unsure.",
  });

  return Response.json({
    clientSecret: session.client_secret.value,
    expiresAt: session.client_secret.expires_at,
  });
}

Mistakes to avoid

  • Do not expose the long-lived OpenAI API key in a public environment variable.
  • Do not create realtime sessions before checking user access.
  • Do not put privileged business tools directly in browser code.
  • Do not reuse the same client secret across users or workflows.
  • Do not ignore expiration and cleanup states in the UI.

Ready checklist

  • Server route authenticates the current user.
  • Authorization checks the workspace and workflow.
  • Browser receives only a short-lived client secret.
  • Realtime instructions are scoped to the workflow.
  • Business actions remain server-side.
  • Session end and failure states clean up local state.

Practical tip

Log safe session metadata on the server: user ID, workspace ID, workflow name, session ID, start time, and end state. Do not log tokens, audio, or raw sensitive transcript text unless your retention policy explicitly allows it.

Practical note
A browser credential should be temporary and scoped.

The server owns identity, permissions, and session policy; the browser owns the live interaction.

Apply this to a build
Contact
Bring the product pressure, system constraints, and expected business outcome.
Send the desired outcome, users, current bottleneck, stack, and timeline. I will respond with a practical senior engineering path for the build.