moxie-site/js/auth.js
Z User 2e693de7fa Add Auth0 authentication and user dashboard
- Add Auth0 SPA SDK integration for authentication
- Create login/logout flow with Auth0
- Add user dashboard page with:
  - Profile display and editing
  - Credits balance and transaction history
  - API key management (create/revoke)
  - Account settings
- Add API client for backend communication
- Update navbar with Login/Dashboard buttons
- Preserve existing landing page design

Configuration:
- Auth0 Domain: dev-t13zhs74oltgqtfxf.auth0.com
- API base: /api (proxied through Caddy)
2026-03-27 22:27:46 +00:00

177 lines
4.7 KiB
JavaScript

/**
* Moxiegen Authentication Module
* Handles Auth0 authentication, login/logout, and token management
*/
class MoxieAuth {
constructor() {
this.auth0Client = null;
this.isAuthenticated = false;
this.user = null;
this.token = null;
this.isInitialized = false;
}
/**
* Initialize Auth0 client
*/
async init() {
if (this.isInitialized) return;
try {
// Dynamically load Auth0 SPA SDK if not already loaded
if (typeof auth0 === 'undefined') {
await this.loadScript('https://cdn.auth0.com/js/auth0-spa-js/2.0/auth0-spa-js.production.js');
}
// Create Auth0 client
this.auth0Client = await auth0.createAuth0Client({
domain: CONFIG.auth0.domain,
clientId: CONFIG.auth0.clientId,
authorizationParams: {
audience: CONFIG.auth0.audience,
redirect_uri: CONFIG.auth0.redirectUri
},
cacheLocation: 'localstorage',
useRefreshTokens: true
});
// Check if coming back from Auth0 redirect
const query = window.location.search;
if (query.includes('code=') && query.includes('state=')) {
await this.auth0Client.handleRedirectCallback();
// Remove query params from URL
window.history.replaceState({}, document.title, window.location.pathname);
}
// Check authentication status
this.isAuthenticated = await this.auth0Client.isAuthenticated();
if (this.isAuthenticated) {
this.user = await this.auth0Client.getUser();
this.token = await this.auth0Client.getTokenSilently();
}
this.isInitialized = true;
console.log('Auth0 initialized. Authenticated:', this.isAuthenticated);
} catch (error) {
console.error('Failed to initialize Auth0:', error);
throw error;
}
}
/**
* Load external script
*/
loadScript(src) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = src;
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
}
/**
* Login - redirect to Auth0
*/
async login(returnTo = null) {
if (!this.auth0Client) {
await this.init();
}
await this.auth0Client.loginWithRedirect({
authorizationParams: {
audience: CONFIG.auth0.audience,
redirect_uri: returnTo || CONFIG.auth0.redirectUri
}
});
}
/**
* Logout
*/
async logout() {
if (!this.auth0Client) {
await this.init();
}
// Clear local state
this.isAuthenticated = false;
this.user = null;
this.token = null;
// Logout from Auth0
await this.auth0Client.logout({
logoutParams: {
returnTo: CONFIG.auth0.logoutUri
}
});
}
/**
* Get access token (silently refreshes if needed)
*/
async getToken() {
if (!this.auth0Client) {
await this.init();
}
if (!this.isAuthenticated) {
return null;
}
try {
this.token = await this.auth0Client.getTokenSilently();
return this.token;
} catch (error) {
console.error('Failed to get token:', error);
// Token might be expired, try to re-authenticate
this.isAuthenticated = false;
return null;
}
}
/**
* Get current user
*/
async getUser() {
if (!this.auth0Client) {
await this.init();
}
return this.user;
}
/**
* Check if user is authenticated
*/
async checkAuth() {
if (!this.auth0Client) {
await this.init();
}
this.isAuthenticated = await this.auth0Client.isAuthenticated();
if (this.isAuthenticated) {
this.user = await this.auth0Client.getUser();
this.token = await this.auth0Client.getTokenSilently();
}
return this.isAuthenticated;
}
/**
* Check if user has specific role
*/
hasRole(role) {
if (!this.user) return false;
const roles = this.user['https://moxiegen.client.guacamolebox.net/roles'] || [];
return roles.includes(role);
}
}
// Create singleton instance
const moxieAuth = new MoxieAuth();
// Export for use in other modules
window.moxieAuth = moxieAuth;