mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 21:21:10 +02:00
Applied formatting to 1487+ files using pnpm format:write - TypeScript/JavaScript files - Svelte components - Astro pages - JSON configs - Markdown docs 13 files still need manual review (Astro JSX comments)
147 lines
4.4 KiB
Markdown
147 lines
4.4 KiB
Markdown
# Edge Function Authentication Fix
|
|
|
|
## Problem
|
|
|
|
The Edge Function tries to validate Mana app tokens as Supabase JWTs using `supabase.auth.getUser()`, but Mana tokens are signed by a different Supabase project and need to be verified using the JWKS endpoint.
|
|
|
|
## Solution
|
|
|
|
Update the Edge Function to verify Mana tokens using the jose library and JWKS:
|
|
|
|
```typescript
|
|
import 'jsr:@supabase/functions-js/edge-runtime.d.ts';
|
|
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.39.3';
|
|
import * as jose from 'https://deno.land/x/jose@v5.9.6/index.ts';
|
|
|
|
const corsHeaders = {
|
|
'Access-Control-Allow-Origin': '*',
|
|
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
|
|
};
|
|
|
|
Deno.serve(async (req) => {
|
|
// Handle CORS preflight requests
|
|
if (req.method === 'OPTIONS') {
|
|
return new Response('ok', { headers: corsHeaders });
|
|
}
|
|
|
|
try {
|
|
// Get the authorization header
|
|
const authHeader = req.headers.get('Authorization');
|
|
if (!authHeader) {
|
|
throw new Error('No authorization header');
|
|
}
|
|
|
|
// Extract the Mana app token
|
|
const appToken = authHeader.replace('Bearer ', '');
|
|
|
|
// Get Mana Core JWKS URL from environment variable
|
|
// This should be: https://your-mana-project.supabase.co/auth/v1/.well-known/jwks.json
|
|
const manaJwksUrl = Deno.env.get('MANA_JWKS_URL');
|
|
if (!manaJwksUrl) {
|
|
throw new Error('MANA_JWKS_URL not configured');
|
|
}
|
|
|
|
// Verify the Mana token using JWKS
|
|
const JWKS = jose.createRemoteJWKSet(new URL(manaJwksUrl));
|
|
const { payload } = await jose.jwtVerify(appToken, JWKS);
|
|
|
|
const userId = payload.sub as string;
|
|
if (!userId) {
|
|
throw new Error('Invalid token: no user ID');
|
|
}
|
|
|
|
console.log(`Authenticated user: ${userId}`);
|
|
|
|
// Initialize Supabase client with service role
|
|
const supabaseUrl = Deno.env.get('SUPABASE_URL')!;
|
|
const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!;
|
|
const supabase = createClient(supabaseUrl, supabaseServiceKey);
|
|
|
|
// Use the userId from the Mana token
|
|
const user = { id: userId };
|
|
|
|
// Parse request body
|
|
const requestData = await req.json();
|
|
const {
|
|
prompt: userPrompt,
|
|
deckTitle,
|
|
deckDescription = '',
|
|
cardCount = 10,
|
|
cardTypes = ['flashcard', 'quiz'],
|
|
difficulty = 'intermediate',
|
|
tags = [],
|
|
} = requestData;
|
|
|
|
// Validate input
|
|
if (!userPrompt || !deckTitle) {
|
|
throw new Error('userPrompt and deckTitle are required');
|
|
}
|
|
if (cardCount < 1 || cardCount > 50) {
|
|
throw new Error('cardCount must be between 1 and 50');
|
|
}
|
|
|
|
// Continue with OpenAI call and rest of your existing function code...
|
|
} catch (error) {
|
|
console.error('Error in generate-deck function:', error);
|
|
return new Response(
|
|
JSON.stringify({
|
|
success: false,
|
|
error: error.message || 'Ein unerwarteter Fehler ist aufgetreten',
|
|
}),
|
|
{
|
|
headers: {
|
|
...corsHeaders,
|
|
'Content-Type': 'application/json',
|
|
},
|
|
status: error.message?.includes('authorization') ? 401 : 400,
|
|
}
|
|
);
|
|
}
|
|
});
|
|
```
|
|
|
|
## Critical: Disable Gateway JWT Verification
|
|
|
|
The Supabase Edge Gateway tries to validate JWTs before passing requests to your function. Since you're using Mana Core JWTs (not Manadeck JWTs), you need to disable this.
|
|
|
|
Create `supabase/functions/generate-deck/config.toml`:
|
|
|
|
```toml
|
|
# Disable automatic JWT verification by Supabase Edge Gateway
|
|
# We'll manually verify the Mana Core JWT inside the function
|
|
verify_jwt = false
|
|
```
|
|
|
|
Do the same for `generate-deck-from-image`:
|
|
|
|
```toml
|
|
# supabase/functions/generate-deck-from-image/config.toml
|
|
verify_jwt = false
|
|
```
|
|
|
|
## Environment Variables Needed
|
|
|
|
Add this to your Supabase Edge Function secrets:
|
|
|
|
```bash
|
|
# Get your Mana Core project reference from the Supabase dashboard
|
|
supabase secrets set MANA_JWKS_URL=https://zvwwwwtcmhnxcjiswrln.supabase.co/auth/v1/.well-known/jwks.json
|
|
```
|
|
|
|
Replace `zvwwwwtcmhnxcjiswrln` with your actual Mana Core Supabase project reference.
|
|
|
|
## How It Works
|
|
|
|
1. ✅ Receives Mana app token from Authorization header
|
|
2. ✅ Verifies token signature using Mana Core JWKS endpoint
|
|
3. ✅ Validates token expiration automatically (jose handles this)
|
|
4. ✅ Extracts user ID from verified token payload
|
|
5. ✅ Uses Supabase service role for database operations
|
|
6. ✅ Associates created decks with the correct user ID
|
|
|
|
## Benefits
|
|
|
|
- Properly validates asymmetric ECC P-256 signed JWTs
|
|
- Handles key rotation automatically via JWKS
|
|
- More secure than manual JWT decoding
|
|
- Works with Supabase's new JWT signing keys
|