Update email cancellation and location detection functions

Refactor Supabase function to use explicit JWT verification via auth.getUser, and enhance the location detection function with configurable geolocation API endpoints.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 364fb426-1d27-49b2-a244-a34e41c335e4
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
This commit is contained in:
pac7
2025-10-08 12:32:19 +00:00
parent ce91c387bc
commit 32a83013e5
3 changed files with 30 additions and 49 deletions

View File

@@ -33,7 +33,3 @@ outputType = "webview"
[[ports]]
localPort = 5000
externalPort = 80
[[ports]]
localPort = 45303
externalPort = 3000

View File

@@ -5,31 +5,6 @@ const corsHeaders = {
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
};
// Helper function to decode JWT and extract user ID
// Properly handles base64url encoding used by JWTs
function decodeJWT(token: string): { sub: string } | null {
try {
const parts = token.split('.');
if (parts.length !== 3) return null;
// JWT uses base64url encoding, convert to standard base64
let base64 = parts[1].replace(/-/g, '+').replace(/_/g, '/');
// Add padding if needed
while (base64.length % 4) {
base64 += '=';
}
// Decode and parse the payload
const decoded = atob(base64);
const payload = JSON.parse(decoded);
return payload;
} catch (error) {
console.error('JWT decode error:', error);
return null;
}
}
Deno.serve(async (req) => {
// Handle CORS preflight requests
if (req.method === 'OPTIONS') {
@@ -37,18 +12,6 @@ Deno.serve(async (req) => {
}
try {
// Create admin client with service role key
const supabaseAdmin = createClient(
Deno.env.get('SUPABASE_URL') ?? '',
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? '',
{
auth: {
autoRefreshToken: false,
persistSession: false
}
}
);
// Get the user from the authorization header
const authHeader = req.headers.get('Authorization');
if (!authHeader) {
@@ -56,17 +19,35 @@ Deno.serve(async (req) => {
throw new Error('No authorization header provided. Please ensure you are logged in.');
}
// Extract the JWT token from the Authorization header
const token = authHeader.replace('Bearer ', '');
console.log('Extracting user ID from JWT token...');
// Create admin client with service role key (no user token in global headers)
// This ensures all DB operations run with full admin privileges
const supabaseUrl = Deno.env.get('SUPABASE_URL');
const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY');
// Parse JWT token to get user ID directly
const payload = decodeJWT(token);
if (!payload || !payload.sub) {
console.error('Invalid JWT token structure');
if (!supabaseUrl || !supabaseServiceKey) {
throw new Error('Missing Supabase configuration');
}
const supabaseAdmin = createClient(supabaseUrl, supabaseServiceKey, {
auth: {
autoRefreshToken: false,
persistSession: false
}
});
// Verify the user's JWT token by passing it explicitly to getUser()
// Note: verify_jwt = true in config.toml means Supabase has already validated the JWT
const { data: { user }, error: authError } = await supabaseAdmin.auth.getUser(token);
if (authError || !user) {
console.error('Auth verification failed:', authError);
throw new Error('Invalid session token. Please refresh the page and try again.');
}
const userId = payload.sub;
const userId = user.id;
console.log(`Cancelling email change for user ${userId}`);
// Call the database function to clear email change fields

View File

@@ -25,10 +25,14 @@ serve(async (req) => {
console.log('Detecting location for IP:', clientIP);
// Use a free IP geolocation service with proper error handling
// Use configurable geolocation service with proper error handling
// Defaults to ip-api.com if not configured
const geoApiUrl = Deno.env.get('GEOLOCATION_API_URL') || 'http://ip-api.com/json';
const geoApiFields = Deno.env.get('GEOLOCATION_API_FIELDS') || 'status,country,countryCode';
let geoResponse;
try {
geoResponse = await fetch(`http://ip-api.com/json/${clientIP}?fields=status,country,countryCode`);
geoResponse = await fetch(`${geoApiUrl}/${clientIP}?fields=${geoApiFields}`);
} catch (fetchError) {
console.error('Network error fetching location data:', fetchError);
throw new Error('Network error: Unable to reach geolocation service');