This example demonstrates how to integrate the @profullstack/auth-system module into a browser-based web application. It provides a complete authentication system with user registration, login/logout, password reset, profile management, and API key management.
The browser integration example includes:
- AuthClient: A browser-friendly wrapper around the auth-system module
- Page Initializers: Functions to initialize different pages in the application
- Utilities: Helper functions for authentication status and token management
auth-client.js: Main client for browser integration with localStorage supportindex.js: Main entry point that exports all page initializers and utilitieslogin-page.js: Login page implementationregister-page.js: Registration page implementation with payment integrationsettings-page.js: Settings page with profile management and password changereset-password-page.js: Password reset functionalityapi-keys-page.js: API key managementutils/auth-status.js: Authentication status utilities
First, install the auth-system module:
npm install @profullstack/auth-systemThen copy the browser integration files to your project.
import { initApp, AuthClient } from './browser-integration/index.js';
// Initialize the application
document.addEventListener('DOMContentLoaded', async () => {
await initApp({
createGlobalAuthClient: true
});
});Use the page initializers in your router or page load handlers:
import { initLoginPage, initRegisterPage, initApiKeysPage, initSettingsPage, initResetPasswordPage } from './browser-integration/index.js';
// Set up router
const router = {
'/login': initLoginPage,
'/register': initRegisterPage,
'/api-keys': initApiKeysPage,
'/settings': initSettingsPage,
'/reset-password': initResetPasswordPage
};
// Initialize current page
const path = window.location.pathname;
if (router[path]) {
router[path]();
}Check authentication status:
import { checkAuthStatus } from './browser-integration/utils/auth-status.js';
async function checkIfLoggedIn() {
const status = await checkAuthStatus();
if (status.authenticated) {
console.log('User is logged in:', status.user);
} else {
console.log('User is not logged in');
window.location.href = '/login';
}
}You can also use the AuthClient directly:
import { AuthClient } from './browser-integration/auth-client.js';
async function createAuthClient() {
const authClient = new AuthClient({
supabaseUrl: 'https://your-project.supabase.co',
supabaseKey: 'your-anon-key',
jwtSecret: 'your-jwt-secret',
onAuthChanged: (authenticated, user) => {
console.log('Auth state changed:', authenticated, user);
}
});
return authClient;
}
async function loginUser(email, password) {
const authClient = await createAuthClient();
try {
const result = await authClient.login({ email, password });
console.log('Login successful:', result);
return result;
} catch (error) {
console.error('Login error:', error);
throw error;
}
}The example assumes the following HTML structure for each page:
<form id="login-form">
<input type="email" id="email" required>
<input type="password" id="password" required>
<button type="submit">Login</button>
</form>
<button id="check-auth-status">Check Auth Status</button>
<pre id="auth-status-result"></pre><form id="register-form">
<input type="email" id="email" required>
<input type="password" id="password" required>
<input type="password" id="confirm-password" required>
<div class="plan-options">
<div class="plan-option" data-plan="monthly">Monthly</div>
<div class="plan-option" data-plan="yearly">Yearly</div>
</div>
<div class="payment-methods">
<div class="payment-method" data-payment="btc">Bitcoin</div>
<div class="payment-method" data-payment="stripe">Stripe</div>
</div>
<button type="submit">Register & Subscribe</button>
</form><form id="profile-form">
<input type="email" id="profile-email" disabled>
<input type="text" id="profile-first-name">
<input type="text" id="profile-last-name">
<input type="tel" id="profile-phone">
<button type="submit">Update Profile</button>
</form>
<form id="password-form">
<input type="password" id="current-password" required>
<input type="password" id="new-password" required>
<input type="password" id="confirm-password" required>
<button type="submit">Change Password</button>
</form>
<div id="subscription-info"></div>
<button id="delete-account-button">Delete Account</button><h2 class="page-title">Reset Password</h2>
<p class="page-description">Enter your email to reset your password</p>
<form id="request-reset-form">
<input type="email" id="email" required>
<button type="submit">Request Reset</button>
</form>
<form id="confirm-reset-form" style="display: none;">
<input type="password" id="new-password" required>
<input type="password" id="confirm-password" required>
<button type="submit">Reset Password</button>
</form>
<form id="change-password-form" style="display: none;">
<input type="password" id="current-password" required>
<input type="password" id="new-password" required>
<input type="password" id="confirm-password" required>
<button type="submit">Change Password</button>
</form><div id="api-keys-container"></div>
<form id="create-api-key-form">
<input type="text" id="api-key-name" required>
<button type="submit">Create API Key</button>
</form>The example assumes the following server API endpoints:
/api/1/config/supabase: Returns Supabase configuration/api/1/auth/register: Registers a new user/api/1/subscriptions/status: Checks subscription status/api/1/subscriptions/create: Creates a subscription/api/1/api-keys: Gets and creates API keys/api/1/api-keys/:id: Revokes an API key/api/stripe-simple/create-checkout: Creates a Stripe checkout session
You can customize the AuthClient and page initializers to fit your application's needs. The example is designed to be modular and flexible, so you can use only the parts you need.
The example uses a custom dialog component (PfDialog) for displaying messages and confirmations. You'll need to implement this component or replace it with your own dialog implementation.
The example assumes a router object with a navigate method for page navigation. You'll need to implement this or replace it with your own routing solution.
MIT