fix: Use Deepgram grantToken() for secure temporary voice tokens

Updated the voice-token API route to use deepgram.auth.grantToken()
consistently in all environments. This generates secure 30-second
temporary tokens instead of exposing the main API key.

- Removed development/production split for consistency
- Now uses grantToken() method in all environments
- Requires API key with "Member" or higher permissions
- Improved security by using short-lived tokens
- Updated documentation to reflect new requirements

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-09 05:59:45 +00:00
parent 2b3cd0c99b
commit 5df6067dd2

View File

@@ -2,10 +2,14 @@ import { NextRequest, NextResponse } from 'next/server';
import { createClient } from '@deepgram/sdk';
/**
* This API route generates a short-lived, temporary API key
* This API route generates a short-lived, temporary access token
* for a client to connect directly to Deepgram's WebSocket.
* This avoids exposing our main API key and bypasses
* serverless WebSocket limitations.
*
* The temporary token has a 30-second TTL and provides better security
* than exposing the main API key. This approach also bypasses
* serverless WebSocket limitations by allowing direct client connections.
*
* Requires: API key with "Member" or higher permissions
*/
export async function POST(request: NextRequest) {
const deepgramApiKey = process.env.DEEPGRAM_API_KEY;
@@ -20,25 +24,24 @@ export async function POST(request: NextRequest) {
const deepgram = createClient(deepgramApiKey);
try {
// Create a new, temporary key with 'member' permissions
// that expires in 1 minute (60 seconds).
const response = await deepgram.manage.createProjectKey(
process.env.DEEPGRAM_PROJECT_ID || '',
{
comment: 'Temporary key for Ponderants user',
scopes: ['member'],
time_to_live_in_seconds: 60,
}
);
console.log('[Voice Token] Generating temporary token...');
const { result, error } = await deepgram.auth.grantToken();
if (!response || !response.key) {
throw new Error('Failed to create temporary key');
if (error) {
console.error('[Voice Token] Deepgram error:', error);
throw new Error(`Deepgram error: ${error.message}`);
}
// Send the temporary key back to the client
return NextResponse.json({ key: response.key });
if (!result || !result.access_token) {
console.error('[Voice Token] No token in response:', result);
throw new Error('No token in response');
}
console.log('[Voice Token] ✓ Token generated successfully');
console.log(`[Voice Token] Token expires in ${result.expires_in} seconds`);
return NextResponse.json({ key: result.access_token });
} catch (error) {
console.error('Error creating Deepgram key:', error);
console.error('[Voice Token] Error creating Deepgram token:', error);
return NextResponse.json(
{ error: 'Failed to generate voice token' },
{ status: 500 }