mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-20 06:23:40 +02:00
refactor(auth): standardize URL resolution and token handling across all web auth stores
Align all 20 web app auth stores to a consistent pattern: - Use DEV_* constants with import.meta.env.DEV guard (no localhost leak in prod) - Pass backendUrl to initializeWebAuth for automatic 401 token refresh - Add redirectTo to forgotPassword for correct post-reset redirect Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f71e7d371b
commit
241cb3332a
20 changed files with 528 additions and 300 deletions
|
|
@ -4,20 +4,21 @@
|
|||
*/
|
||||
|
||||
import { browser } from '$app/environment';
|
||||
import { initializeWebAuth } from '@manacore/shared-auth';
|
||||
import type { UserData } from '@manacore/shared-auth';
|
||||
import { initializeWebAuth, type UserData } from '@manacore/shared-auth';
|
||||
|
||||
// Default URLs for local development only
|
||||
const DEV_AUTH_URL = 'http://localhost:3001';
|
||||
const DEV_BACKEND_URL = 'http://localhost:3014';
|
||||
|
||||
// Get auth URL dynamically at runtime - fallback for SSR and client
|
||||
function getAuthUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
// Client-side: use injected window variable (set by hooks.server.ts)
|
||||
// Falls back to localhost for local development
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string })
|
||||
.__PUBLIC_MANA_CORE_AUTH_URL__;
|
||||
return injectedUrl || 'http://localhost:3001';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_AUTH_URL : '';
|
||||
}
|
||||
// Server-side (SSR): use Docker internal URL for container-to-container communication
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || DEV_AUTH_URL;
|
||||
}
|
||||
|
||||
// Get backend URL dynamically at runtime
|
||||
|
|
@ -25,9 +26,10 @@ function getBackendUrl(): string {
|
|||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
|
||||
.__PUBLIC_BACKEND_URL__;
|
||||
return injectedUrl || 'http://localhost:3014';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_BACKEND_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_BACKEND_URL || 'http://localhost:3014';
|
||||
return process.env.PUBLIC_BACKEND_URL || DEV_BACKEND_URL;
|
||||
}
|
||||
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
|
|
@ -39,7 +41,7 @@ function getAuthService() {
|
|||
if (!_authService) {
|
||||
const auth = initializeWebAuth({
|
||||
baseUrl: getAuthUrl(),
|
||||
backendUrl: getBackendUrl(), // Enables automatic token refresh on 401 responses
|
||||
backendUrl: getBackendUrl(),
|
||||
});
|
||||
_authService = auth.authService;
|
||||
_tokenManager = auth.tokenManager;
|
||||
|
|
|
|||
|
|
@ -4,20 +4,21 @@
|
|||
*/
|
||||
|
||||
import { browser } from '$app/environment';
|
||||
import { initializeWebAuth } from '@manacore/shared-auth';
|
||||
import type { UserData } from '@manacore/shared-auth';
|
||||
import { initializeWebAuth, type UserData } from '@manacore/shared-auth';
|
||||
|
||||
// Default URLs for local development only
|
||||
const DEV_AUTH_URL = 'http://localhost:3001';
|
||||
const DEV_BACKEND_URL = 'http://localhost:3002';
|
||||
|
||||
// Get auth URL dynamically at runtime - fallback for SSR and client
|
||||
function getAuthUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
// Client-side: use injected window variable (set by hooks.server.ts)
|
||||
// Falls back to localhost for local development
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string })
|
||||
.__PUBLIC_MANA_CORE_AUTH_URL__;
|
||||
return injectedUrl || 'http://localhost:3001';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_AUTH_URL : '';
|
||||
}
|
||||
// Server-side (SSR): use Docker internal URL for container-to-container communication
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || DEV_AUTH_URL;
|
||||
}
|
||||
|
||||
// Get backend URL dynamically at runtime
|
||||
|
|
@ -25,9 +26,10 @@ function getBackendUrl(): string {
|
|||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
|
||||
.__PUBLIC_BACKEND_URL__;
|
||||
return injectedUrl || 'http://localhost:3002';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_BACKEND_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_BACKEND_URL || 'http://localhost:3002';
|
||||
return process.env.PUBLIC_BACKEND_URL || DEV_BACKEND_URL;
|
||||
}
|
||||
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
|
|
@ -136,7 +138,7 @@ export const authStore = {
|
|||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
|
||||
return { success: true, error: null };
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||
return { success: false, error: errorMessage };
|
||||
|
|
@ -163,7 +165,7 @@ export const authStore = {
|
|||
|
||||
// Mana Core Auth requires separate login after signup
|
||||
if (result.needsVerification) {
|
||||
return { success: true, error: null, needsVerification: true };
|
||||
return { success: true, needsVerification: true };
|
||||
}
|
||||
|
||||
// Auto sign in after successful signup
|
||||
|
|
@ -205,13 +207,14 @@ export const authStore = {
|
|||
}
|
||||
|
||||
try {
|
||||
const result = await authService.forgotPassword(email);
|
||||
const redirectTo = browser ? window.location.origin : undefined;
|
||||
const result = await authService.forgotPassword(email, redirectTo);
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Password reset failed' };
|
||||
}
|
||||
|
||||
return { success: true, error: null };
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||
return { success: false, error: errorMessage };
|
||||
|
|
|
|||
|
|
@ -7,22 +7,28 @@ import { browser } from '$app/environment';
|
|||
import { initializeWebAuth } from '@manacore/shared-auth';
|
||||
import type { UserData } from '@manacore/shared-auth';
|
||||
|
||||
// Default URLs for local development only
|
||||
const DEV_AUTH_URL = 'http://localhost:3001';
|
||||
const DEV_BACKEND_URL = 'http://localhost:3025';
|
||||
|
||||
function getAuthUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string })
|
||||
.__PUBLIC_MANA_CORE_AUTH_URL__;
|
||||
return injectedUrl || 'http://localhost:3001';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_AUTH_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || DEV_AUTH_URL;
|
||||
}
|
||||
|
||||
function getBackendUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
|
||||
.__PUBLIC_BACKEND_URL__;
|
||||
return injectedUrl || 'http://localhost:3025';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_BACKEND_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_BACKEND_URL || 'http://localhost:3025';
|
||||
return process.env.PUBLIC_BACKEND_URL || DEV_BACKEND_URL;
|
||||
}
|
||||
|
||||
let _authService: ReturnType<typeof initializeWebAuth>['authService'] | null = null;
|
||||
|
|
@ -168,7 +174,8 @@ export const authStore = {
|
|||
}
|
||||
|
||||
try {
|
||||
const result = await authService.forgotPassword(email);
|
||||
const redirectTo = browser ? window.location.origin : undefined;
|
||||
const result = await authService.forgotPassword(email, redirectTo);
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Password reset failed' };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,17 +6,19 @@
|
|||
import { browser } from '$app/environment';
|
||||
import { initializeWebAuth, type UserData } from '@manacore/shared-auth';
|
||||
|
||||
// Default URLs for local development only
|
||||
const DEV_AUTH_URL = 'http://localhost:3001';
|
||||
const DEV_BACKEND_URL = 'http://localhost:3017';
|
||||
|
||||
// Get auth URL dynamically at runtime - fallback for SSR and client
|
||||
function getAuthUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
// Client-side: use injected window variable (set by hooks.server.ts)
|
||||
// Falls back to localhost for local development
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string })
|
||||
.__PUBLIC_MANA_CORE_AUTH_URL__;
|
||||
return injectedUrl || 'http://localhost:3001';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_AUTH_URL : '';
|
||||
}
|
||||
// Server-side (SSR): use Docker internal URL for container-to-container communication
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || DEV_AUTH_URL;
|
||||
}
|
||||
|
||||
// Get backend URL dynamically at runtime
|
||||
|
|
@ -24,9 +26,10 @@ function getBackendUrl(): string {
|
|||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
|
||||
.__PUBLIC_BACKEND_URL__;
|
||||
return injectedUrl || 'http://localhost:3017';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_BACKEND_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_BACKEND_URL || 'http://localhost:3017';
|
||||
return process.env.PUBLIC_BACKEND_URL || DEV_BACKEND_URL;
|
||||
}
|
||||
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
|
|
@ -204,7 +207,8 @@ export const authStore = {
|
|||
}
|
||||
|
||||
try {
|
||||
const result = await authService.forgotPassword(email);
|
||||
const redirectTo = browser ? window.location.origin : undefined;
|
||||
const result = await authService.forgotPassword(email, redirectTo);
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Password reset failed' };
|
||||
|
|
|
|||
|
|
@ -4,20 +4,21 @@
|
|||
*/
|
||||
|
||||
import { browser } from '$app/environment';
|
||||
import { initializeWebAuth } from '@manacore/shared-auth';
|
||||
import type { UserData } from '@manacore/shared-auth';
|
||||
import { initializeWebAuth, type UserData } from '@manacore/shared-auth';
|
||||
|
||||
// Default URLs for local development only
|
||||
const DEV_AUTH_URL = 'http://localhost:3001';
|
||||
const DEV_BACKEND_URL = 'http://localhost:3015';
|
||||
|
||||
// Get auth URL dynamically at runtime - fallback for SSR and client
|
||||
function getAuthUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
// Client-side: use injected window variable (set by hooks.server.ts)
|
||||
// Falls back to localhost for local development
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string })
|
||||
.__PUBLIC_MANA_CORE_AUTH_URL__;
|
||||
return injectedUrl || 'http://localhost:3001';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_AUTH_URL : '';
|
||||
}
|
||||
// Server-side (SSR): use Docker internal URL for container-to-container communication
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || DEV_AUTH_URL;
|
||||
}
|
||||
|
||||
// Get backend URL dynamically at runtime
|
||||
|
|
@ -25,9 +26,10 @@ function getBackendUrl(): string {
|
|||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
|
||||
.__PUBLIC_BACKEND_URL__;
|
||||
return injectedUrl || 'http://localhost:3015';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_BACKEND_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_BACKEND_URL || 'http://localhost:3015';
|
||||
return process.env.PUBLIC_BACKEND_URL || DEV_BACKEND_URL;
|
||||
}
|
||||
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
|
|
@ -205,7 +207,8 @@ export const authStore = {
|
|||
}
|
||||
|
||||
try {
|
||||
const result = await authService.forgotPassword(email);
|
||||
const redirectTo = browser ? window.location.origin : undefined;
|
||||
const result = await authService.forgotPassword(email, redirectTo);
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Password reset failed' };
|
||||
|
|
|
|||
|
|
@ -6,14 +6,28 @@
|
|||
import { browser } from '$app/environment';
|
||||
import { initializeWebAuth, type UserData } from '@manacore/shared-auth';
|
||||
|
||||
// Get auth URL dynamically at runtime - fallback for SSR and client
|
||||
// Default URLs for local development only
|
||||
const DEV_AUTH_URL = 'http://localhost:3001';
|
||||
const DEV_BACKEND_URL = 'http://localhost:3020';
|
||||
|
||||
function getAuthUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string })
|
||||
.__PUBLIC_MANA_CORE_AUTH_URL__;
|
||||
return injectedUrl || 'http://localhost:3001';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_AUTH_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || DEV_AUTH_URL;
|
||||
}
|
||||
|
||||
function getBackendUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
|
||||
.__PUBLIC_BACKEND_URL__;
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_BACKEND_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_BACKEND_URL || DEV_BACKEND_URL;
|
||||
}
|
||||
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
|
|
@ -25,6 +39,7 @@ function getAuthService() {
|
|||
if (!_authService) {
|
||||
const auth = initializeWebAuth({
|
||||
baseUrl: getAuthUrl(),
|
||||
backendUrl: getBackendUrl(),
|
||||
});
|
||||
_authService = auth.authService;
|
||||
_tokenManager = auth.tokenManager;
|
||||
|
|
@ -163,7 +178,8 @@ export const authStore = {
|
|||
}
|
||||
|
||||
try {
|
||||
const result = await authService.forgotPassword(email);
|
||||
const redirectTo = browser ? window.location.origin : undefined;
|
||||
const result = await authService.forgotPassword(email, redirectTo);
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Password reset failed' };
|
||||
|
|
|
|||
|
|
@ -4,20 +4,20 @@
|
|||
*/
|
||||
|
||||
import { browser } from '$app/environment';
|
||||
import { initializeWebAuth } from '@manacore/shared-auth';
|
||||
import type { UserData } from '@manacore/shared-auth';
|
||||
import { initializeWebAuth, type UserData } from '@manacore/shared-auth';
|
||||
|
||||
// Default URL for local development only
|
||||
const DEV_AUTH_URL = 'http://localhost:3001';
|
||||
|
||||
// Get auth URL dynamically at runtime - fallback for SSR and client
|
||||
function getAuthUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
// Client-side: use injected window variable (set by hooks.server.ts)
|
||||
// Falls back to localhost for local development
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string })
|
||||
.__PUBLIC_MANA_CORE_AUTH_URL__;
|
||||
return injectedUrl || 'http://localhost:3001';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_AUTH_URL : '';
|
||||
}
|
||||
// Server-side (SSR): use Docker internal URL for container-to-container communication
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || DEV_AUTH_URL;
|
||||
}
|
||||
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
|
|
@ -203,7 +203,8 @@ export const authStore = {
|
|||
}
|
||||
|
||||
try {
|
||||
const result = await authService.forgotPassword(email);
|
||||
const redirectTo = browser ? window.location.origin : undefined;
|
||||
const result = await authService.forgotPassword(email, redirectTo);
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Password reset failed' };
|
||||
|
|
|
|||
|
|
@ -123,7 +123,8 @@ export const authStore = {
|
|||
* Send password reset email
|
||||
*/
|
||||
async forgotPassword(email: string) {
|
||||
return authService.forgotPassword(email);
|
||||
const redirectTo = browser ? window.location.origin : undefined;
|
||||
return authService.forgotPassword(email, redirectTo);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7,24 +7,28 @@ import { browser } from '$app/environment';
|
|||
import { initializeWebAuth } from '@manacore/shared-auth';
|
||||
import type { UserData } from '@manacore/shared-auth';
|
||||
|
||||
// Get auth URL dynamically at runtime - fallback for SSR and client
|
||||
// Default URLs for local development only
|
||||
const DEV_AUTH_URL = 'http://localhost:3001';
|
||||
const DEV_BACKEND_URL = 'http://localhost:3010';
|
||||
|
||||
function getAuthUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string })
|
||||
.__PUBLIC_MANA_CORE_AUTH_URL__;
|
||||
return injectedUrl || 'http://localhost:3001';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_AUTH_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || DEV_AUTH_URL;
|
||||
}
|
||||
|
||||
// Get backend URL dynamically at runtime
|
||||
function getBackendUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
|
||||
.__PUBLIC_BACKEND_URL__;
|
||||
return injectedUrl || 'http://localhost:3010';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_BACKEND_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_BACKEND_URL || 'http://localhost:3010';
|
||||
return process.env.PUBLIC_BACKEND_URL || DEV_BACKEND_URL;
|
||||
}
|
||||
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
|
|
@ -196,8 +200,8 @@ export const authStore = {
|
|||
}
|
||||
|
||||
try {
|
||||
const sourceAppUrl = browser ? window.location.origin : undefined;
|
||||
const result = await authService.forgotPassword(email, sourceAppUrl);
|
||||
const redirectTo = browser ? window.location.origin : undefined;
|
||||
const result = await authService.forgotPassword(email, redirectTo);
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Failed to send reset email' };
|
||||
|
|
|
|||
|
|
@ -7,27 +7,28 @@ import { browser } from '$app/environment';
|
|||
import { initializeWebAuth } from '@manacore/shared-auth';
|
||||
import type { UserData } from '@manacore/shared-auth';
|
||||
|
||||
// Get auth URL dynamically at runtime - fallback for SSR and client
|
||||
// Default URLs for local development only
|
||||
const DEV_AUTH_URL = 'http://localhost:3001';
|
||||
const DEV_BACKEND_URL = 'http://localhost:3023';
|
||||
|
||||
function getAuthUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
// Client-side: use injected window variable (set by hooks.server.ts)
|
||||
// Falls back to localhost for local development
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string })
|
||||
.__PUBLIC_MANA_CORE_AUTH_URL__;
|
||||
return injectedUrl || 'http://localhost:3001';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_AUTH_URL : '';
|
||||
}
|
||||
// Server-side (SSR): use Docker internal URL for container-to-container communication
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || DEV_AUTH_URL;
|
||||
}
|
||||
|
||||
// Get backend URL dynamically at runtime
|
||||
function getBackendUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
|
||||
.__PUBLIC_BACKEND_URL__;
|
||||
return injectedUrl || 'http://localhost:3023';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_BACKEND_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_BACKEND_URL || 'http://localhost:3023';
|
||||
return process.env.PUBLIC_BACKEND_URL || DEV_BACKEND_URL;
|
||||
}
|
||||
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
|
|
@ -202,7 +203,8 @@ export const authStore = {
|
|||
}
|
||||
|
||||
try {
|
||||
const result = await authService.forgotPassword(email);
|
||||
const redirectTo = browser ? window.location.origin : undefined;
|
||||
const result = await authService.forgotPassword(email, redirectTo);
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Password reset failed' };
|
||||
|
|
|
|||
|
|
@ -7,24 +7,28 @@ import { browser } from '$app/environment';
|
|||
import { initializeWebAuth } from '@manacore/shared-auth';
|
||||
import type { UserData } from '@manacore/shared-auth';
|
||||
|
||||
// Get auth URL dynamically at runtime
|
||||
// Default URLs for local development only
|
||||
const DEV_AUTH_URL = 'http://localhost:3001';
|
||||
const DEV_BACKEND_URL = 'http://localhost:3019';
|
||||
|
||||
function getAuthUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string })
|
||||
.__PUBLIC_MANA_CORE_AUTH_URL__;
|
||||
return injectedUrl || 'http://localhost:3001';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_AUTH_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || DEV_AUTH_URL;
|
||||
}
|
||||
|
||||
// Get backend URL dynamically at runtime
|
||||
function getBackendUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
|
||||
.__PUBLIC_BACKEND_URL__;
|
||||
return injectedUrl || 'http://localhost:3019';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_BACKEND_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_BACKEND_URL || 'http://localhost:3019';
|
||||
return process.env.PUBLIC_BACKEND_URL || DEV_BACKEND_URL;
|
||||
}
|
||||
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
|
|
@ -177,7 +181,8 @@ export const authStore = {
|
|||
}
|
||||
|
||||
try {
|
||||
const result = await authService.forgotPassword(email);
|
||||
const redirectTo = browser ? window.location.origin : undefined;
|
||||
const result = await authService.forgotPassword(email, redirectTo);
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Password reset failed' };
|
||||
|
|
|
|||
|
|
@ -1,52 +1,57 @@
|
|||
/**
|
||||
* Auth Store - Manages authentication state using Svelte 5 runes
|
||||
* Now using Mana Core Auth instead of Supabase Auth
|
||||
* Uses Mana Core Auth
|
||||
*/
|
||||
|
||||
import { browser } from '$app/environment';
|
||||
import { env } from '$env/dynamic/public';
|
||||
import { initializeWebAuth, type UserData } from '@manacore/shared-auth';
|
||||
|
||||
const MANA_AUTH_URL = env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
const BACKEND_URL = env.PUBLIC_BACKEND_URL || 'http://localhost:3006';
|
||||
// Default URLs for local development only
|
||||
const DEV_AUTH_URL = 'http://localhost:3001';
|
||||
const DEV_BACKEND_URL = 'http://localhost:3006';
|
||||
|
||||
export interface UserData {
|
||||
id: string;
|
||||
email: string;
|
||||
role?: string;
|
||||
// Get auth URL dynamically at runtime - fallback for SSR and client
|
||||
function getAuthUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string })
|
||||
.__PUBLIC_MANA_CORE_AUTH_URL__;
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_AUTH_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || DEV_AUTH_URL;
|
||||
}
|
||||
|
||||
interface AuthResult {
|
||||
success: boolean;
|
||||
error?: string;
|
||||
// Get backend URL dynamically at runtime
|
||||
function getBackendUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
|
||||
.__PUBLIC_BACKEND_URL__;
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_BACKEND_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_BACKEND_URL || DEV_BACKEND_URL;
|
||||
}
|
||||
|
||||
// Internal auth service reference
|
||||
let _authService: any = null;
|
||||
let _tokenManager: any = null;
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
let _authService: ReturnType<typeof initializeWebAuth>['authService'] | null = null;
|
||||
let _tokenManager: ReturnType<typeof initializeWebAuth>['tokenManager'] | null = null;
|
||||
|
||||
async function getAuthService() {
|
||||
function getAuthService() {
|
||||
if (!browser) return null;
|
||||
if (!_authService) {
|
||||
try {
|
||||
const { initializeWebAuth } = await import('@manacore/shared-auth');
|
||||
const auth = initializeWebAuth({
|
||||
baseUrl: MANA_AUTH_URL,
|
||||
backendUrl: BACKEND_URL, // Enables automatic token refresh on 401 responses
|
||||
});
|
||||
_authService = auth.authService;
|
||||
_tokenManager = auth.tokenManager;
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize auth service:', error);
|
||||
return null;
|
||||
}
|
||||
const auth = initializeWebAuth({
|
||||
baseUrl: getAuthUrl(),
|
||||
backendUrl: getBackendUrl(),
|
||||
});
|
||||
_authService = auth.authService;
|
||||
_tokenManager = auth.tokenManager;
|
||||
}
|
||||
return _authService;
|
||||
}
|
||||
|
||||
async function getTokenManager() {
|
||||
function getTokenManager() {
|
||||
if (!browser) return null;
|
||||
// Ensure auth service is initialized first
|
||||
await getAuthService();
|
||||
getAuthService();
|
||||
return _tokenManager;
|
||||
}
|
||||
|
||||
|
|
@ -69,158 +74,174 @@ export const authStore = {
|
|||
return initialized;
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize auth state from stored tokens
|
||||
* Also tries SSO if no local tokens exist (cross-domain authentication)
|
||||
*/
|
||||
async initialize() {
|
||||
if (!browser || initialized) return;
|
||||
if (initialized) return;
|
||||
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
initialized = true;
|
||||
loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
loading = true;
|
||||
|
||||
try {
|
||||
const authService = await getAuthService();
|
||||
if (authService) {
|
||||
// First, check if we have valid local tokens
|
||||
let authenticated = await authService.isAuthenticated();
|
||||
// First, check if we have valid local tokens
|
||||
let authenticated = await authService.isAuthenticated();
|
||||
|
||||
// If not authenticated locally, try SSO (shared session cookie)
|
||||
if (!authenticated) {
|
||||
console.log('No local tokens, trying SSO...');
|
||||
const ssoResult = await authService.trySSO();
|
||||
if (ssoResult.success) {
|
||||
console.log('SSO successful, user authenticated via shared session');
|
||||
authenticated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticated) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
// If not authenticated locally, try SSO (shared session cookie)
|
||||
if (!authenticated) {
|
||||
console.log('No local tokens, trying SSO...');
|
||||
const ssoResult = await authService.trySSO();
|
||||
if (ssoResult.success) {
|
||||
console.log('SSO successful, user authenticated via shared session');
|
||||
authenticated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticated) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
}
|
||||
initialized = true;
|
||||
} catch (error) {
|
||||
console.error('Auth initialization error:', error);
|
||||
console.error('Failed to initialize auth:', error);
|
||||
user = null;
|
||||
} finally {
|
||||
loading = false;
|
||||
initialized = true;
|
||||
}
|
||||
},
|
||||
|
||||
async signIn(email: string, password: string): Promise<AuthResult> {
|
||||
const authService = await getAuthService();
|
||||
/**
|
||||
* Sign in with email and password
|
||||
*/
|
||||
async signIn(email: string, password: string) {
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
return { success: false, error: 'Auth service not available' };
|
||||
return { success: false, error: 'Auth not available on server' };
|
||||
}
|
||||
|
||||
try {
|
||||
loading = true;
|
||||
const result = await authService.signIn(email, password);
|
||||
|
||||
if (result.success) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
return { success: true };
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Login failed' };
|
||||
}
|
||||
|
||||
return { success: false, error: result.error || 'Login failed' };
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Login failed',
|
||||
};
|
||||
} finally {
|
||||
loading = false;
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||
return { success: false, error: errorMessage };
|
||||
}
|
||||
},
|
||||
|
||||
async signUp(email: string, password: string): Promise<AuthResult> {
|
||||
const authService = await getAuthService();
|
||||
/**
|
||||
* Sign up with email and password
|
||||
*/
|
||||
async signUp(email: string, password: string) {
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
return { success: false, error: 'Auth service not available' };
|
||||
return { success: false, error: 'Auth not available on server', needsVerification: false };
|
||||
}
|
||||
|
||||
try {
|
||||
loading = true;
|
||||
// Pass the current app URL for post-verification redirect
|
||||
const sourceAppUrl = browser ? window.location.origin : undefined;
|
||||
const result = await authService.signUp(email, password, sourceAppUrl);
|
||||
|
||||
if (result.success) {
|
||||
// Auto-login after signup
|
||||
const signInResult = await this.signIn(email, password);
|
||||
return signInResult;
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Signup failed', needsVerification: false };
|
||||
}
|
||||
|
||||
return { success: false, error: result.error || 'Signup failed' };
|
||||
if (result.needsVerification) {
|
||||
return { success: true, needsVerification: true };
|
||||
}
|
||||
|
||||
const signInResult = await this.signIn(email, password);
|
||||
return { ...signInResult, needsVerification: false };
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Signup failed',
|
||||
};
|
||||
} finally {
|
||||
loading = false;
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||
return { success: false, error: errorMessage, needsVerification: false };
|
||||
}
|
||||
},
|
||||
|
||||
async signOut(): Promise<void> {
|
||||
const authService = await getAuthService();
|
||||
if (authService) {
|
||||
try {
|
||||
await authService.signOut();
|
||||
} catch (error) {
|
||||
console.error('Sign out error:', error);
|
||||
}
|
||||
}
|
||||
user = null;
|
||||
},
|
||||
|
||||
async resetPassword(email: string): Promise<AuthResult> {
|
||||
const authService = await getAuthService();
|
||||
/**
|
||||
* Sign out
|
||||
*/
|
||||
async signOut() {
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
return { success: false, error: 'Auth service not available' };
|
||||
user = null;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await authService.forgotPassword(email);
|
||||
return {
|
||||
success: result.success,
|
||||
error: result.error,
|
||||
};
|
||||
await authService.signOut();
|
||||
user = null;
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Password reset failed',
|
||||
};
|
||||
console.error('Sign out error:', error);
|
||||
user = null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get access token for API calls (raw token, no refresh)
|
||||
* @deprecated Use getValidToken() instead for automatic refresh
|
||||
* Send password reset email
|
||||
*/
|
||||
async getAccessToken(): Promise<string | null> {
|
||||
const authService = await getAuthService();
|
||||
if (!authService) return null;
|
||||
return authService.getAppToken();
|
||||
async resetPassword(email: string) {
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
return { success: false, error: 'Auth not available on server' };
|
||||
}
|
||||
|
||||
try {
|
||||
const redirectTo = browser ? window.location.origin : undefined;
|
||||
const result = await authService.forgotPassword(email, redirectTo);
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Password reset failed' };
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||
return { success: false, error: errorMessage };
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a valid access token for API calls
|
||||
* Automatically refreshes if the token is expired or about to expire
|
||||
* Reset password with token (from reset email link)
|
||||
*/
|
||||
async getValidToken(): Promise<string | null> {
|
||||
const tokenManager = await getTokenManager();
|
||||
if (!tokenManager) {
|
||||
return null;
|
||||
async resetPasswordWithToken(token: string, newPassword: string) {
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
return { success: false, error: 'Auth not available on server' };
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await authService.resetPassword(token, newPassword);
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Failed to reset password' };
|
||||
}
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||
return { success: false, error: errorMessage };
|
||||
}
|
||||
return await tokenManager.getValidToken();
|
||||
},
|
||||
|
||||
/**
|
||||
* Resend verification email
|
||||
*/
|
||||
async resendVerificationEmail(email: string) {
|
||||
const authService = await getAuthService();
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
return { success: false, error: 'Auth service not available' };
|
||||
return { success: false, error: 'Auth not available on server' };
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -233,28 +254,32 @@ export const authStore = {
|
|||
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Failed to resend verification email',
|
||||
};
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||
return { success: false, error: errorMessage };
|
||||
}
|
||||
},
|
||||
|
||||
// For compatibility with old code that reads user store directly
|
||||
setUser(userData: UserData | null) {
|
||||
user = userData;
|
||||
/**
|
||||
* Get access token for API calls (raw token, no refresh)
|
||||
* @deprecated Use getValidToken() instead for automatic refresh
|
||||
*/
|
||||
async getAccessToken() {
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
return null;
|
||||
}
|
||||
return await authService.getAppToken();
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a valid access token for API calls
|
||||
* Automatically refreshes if the token is expired or about to expire
|
||||
*/
|
||||
async getValidToken(): Promise<string | null> {
|
||||
const tokenManager = getTokenManager();
|
||||
if (!tokenManager) {
|
||||
return null;
|
||||
}
|
||||
return await tokenManager.getValidToken();
|
||||
},
|
||||
};
|
||||
|
||||
// Export individual reactive getters for backward compatibility
|
||||
export function getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
export function getLoading() {
|
||||
return loading;
|
||||
}
|
||||
|
||||
export function getIsAuthenticated() {
|
||||
return !!user;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,24 +7,28 @@ import { browser } from '$app/environment';
|
|||
import { initializeWebAuth } from '@manacore/shared-auth';
|
||||
import type { UserData } from '@manacore/shared-auth';
|
||||
|
||||
// Get auth URL dynamically at runtime
|
||||
// Default URLs for local development only
|
||||
const DEV_AUTH_URL = 'http://localhost:3001';
|
||||
const DEV_BACKEND_URL = 'http://localhost:3022';
|
||||
|
||||
function getAuthUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string })
|
||||
.__PUBLIC_MANA_CORE_AUTH_URL__;
|
||||
return injectedUrl || 'http://localhost:3001';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_AUTH_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || DEV_AUTH_URL;
|
||||
}
|
||||
|
||||
// Get backend URL dynamically at runtime
|
||||
function getBackendUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
|
||||
.__PUBLIC_BACKEND_URL__;
|
||||
return injectedUrl || 'http://localhost:3022';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_BACKEND_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_BACKEND_URL || 'http://localhost:3022';
|
||||
return process.env.PUBLIC_BACKEND_URL || DEV_BACKEND_URL;
|
||||
}
|
||||
|
||||
// Lazy initialization to avoid SSR issues
|
||||
|
|
@ -187,7 +191,8 @@ export const authStore = {
|
|||
}
|
||||
|
||||
try {
|
||||
const result = await authService.forgotPassword(email);
|
||||
const redirectTo = browser ? window.location.origin : undefined;
|
||||
const result = await authService.forgotPassword(email, redirectTo);
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Password reset failed' };
|
||||
|
|
|
|||
|
|
@ -2,43 +2,56 @@ import { browser } from '$app/environment';
|
|||
import { goto } from '$app/navigation';
|
||||
import { initializeWebAuth, type AuthService, type UserData } from '@manacore/shared-auth';
|
||||
|
||||
// Default URLs for local development only
|
||||
const DEV_AUTH_URL = 'http://localhost:3001';
|
||||
const DEV_BACKEND_URL = 'http://localhost:3025';
|
||||
|
||||
function getAuthUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string })
|
||||
.__PUBLIC_MANA_CORE_AUTH_URL__;
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_AUTH_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || DEV_AUTH_URL;
|
||||
}
|
||||
|
||||
function getBackendUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_MANA_LLM_URL__?: string })
|
||||
.__PUBLIC_MANA_LLM_URL__;
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_BACKEND_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_MANA_LLM_URL || DEV_BACKEND_URL;
|
||||
}
|
||||
|
||||
let user = $state<UserData | null>(null);
|
||||
let loading = $state(true);
|
||||
let initialized = $state(false);
|
||||
|
||||
let _authService: AuthService | null = null;
|
||||
|
||||
function getAuthUrl(): string {
|
||||
if (!browser) return '';
|
||||
return (
|
||||
(window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string })
|
||||
.__PUBLIC_MANA_CORE_AUTH_URL__ ||
|
||||
import.meta.env.PUBLIC_MANA_CORE_AUTH_URL ||
|
||||
'http://localhost:3001'
|
||||
);
|
||||
}
|
||||
|
||||
function getLlmUrl(): string {
|
||||
if (!browser) return '';
|
||||
return (
|
||||
(window as unknown as { __PUBLIC_MANA_LLM_URL__?: string }).__PUBLIC_MANA_LLM_URL__ ||
|
||||
import.meta.env.PUBLIC_MANA_LLM_URL ||
|
||||
'http://localhost:3025'
|
||||
);
|
||||
}
|
||||
let _tokenManager: ReturnType<typeof initializeWebAuth>['tokenManager'] | null = null;
|
||||
|
||||
function getAuthService(): AuthService | null {
|
||||
if (!browser) return null;
|
||||
if (!_authService) {
|
||||
const auth = initializeWebAuth({
|
||||
baseUrl: getAuthUrl(),
|
||||
backendUrl: getLlmUrl(),
|
||||
backendUrl: getBackendUrl(),
|
||||
});
|
||||
_authService = auth.authService;
|
||||
_tokenManager = auth.tokenManager;
|
||||
}
|
||||
return _authService;
|
||||
}
|
||||
|
||||
function getTokenManager() {
|
||||
if (!browser) return null;
|
||||
getAuthService();
|
||||
return _tokenManager;
|
||||
}
|
||||
|
||||
export const authStore = {
|
||||
get user() {
|
||||
return user;
|
||||
|
|
@ -118,10 +131,29 @@ export const authStore = {
|
|||
goto('/login');
|
||||
},
|
||||
|
||||
async getValidToken(): Promise<string | null> {
|
||||
async resetPassword(email: string) {
|
||||
const authService = getAuthService();
|
||||
if (!authService) return null;
|
||||
return authService.getAppToken();
|
||||
if (!authService) {
|
||||
return { success: false, error: 'Auth not available on server' };
|
||||
}
|
||||
|
||||
try {
|
||||
const redirectTo = browser ? window.location.origin : undefined;
|
||||
const result = await authService.forgotPassword(email, redirectTo);
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Password reset failed' };
|
||||
}
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||
return { success: false, error: errorMessage };
|
||||
}
|
||||
},
|
||||
|
||||
async getValidToken(): Promise<string | null> {
|
||||
const tokenManager = getTokenManager();
|
||||
if (!tokenManager) return null;
|
||||
return await tokenManager.getValidToken();
|
||||
},
|
||||
|
||||
async resendVerificationEmail(email: string) {
|
||||
|
|
|
|||
|
|
@ -4,12 +4,33 @@
|
|||
*/
|
||||
|
||||
import { browser } from '$app/environment';
|
||||
import { initializeWebAuth } from '@manacore/shared-auth';
|
||||
import type { UserData } from '@manacore/shared-auth';
|
||||
import { PUBLIC_MANA_CORE_AUTH_URL } from '$env/static/public';
|
||||
import { initializeWebAuth, type UserData } from '@manacore/shared-auth';
|
||||
|
||||
// Initialize Mana Core Auth only on the client side
|
||||
const MANA_AUTH_URL = PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
// Default URLs for local development only
|
||||
const DEV_AUTH_URL = 'http://localhost:3001';
|
||||
const DEV_BACKEND_URL = 'http://localhost:3008';
|
||||
|
||||
// Get auth URL dynamically at runtime - fallback for SSR and client
|
||||
function getAuthUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string })
|
||||
.__PUBLIC_MANA_CORE_AUTH_URL__;
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_AUTH_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || DEV_AUTH_URL;
|
||||
}
|
||||
|
||||
// Get backend URL dynamically at runtime
|
||||
function getBackendUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
|
||||
.__PUBLIC_BACKEND_URL__;
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_BACKEND_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_BACKEND_URL || DEV_BACKEND_URL;
|
||||
}
|
||||
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
let _authService: ReturnType<typeof initializeWebAuth>['authService'] | null = null;
|
||||
|
|
@ -18,13 +39,22 @@ let _tokenManager: ReturnType<typeof initializeWebAuth>['tokenManager'] | null =
|
|||
function getAuthService() {
|
||||
if (!browser) return null;
|
||||
if (!_authService) {
|
||||
const auth = initializeWebAuth({ baseUrl: MANA_AUTH_URL });
|
||||
const auth = initializeWebAuth({
|
||||
baseUrl: getAuthUrl(),
|
||||
backendUrl: getBackendUrl(),
|
||||
});
|
||||
_authService = auth.authService;
|
||||
_tokenManager = auth.tokenManager;
|
||||
}
|
||||
return _authService;
|
||||
}
|
||||
|
||||
function getTokenManager() {
|
||||
if (!browser) return null;
|
||||
getAuthService();
|
||||
return _tokenManager;
|
||||
}
|
||||
|
||||
// State
|
||||
let user = $state<UserData | null>(null);
|
||||
let loading = $state(true);
|
||||
|
|
@ -61,10 +91,8 @@ export const auth = {
|
|||
|
||||
loading = true;
|
||||
try {
|
||||
// First, check if we have valid local tokens
|
||||
let authenticated = await authService.isAuthenticated();
|
||||
|
||||
// If not authenticated locally, try SSO (shared session cookie)
|
||||
if (!authenticated) {
|
||||
console.log('No local tokens, trying SSO...');
|
||||
const ssoResult = await authService.trySSO();
|
||||
|
|
@ -89,7 +117,6 @@ export const auth = {
|
|||
|
||||
/**
|
||||
* Sign in with email and password
|
||||
* Returns AuthResult compatible format for shared-auth-ui
|
||||
*/
|
||||
async login(email: string, password: string): Promise<{ success: boolean; error?: string }> {
|
||||
const authService = getAuthService();
|
||||
|
|
@ -104,7 +131,6 @@ export const auth = {
|
|||
return { success: false, error: result.error || 'Login failed' };
|
||||
}
|
||||
|
||||
// Get user data from token
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
|
||||
|
|
@ -128,7 +154,6 @@ export const auth = {
|
|||
}
|
||||
|
||||
try {
|
||||
// Pass the current app URL for post-verification redirect
|
||||
const sourceAppUrl = browser ? window.location.origin : undefined;
|
||||
const result = await authService.signUp(email, password, sourceAppUrl);
|
||||
|
||||
|
|
@ -136,12 +161,10 @@ export const auth = {
|
|||
return { success: false, error: result.error || 'Signup failed', needsVerification: false };
|
||||
}
|
||||
|
||||
// Mana Core Auth requires separate login after signup
|
||||
if (result.needsVerification) {
|
||||
return { success: true, needsVerification: true };
|
||||
}
|
||||
|
||||
// Auto sign in after successful signup
|
||||
const signInResult = await this.login(email, password);
|
||||
return { ...signInResult, needsVerification: false };
|
||||
} catch (error) {
|
||||
|
|
@ -165,7 +188,6 @@ export const auth = {
|
|||
user = null;
|
||||
} catch (error) {
|
||||
console.error('Sign out error:', error);
|
||||
// Clear user even if sign out fails
|
||||
user = null;
|
||||
}
|
||||
},
|
||||
|
|
@ -180,7 +202,8 @@ export const auth = {
|
|||
}
|
||||
|
||||
try {
|
||||
const result = await authService.forgotPassword(email);
|
||||
const redirectTo = browser ? window.location.origin : undefined;
|
||||
const result = await authService.forgotPassword(email, redirectTo);
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Password reset failed' };
|
||||
|
|
@ -216,6 +239,7 @@ export const auth = {
|
|||
|
||||
/**
|
||||
* Get access token for API calls
|
||||
* @deprecated Use getValidToken() instead for automatic refresh
|
||||
*/
|
||||
async getAccessToken() {
|
||||
const authService = getAuthService();
|
||||
|
|
@ -225,6 +249,18 @@ export const auth = {
|
|||
return await authService.getAppToken();
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a valid access token for API calls
|
||||
* Automatically refreshes if the token is expired or about to expire
|
||||
*/
|
||||
async getValidToken(): Promise<string | null> {
|
||||
const tokenManager = getTokenManager();
|
||||
if (!tokenManager) {
|
||||
return null;
|
||||
}
|
||||
return await tokenManager.getValidToken();
|
||||
},
|
||||
|
||||
/**
|
||||
* Resend verification email
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -7,22 +7,28 @@ import { browser } from '$app/environment';
|
|||
import { initializeWebAuth } from '@manacore/shared-auth';
|
||||
import type { UserData } from '@manacore/shared-auth';
|
||||
|
||||
// Default URLs for local development only
|
||||
const DEV_AUTH_URL = 'http://localhost:3001';
|
||||
const DEV_BACKEND_URL = 'http://localhost:3011';
|
||||
|
||||
function getAuthUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string })
|
||||
.__PUBLIC_MANA_CORE_AUTH_URL__;
|
||||
return injectedUrl || 'http://localhost:3001';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_AUTH_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || DEV_AUTH_URL;
|
||||
}
|
||||
|
||||
function getBackendUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
|
||||
.__PUBLIC_BACKEND_URL__;
|
||||
return injectedUrl || 'http://localhost:3011';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_BACKEND_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_BACKEND_URL || 'http://localhost:3011';
|
||||
return process.env.PUBLIC_BACKEND_URL || DEV_BACKEND_URL;
|
||||
}
|
||||
|
||||
let _authService: ReturnType<typeof initializeWebAuth>['authService'] | null = null;
|
||||
|
|
@ -179,7 +185,8 @@ export const authStore = {
|
|||
}
|
||||
|
||||
try {
|
||||
const result = await authService.forgotPassword(email);
|
||||
const redirectTo = browser ? window.location.origin : undefined;
|
||||
const result = await authService.forgotPassword(email, redirectTo);
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Password reset failed' };
|
||||
|
|
|
|||
|
|
@ -197,7 +197,8 @@ export const authStore = {
|
|||
}
|
||||
|
||||
try {
|
||||
const result = await authService.forgotPassword(email);
|
||||
const redirectTo = browser ? window.location.origin : undefined;
|
||||
const result = await authService.forgotPassword(email, redirectTo);
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Password reset failed' };
|
||||
|
|
|
|||
|
|
@ -6,33 +6,56 @@
|
|||
import { browser } from '$app/environment';
|
||||
import { initializeWebAuth, type UserData } from '@manacore/shared-auth';
|
||||
|
||||
// Default URLs for local development only
|
||||
const DEV_AUTH_URL = 'http://localhost:3001';
|
||||
const DEV_BACKEND_URL = 'http://localhost:3016';
|
||||
|
||||
// Get auth URL dynamically at runtime - fallback for SSR and client
|
||||
function getAuthUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
// Client-side: use injected window variable (set by hooks.server.ts)
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string })
|
||||
.__PUBLIC_MANA_CORE_AUTH_URL__;
|
||||
return injectedUrl || 'http://localhost:3001';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_AUTH_URL : '';
|
||||
}
|
||||
// Server-side (SSR): use Docker internal URL for container-to-container communication
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || DEV_AUTH_URL;
|
||||
}
|
||||
|
||||
const MANA_AUTH_URL = getAuthUrl();
|
||||
// Get backend URL dynamically at runtime
|
||||
function getBackendUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
|
||||
.__PUBLIC_BACKEND_URL__;
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_BACKEND_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_BACKEND_URL || DEV_BACKEND_URL;
|
||||
}
|
||||
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
let _authService: ReturnType<typeof initializeWebAuth>['authService'] | null = null;
|
||||
let _tokenManager: ReturnType<typeof initializeWebAuth>['tokenManager'] | null = null;
|
||||
|
||||
function getAuthService() {
|
||||
if (!browser) return null;
|
||||
if (!_authService) {
|
||||
const auth = initializeWebAuth({ baseUrl: MANA_AUTH_URL });
|
||||
const auth = initializeWebAuth({
|
||||
baseUrl: getAuthUrl(),
|
||||
backendUrl: getBackendUrl(),
|
||||
});
|
||||
_authService = auth.authService;
|
||||
_tokenManager = auth.tokenManager;
|
||||
}
|
||||
return _authService;
|
||||
}
|
||||
|
||||
function getTokenManager() {
|
||||
if (!browser) return null;
|
||||
getAuthService();
|
||||
return _tokenManager;
|
||||
}
|
||||
|
||||
// State
|
||||
let user = $state<UserData | null>(null);
|
||||
let loading = $state(true);
|
||||
let initialized = $state(false);
|
||||
|
|
@ -67,10 +90,8 @@ export const authStore = {
|
|||
|
||||
loading = true;
|
||||
try {
|
||||
// First, check if we have valid local tokens
|
||||
let authenticated = await authService.isAuthenticated();
|
||||
|
||||
// If not authenticated locally, try SSO (shared session cookie)
|
||||
if (!authenticated) {
|
||||
console.log('No local tokens, trying SSO...');
|
||||
const ssoResult = await authService.trySSO();
|
||||
|
|
@ -93,6 +114,9 @@ export const authStore = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sign in with email and password
|
||||
*/
|
||||
async signIn(email: string, password: string) {
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
|
|
@ -116,6 +140,9 @@ export const authStore = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sign up with email and password
|
||||
*/
|
||||
async signUp(email: string, password: string) {
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
|
|
@ -123,7 +150,6 @@ export const authStore = {
|
|||
}
|
||||
|
||||
try {
|
||||
// Pass the current app URL for post-verification redirect
|
||||
const sourceAppUrl = browser ? window.location.origin : undefined;
|
||||
const result = await authService.signUp(email, password, sourceAppUrl);
|
||||
|
||||
|
|
@ -143,6 +169,9 @@ export const authStore = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sign out
|
||||
*/
|
||||
async signOut() {
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
|
|
@ -159,6 +188,9 @@ export const authStore = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Send password reset email
|
||||
*/
|
||||
async resetPassword(email: string) {
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
|
|
@ -166,7 +198,8 @@ export const authStore = {
|
|||
}
|
||||
|
||||
try {
|
||||
const result = await authService.forgotPassword(email);
|
||||
const redirectTo = browser ? window.location.origin : undefined;
|
||||
const result = await authService.forgotPassword(email, redirectTo);
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Password reset failed' };
|
||||
|
|
@ -179,12 +212,25 @@ export const authStore = {
|
|||
}
|
||||
},
|
||||
|
||||
async getAccessToken() {
|
||||
/**
|
||||
* Reset password with token (from reset email link)
|
||||
*/
|
||||
async resetPasswordWithToken(token: string, newPassword: string) {
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
return null;
|
||||
return { success: false, error: 'Auth not available on server' };
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await authService.resetPassword(token, newPassword);
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Failed to reset password' };
|
||||
}
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||
return { success: false, error: errorMessage };
|
||||
}
|
||||
return await authService.getAppToken();
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -210,4 +256,28 @@ export const authStore = {
|
|||
return { success: false, error: errorMessage };
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get access token for API calls (raw token, no refresh)
|
||||
* @deprecated Use getValidToken() instead for automatic refresh
|
||||
*/
|
||||
async getAccessToken() {
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
return null;
|
||||
}
|
||||
return await authService.getAppToken();
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a valid access token for API calls
|
||||
* Automatically refreshes if the token is expired or about to expire
|
||||
*/
|
||||
async getValidToken(): Promise<string | null> {
|
||||
const tokenManager = getTokenManager();
|
||||
if (!tokenManager) {
|
||||
return null;
|
||||
}
|
||||
return await tokenManager.getValidToken();
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -227,7 +227,8 @@ export const authStore = {
|
|||
}
|
||||
|
||||
try {
|
||||
const result = await authService.forgotPassword(email);
|
||||
const redirectTo = browser ? window.location.origin : undefined;
|
||||
const result = await authService.forgotPassword(email, redirectTo);
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Password reset failed' };
|
||||
|
|
|
|||
|
|
@ -4,20 +4,21 @@
|
|||
*/
|
||||
|
||||
import { browser } from '$app/environment';
|
||||
import { initializeWebAuth } from '@manacore/shared-auth';
|
||||
import type { UserData } from '@manacore/shared-auth';
|
||||
import { initializeWebAuth, type UserData } from '@manacore/shared-auth';
|
||||
|
||||
// Default URLs for local development only
|
||||
const DEV_AUTH_URL = 'http://localhost:3001';
|
||||
const DEV_BACKEND_URL = 'http://localhost:3007';
|
||||
|
||||
// Get auth URL dynamically at runtime - fallback for SSR and client
|
||||
function getAuthUrl(): string {
|
||||
if (browser && typeof window !== 'undefined') {
|
||||
// Client-side: use injected window variable (set by hooks.server.ts)
|
||||
// Falls back to localhost for local development
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_MANA_CORE_AUTH_URL__?: string })
|
||||
.__PUBLIC_MANA_CORE_AUTH_URL__;
|
||||
return injectedUrl || 'http://localhost:3001';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_AUTH_URL : '';
|
||||
}
|
||||
// Server-side (SSR): use Docker internal URL for container-to-container communication
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
return process.env.PUBLIC_MANA_CORE_AUTH_URL || DEV_AUTH_URL;
|
||||
}
|
||||
|
||||
// Get backend URL dynamically at runtime
|
||||
|
|
@ -25,9 +26,10 @@ function getBackendUrl(): string {
|
|||
if (browser && typeof window !== 'undefined') {
|
||||
const injectedUrl = (window as unknown as { __PUBLIC_BACKEND_URL__?: string })
|
||||
.__PUBLIC_BACKEND_URL__;
|
||||
return injectedUrl || 'http://localhost:3007';
|
||||
if (injectedUrl) return injectedUrl;
|
||||
return import.meta.env.DEV ? DEV_BACKEND_URL : '';
|
||||
}
|
||||
return process.env.PUBLIC_BACKEND_URL || 'http://localhost:3007';
|
||||
return process.env.PUBLIC_BACKEND_URL || DEV_BACKEND_URL;
|
||||
}
|
||||
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
|
|
@ -205,7 +207,8 @@ export const authStore = {
|
|||
}
|
||||
|
||||
try {
|
||||
const result = await authService.forgotPassword(email);
|
||||
const redirectTo = browser ? window.location.origin : undefined;
|
||||
const result = await authService.forgotPassword(email, redirectTo);
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Password reset failed' };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue