mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-24 09:11:13 -05:00
Implement Auth0 migration
This commit is contained in:
32
src/lib/auth0Config.ts
Normal file
32
src/lib/auth0Config.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Auth0 Configuration
|
||||
*
|
||||
* Centralized configuration for Auth0 authentication
|
||||
*/
|
||||
|
||||
export const auth0Config = {
|
||||
domain: import.meta.env.VITE_AUTH0_DOMAIN || '',
|
||||
clientId: import.meta.env.VITE_AUTH0_CLIENT_ID || '',
|
||||
authorizationParams: {
|
||||
redirect_uri: typeof window !== 'undefined' ? `${window.location.origin}/auth/callback` : '',
|
||||
audience: import.meta.env.VITE_AUTH0_DOMAIN ? `https://${import.meta.env.VITE_AUTH0_DOMAIN}/api/v2/` : '',
|
||||
scope: 'openid profile email'
|
||||
},
|
||||
cacheLocation: 'localstorage' as const,
|
||||
useRefreshTokens: true,
|
||||
useRefreshTokensFallback: true,
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if Auth0 is properly configured
|
||||
*/
|
||||
export function isAuth0Configured(): boolean {
|
||||
return !!(auth0Config.domain && auth0Config.clientId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Auth0 Management API audience
|
||||
*/
|
||||
export function getManagementAudience(): string {
|
||||
return `https://${auth0Config.domain}/api/v2/`;
|
||||
}
|
||||
138
src/lib/auth0Management.ts
Normal file
138
src/lib/auth0Management.ts
Normal file
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* Auth0 Management API Helper
|
||||
*
|
||||
* Provides helper functions to interact with Auth0 Management API
|
||||
*/
|
||||
|
||||
import { supabase } from '@/integrations/supabase/client';
|
||||
import type { Auth0MFAStatus, Auth0RoleInfo, ManagementTokenResponse } from '@/types/auth0';
|
||||
|
||||
/**
|
||||
* Get Auth0 Management API access token via edge function
|
||||
*/
|
||||
export async function getManagementToken(): Promise<string> {
|
||||
const { data, error } = await supabase.functions.invoke<ManagementTokenResponse>(
|
||||
'auth0-get-management-token',
|
||||
{ method: 'POST' }
|
||||
);
|
||||
|
||||
if (error || !data) {
|
||||
throw new Error('Failed to get management token: ' + (error?.message || 'Unknown error'));
|
||||
}
|
||||
|
||||
return data.access_token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user's MFA enrollment status
|
||||
*/
|
||||
export async function getMFAStatus(userId: string): Promise<Auth0MFAStatus> {
|
||||
try {
|
||||
const token = await getManagementToken();
|
||||
const domain = import.meta.env.VITE_AUTH0_DOMAIN;
|
||||
|
||||
const response = await fetch(`https://${domain}/api/v2/users/${userId}/enrollments`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch MFA status');
|
||||
}
|
||||
|
||||
const enrollments = await response.json();
|
||||
|
||||
return {
|
||||
enrolled: enrollments.length > 0,
|
||||
methods: enrollments.map((e: any) => ({
|
||||
id: e.id,
|
||||
type: e.type,
|
||||
name: e.name,
|
||||
confirmed: e.status === 'confirmed',
|
||||
})),
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error fetching MFA status:', error);
|
||||
return { enrolled: false, methods: [] };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user's roles from Auth0
|
||||
*/
|
||||
export async function getUserRoles(userId: string): Promise<Auth0RoleInfo[]> {
|
||||
try {
|
||||
const token = await getManagementToken();
|
||||
const domain = import.meta.env.VITE_AUTH0_DOMAIN;
|
||||
|
||||
const response = await fetch(`https://${domain}/api/v2/users/${userId}/roles`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch user roles');
|
||||
}
|
||||
|
||||
const roles = await response.json();
|
||||
|
||||
return roles.map((role: any) => ({
|
||||
id: role.id,
|
||||
name: role.name,
|
||||
description: role.description,
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error('Error fetching user roles:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user metadata
|
||||
*/
|
||||
export async function updateUserMetadata(
|
||||
userId: string,
|
||||
metadata: Record<string, any>
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
const token = await getManagementToken();
|
||||
const domain = import.meta.env.VITE_AUTH0_DOMAIN;
|
||||
|
||||
const response = await fetch(`https://${domain}/api/v2/users/${userId}`, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
user_metadata: metadata,
|
||||
}),
|
||||
});
|
||||
|
||||
return response.ok;
|
||||
} catch (error) {
|
||||
console.error('Error updating user metadata:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger MFA enrollment for user
|
||||
*/
|
||||
export async function triggerMFAEnrollment(redirectUri?: string): Promise<void> {
|
||||
const domain = import.meta.env.VITE_AUTH0_DOMAIN;
|
||||
const clientId = import.meta.env.VITE_AUTH0_CLIENT_ID;
|
||||
const redirect = redirectUri || `${window.location.origin}/settings`;
|
||||
|
||||
// Redirect to Auth0 MFA enrollment page
|
||||
window.location.href = `https://${domain}/authorize?` +
|
||||
`client_id=${clientId}&` +
|
||||
`response_type=code&` +
|
||||
`redirect_uri=${encodeURIComponent(redirect)}&` +
|
||||
`scope=openid profile email&` +
|
||||
`prompt=enroll`;
|
||||
}
|
||||
Reference in New Issue
Block a user