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:
@@ -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 }
|
||||
|
||||
Reference in New Issue
Block a user