From 2ccd0636283706868721730eb81e8787221c7968 Mon Sep 17 00:00:00 2001 From: Till-JS <101404291+Till-JS@users.noreply.github.com> Date: Tue, 27 Jan 2026 01:31:31 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(auth):=20redirect=20users=20to?= =?UTF-8?q?=20source=20app=20after=20email=20verification?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add sourceAppUrl tracking during registration to redirect users back to the app they registered from after email verification. Includes URL validation for security (only *.mana.how, mana.how, localhost). Co-Authored-By: Claude Opus 4.5 --- .../apps/web/src/lib/stores/auth.svelte.ts | 4 +- .../apps/web/src/lib/stores/auth.svelte.ts | 4 +- .../apps/web/src/lib/stores/auth.svelte.ts | 4 +- .../apps/web/src/lib/stores/auth.svelte.ts | 4 +- .../apps/web/src/lib/stores/auth.svelte.ts | 4 +- .../apps/web/src/lib/stores/auth.svelte.ts | 5 +- .../apps/web/src/lib/stores/auth.svelte.ts | 4 +- .../apps/web/src/lib/stores/auth.svelte.ts | 4 +- .../apps/web/src/lib/stores/auth.svelte.ts | 4 +- .../apps/web/src/lib/stores/auth.svelte.ts | 4 +- .../apps/web/src/lib/stores/auth.svelte.ts | 4 +- .../apps/web/src/lib/stores/auth.svelte.ts | 4 +- .../apps/web/src/lib/stores/auth.svelte.ts | 4 +- packages/shared-auth/src/core/authService.ts | 11 +- .../src/auth/auth.controller.ts | 1 + .../better-auth-passthrough.controller.ts | 87 +++++++++++++-- .../src/auth/better-auth.config.ts | 19 +++- .../src/auth/dto/register.dto.ts | 8 +- .../src/auth/services/better-auth.service.ts | 31 +++++- .../src/auth/stores/source-app.store.ts | 104 ++++++++++++++++++ .../src/auth/types/better-auth.types.ts | 1 + 21 files changed, 285 insertions(+), 30 deletions(-) create mode 100644 services/mana-core-auth/src/auth/stores/source-app.store.ts diff --git a/apps/calendar/apps/web/src/lib/stores/auth.svelte.ts b/apps/calendar/apps/web/src/lib/stores/auth.svelte.ts index ced1c1ad4..1e0aba3fc 100644 --- a/apps/calendar/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/calendar/apps/web/src/lib/stores/auth.svelte.ts @@ -140,7 +140,9 @@ export const authStore = { } try { - const result = await authService.signUp(email, password); + // Pass the current app URL for post-verification redirect + const sourceAppUrl = browser ? window.location.origin : undefined; + const result = await authService.signUp(email, password, undefined, sourceAppUrl); if (!result.success) { return { success: false, error: result.error || 'Signup failed', needsVerification: false }; diff --git a/apps/chat/apps/web/src/lib/stores/auth.svelte.ts b/apps/chat/apps/web/src/lib/stores/auth.svelte.ts index ed412923c..204acedbc 100644 --- a/apps/chat/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/chat/apps/web/src/lib/stores/auth.svelte.ts @@ -140,7 +140,9 @@ export const authStore = { } try { - const result = await authService.signUp(email, password); + // Pass the current app URL for post-verification redirect + const sourceAppUrl = browser ? window.location.origin : undefined; + const result = await authService.signUp(email, password, undefined, sourceAppUrl); if (!result.success) { return { success: false, error: result.error || 'Signup failed', needsVerification: false }; diff --git a/apps/clock/apps/web/src/lib/stores/auth.svelte.ts b/apps/clock/apps/web/src/lib/stores/auth.svelte.ts index 931f6327e..2928ef6b2 100644 --- a/apps/clock/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/clock/apps/web/src/lib/stores/auth.svelte.ts @@ -139,7 +139,9 @@ export const authStore = { } try { - const result = await authService.signUp(email, password); + // Pass the current app URL for post-verification redirect + const sourceAppUrl = browser ? window.location.origin : undefined; + const result = await authService.signUp(email, password, undefined, sourceAppUrl); if (!result.success) { return { success: false, error: result.error || 'Signup failed', needsVerification: false }; diff --git a/apps/contacts/apps/web/src/lib/stores/auth.svelte.ts b/apps/contacts/apps/web/src/lib/stores/auth.svelte.ts index 4582f599b..63c3c1d3d 100644 --- a/apps/contacts/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/contacts/apps/web/src/lib/stores/auth.svelte.ts @@ -140,7 +140,9 @@ export const authStore = { } try { - const result = await authService.signUp(email, password); + // Pass the current app URL for post-verification redirect + const sourceAppUrl = browser ? window.location.origin : undefined; + const result = await authService.signUp(email, password, undefined, sourceAppUrl); if (!result.success) { return { success: false, error: result.error || 'Signup failed', needsVerification: false }; diff --git a/apps/manacore/apps/web/src/lib/stores/auth.svelte.ts b/apps/manacore/apps/web/src/lib/stores/auth.svelte.ts index 703cf974f..e0b1f0b49 100644 --- a/apps/manacore/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/manacore/apps/web/src/lib/stores/auth.svelte.ts @@ -139,7 +139,9 @@ export const authStore = { } try { - const result = await authService.signUp(email, password, referralCode); + // Pass the current app URL for post-verification redirect + const sourceAppUrl = browser ? window.location.origin : undefined; + const result = await authService.signUp(email, password, referralCode, sourceAppUrl); if (!result.success) { return { success: false, error: result.error || 'Signup failed', needsVerification: false }; diff --git a/apps/manadeck/apps/web/src/lib/stores/auth.svelte.ts b/apps/manadeck/apps/web/src/lib/stores/auth.svelte.ts index 40107f7ca..f6f762502 100644 --- a/apps/manadeck/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/manadeck/apps/web/src/lib/stores/auth.svelte.ts @@ -1,3 +1,4 @@ +import { browser } from '$app/environment'; import type { ManaUser } from '$lib/types/auth'; import { authService, tokenManager } from '$lib/auth'; import type { UserData } from '$lib/auth'; @@ -95,7 +96,9 @@ export const authStore = { * Sign up with email and password */ async signUp(email: string, password: string) { - const result = await authService.signUp(email, password); + // Pass the current app URL for post-verification redirect + const sourceAppUrl = browser ? window.location.origin : undefined; + const result = await authService.signUp(email, password, undefined, sourceAppUrl); if (result.success && !result.needsVerification) { const userData = await authService.getUserFromToken(); user = toManaUser(userData); diff --git a/apps/nutriphi/apps/web/src/lib/stores/auth.svelte.ts b/apps/nutriphi/apps/web/src/lib/stores/auth.svelte.ts index 86757f1ce..1d7ced4b7 100644 --- a/apps/nutriphi/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/nutriphi/apps/web/src/lib/stores/auth.svelte.ts @@ -127,7 +127,9 @@ export const authStore = { } try { - const result = await authService.signUp(email, password); + // Pass the current app URL for post-verification redirect + const sourceAppUrl = browser ? window.location.origin : undefined; + const result = await authService.signUp(email, password, undefined, sourceAppUrl); if (!result.success) { return { success: false, error: result.error || 'Signup failed', needsVerification: false }; diff --git a/apps/picture/apps/web/src/lib/stores/auth.svelte.ts b/apps/picture/apps/web/src/lib/stores/auth.svelte.ts index b63abb804..4b74bcb68 100644 --- a/apps/picture/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/picture/apps/web/src/lib/stores/auth.svelte.ts @@ -124,7 +124,9 @@ export const authStore = { try { loading = true; - const result = await authService.signUp(email, password); + // Pass the current app URL for post-verification redirect + const sourceAppUrl = browser ? window.location.origin : undefined; + const result = await authService.signUp(email, password, undefined, sourceAppUrl); if (result.success) { // Auto-login after signup diff --git a/apps/planta/apps/web/src/lib/stores/auth.svelte.ts b/apps/planta/apps/web/src/lib/stores/auth.svelte.ts index 773c21a6f..4870921fd 100644 --- a/apps/planta/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/planta/apps/web/src/lib/stores/auth.svelte.ts @@ -125,7 +125,9 @@ export const authStore = { } try { - const result = await authService.signUp(email, password); + // Pass the current app URL for post-verification redirect + const sourceAppUrl = browser ? window.location.origin : undefined; + const result = await authService.signUp(email, password, undefined, sourceAppUrl); if (!result.success) { return { success: false, error: result.error || 'Signup failed', needsVerification: false }; diff --git a/apps/presi/apps/web/src/lib/stores/auth.svelte.ts b/apps/presi/apps/web/src/lib/stores/auth.svelte.ts index 5117acb79..45f77eff5 100644 --- a/apps/presi/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/presi/apps/web/src/lib/stores/auth.svelte.ts @@ -115,7 +115,9 @@ export const auth = { } try { - const result = await authService.signUp(email, password); + // Pass the current app URL for post-verification redirect + const sourceAppUrl = browser ? window.location.origin : undefined; + const result = await authService.signUp(email, password, undefined, sourceAppUrl); if (!result.success) { return { success: false, error: result.error || 'Signup failed', needsVerification: false }; diff --git a/apps/storage/apps/web/src/lib/stores/auth.svelte.ts b/apps/storage/apps/web/src/lib/stores/auth.svelte.ts index 4d8a27853..c44e8af58 100644 --- a/apps/storage/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/storage/apps/web/src/lib/stores/auth.svelte.ts @@ -95,7 +95,9 @@ export const authStore = { } try { - const result = await authService.signUp(email, password); + // Pass the current app URL for post-verification redirect + const sourceAppUrl = browser ? window.location.origin : undefined; + const result = await authService.signUp(email, password, undefined, sourceAppUrl); if (!result.success) { return { success: false, error: result.error || 'Signup failed', needsVerification: false }; diff --git a/apps/todo/apps/web/src/lib/stores/auth.svelte.ts b/apps/todo/apps/web/src/lib/stores/auth.svelte.ts index 817c251fd..c85b5144f 100644 --- a/apps/todo/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/todo/apps/web/src/lib/stores/auth.svelte.ts @@ -152,7 +152,9 @@ export const authStore = { } try { - const result = await authService.signUp(email, password); + // Pass the current app URL for post-verification redirect + const sourceAppUrl = browser ? window.location.origin : undefined; + const result = await authService.signUp(email, password, undefined, sourceAppUrl); if (!result.success) { return { success: false, error: result.error || 'Signup failed', needsVerification: false }; diff --git a/apps/zitare/apps/web/src/lib/stores/auth.svelte.ts b/apps/zitare/apps/web/src/lib/stores/auth.svelte.ts index 03771a80c..e8d02a327 100644 --- a/apps/zitare/apps/web/src/lib/stores/auth.svelte.ts +++ b/apps/zitare/apps/web/src/lib/stores/auth.svelte.ts @@ -140,7 +140,9 @@ export const authStore = { } try { - const result = await authService.signUp(email, password); + // Pass the current app URL for post-verification redirect + const sourceAppUrl = browser ? window.location.origin : undefined; + const result = await authService.signUp(email, password, undefined, sourceAppUrl); if (!result.success) { return { success: false, error: result.error || 'Signup failed', needsVerification: false }; diff --git a/packages/shared-auth/src/core/authService.ts b/packages/shared-auth/src/core/authService.ts index 83905ad59..dde72da55 100644 --- a/packages/shared-auth/src/core/authService.ts +++ b/packages/shared-auth/src/core/authService.ts @@ -107,13 +107,22 @@ export function createAuthService(config: AuthServiceConfig) { * @param email User email * @param password User password * @param referralCode Optional referral code for bonus credits + * @param sourceAppUrl Optional URL of the app where the user is registering */ - async signUp(email: string, password: string, referralCode?: string): Promise { + async signUp( + email: string, + password: string, + referralCode?: string, + sourceAppUrl?: string + ): Promise { try { const body: Record = { email, password }; if (referralCode) { body.referralCode = referralCode; } + if (sourceAppUrl) { + body.sourceAppUrl = sourceAppUrl; + } const response = await fetch(`${baseUrl}${endpoints.signUp}`, { method: 'POST', diff --git a/services/mana-core-auth/src/auth/auth.controller.ts b/services/mana-core-auth/src/auth/auth.controller.ts index 5ad646960..e5e1a2c1f 100644 --- a/services/mana-core-auth/src/auth/auth.controller.ts +++ b/services/mana-core-auth/src/auth/auth.controller.ts @@ -62,6 +62,7 @@ export class AuthController { email: registerDto.email, password: registerDto.password, name: registerDto.name || '', + sourceAppUrl: registerDto.sourceAppUrl, }); } diff --git a/services/mana-core-auth/src/auth/better-auth-passthrough.controller.ts b/services/mana-core-auth/src/auth/better-auth-passthrough.controller.ts index 0202a2cba..f4e5b9b61 100644 --- a/services/mana-core-auth/src/auth/better-auth-passthrough.controller.ts +++ b/services/mana-core-auth/src/auth/better-auth-passthrough.controller.ts @@ -17,40 +17,103 @@ import { BetterAuthService } from './services/better-auth.service'; @Controller('api/auth') export class BetterAuthPassthroughController { + private readonly defaultFrontendUrl = 'https://mana.how'; + constructor(private readonly betterAuthService: BetterAuthService) {} + /** + * Validate redirect URL for security + * + * Only allows redirects to: + * - *.mana.how domains + * - mana.how (main domain) + * - localhost (for development) + * + * @param redirectTo - URL to validate + * @returns Validated origin URL or null if invalid + */ + private validateRedirectUrl(redirectTo?: string): string | null { + if (!redirectTo) return null; + + try { + const url = new URL(redirectTo); + + // Allow *.mana.how, mana.how, and localhost + if ( + url.hostname.endsWith('.mana.how') || + url.hostname === 'mana.how' || + url.hostname === 'localhost' + ) { + return url.origin; + } + } catch { + // Invalid URL, return null + } + + return null; + } + /** * Handle email verification * * Better Auth sends verification emails with links to: - * {baseURL}/api/auth/verify-email?token=... + * {baseURL}/api/auth/verify-email?token=...&redirectTo=... * - * This endpoint calls Better Auth's verifyEmail API and redirects - * the user to the appropriate page. + * This endpoint: + * 1. Calls Better Auth's verifyEmail API + * 2. Gets the source app URL from the store (set during registration) + * 3. Redirects the user to the app's login page with verified=true and email */ @Get('verify-email') - async verifyEmail(@Query('token') token: string, @Res() res: Response) { + async verifyEmail( + @Query('token') token: string, + @Query('redirectTo') redirectTo: string | undefined, + @Res() res: Response + ) { + const fallbackUrl = process.env.FRONTEND_URL || this.defaultFrontendUrl; + try { if (!token) { - return res.redirect('/verification-failed?error=missing_token'); + return res.redirect(`${fallbackUrl}/verification-failed?error=missing_token`); } // Call Better Auth's verifyEmail API const result = await this.betterAuthService.verifyEmail(token); if (result.success) { - // Redirect to success page (frontend should handle this) - const frontendUrl = process.env.FRONTEND_URL || 'https://mana.how'; - return res.redirect(`${frontendUrl}/email-verified`); + const email = result.email || ''; + + // Determine redirect URL: + // 1. First try the redirectTo query param (passed through URL) + // 2. Then try the sourceAppStore (set during registration) + // 3. Finally fall back to default frontend URL + let baseUrl = this.validateRedirectUrl(redirectTo); + + if (!baseUrl && email) { + // Try to get source app URL from store (set during registration) + const storedUrl = this.betterAuthService.getSourceAppUrl(email); + baseUrl = this.validateRedirectUrl(storedUrl || undefined); + } + + if (!baseUrl) { + baseUrl = fallbackUrl; + } + + // Redirect to app's login page with verified=true and email + const loginUrl = new URL('/login', baseUrl); + loginUrl.searchParams.set('verified', 'true'); + if (email) { + loginUrl.searchParams.set('email', email); + } + + return res.redirect(loginUrl.toString()); } else { // Redirect to error page - const frontendUrl = process.env.FRONTEND_URL || 'https://mana.how'; - return res.redirect(`${frontendUrl}/verification-failed?error=${result.error}`); + return res.redirect(`${fallbackUrl}/verification-failed?error=${result.error}`); } } catch (error) { console.error('[verify-email] Error:', error); - const frontendUrl = process.env.FRONTEND_URL || 'https://mana.how'; - return res.redirect(`${frontendUrl}/verification-failed?error=verification_failed`); + return res.redirect(`${fallbackUrl}/verification-failed?error=verification_failed`); } } } diff --git a/services/mana-core-auth/src/auth/better-auth.config.ts b/services/mana-core-auth/src/auth/better-auth.config.ts index 4203eb425..ff0d354c0 100644 --- a/services/mana-core-auth/src/auth/better-auth.config.ts +++ b/services/mana-core-auth/src/auth/better-auth.config.ts @@ -27,6 +27,7 @@ import { sendInvitationEmail, sendVerificationEmail, } from '../email/email.service'; +import { sourceAppStore } from './stores/source-app.store'; /** * JWT Custom Payload Interface @@ -117,6 +118,9 @@ export function createBetterAuth(databaseUrl: string) { * * Sends verification email when user registers. * User must verify email before they can log in. + * + * The verification URL is modified to include redirectTo parameter + * so users are redirected back to the app they registered from. */ emailVerification: { sendOnSignUp: true, @@ -128,7 +132,20 @@ export function createBetterAuth(databaseUrl: string) { user: { email: string; name: string }; url: string; }) => { - await sendVerificationEmail(user.email, url, user.name); + // Check if we have a source app URL stored for this user + // Note: We get the URL without deleting it here since it might be needed + // during the verification process in the passthrough controller + const sourceAppUrl = sourceAppStore.get(user.email); + + // Modify verification URL to include redirectTo parameter + let verificationUrl = url; + if (sourceAppUrl) { + const urlObj = new URL(url); + urlObj.searchParams.set('redirectTo', sourceAppUrl); + verificationUrl = urlObj.toString(); + } + + await sendVerificationEmail(user.email, verificationUrl, user.name); }, }, diff --git a/services/mana-core-auth/src/auth/dto/register.dto.ts b/services/mana-core-auth/src/auth/dto/register.dto.ts index 2fcdb619d..394567f51 100644 --- a/services/mana-core-auth/src/auth/dto/register.dto.ts +++ b/services/mana-core-auth/src/auth/dto/register.dto.ts @@ -1,4 +1,4 @@ -import { IsEmail, IsString, MinLength, MaxLength, IsOptional } from 'class-validator'; +import { IsEmail, IsString, MinLength, MaxLength, IsOptional, IsUrl } from 'class-validator'; export class RegisterDto { @IsEmail() @@ -13,4 +13,10 @@ export class RegisterDto { @IsOptional() @MaxLength(255) name?: string; + + @IsString() + @IsOptional() + @IsUrl({ require_tld: false }) // Allow localhost URLs for development + @MaxLength(255) + sourceAppUrl?: string; } diff --git a/services/mana-core-auth/src/auth/services/better-auth.service.ts b/services/mana-core-auth/src/auth/services/better-auth.service.ts index d6ab946be..b164d8eca 100644 --- a/services/mana-core-auth/src/auth/services/better-auth.service.ts +++ b/services/mana-core-auth/src/auth/services/better-auth.service.ts @@ -32,6 +32,7 @@ import { ReferralCodeService } from '../../referrals/services/referral-code.serv import { ReferralTierService } from '../../referrals/services/referral-tier.service'; import { ReferralTrackingService } from '../../referrals/services/referral-tracking.service'; import { hasUser, hasToken, hasMember, hasMembers, hasSession } from '../types/better-auth.types'; +import { sourceAppStore } from '../stores/source-app.store'; import type { RegisterB2CDto, RegisterB2BDto, @@ -125,6 +126,11 @@ export class BetterAuthService { */ async registerB2C(dto: RegisterB2CDto): Promise { try { + // Store source app URL before registration (for email verification redirect) + if (dto.sourceAppUrl) { + sourceAppStore.set(dto.email, dto.sourceAppUrl); + } + // Create user via Better Auth const result = await this.auth.api.signUpEmail({ body: { @@ -945,9 +951,9 @@ export class BetterAuthService { * Uses Better Auth's verifyEmail API. * * @param token - Verification token from email link - * @returns Success status + * @returns Success status and user email */ - async verifyEmail(token: string): Promise<{ success: boolean; error?: string }> { + async verifyEmail(token: string): Promise<{ success: boolean; email?: string; error?: string }> { try { // Better Auth's verifyEmail method // See: https://www.better-auth.com/docs/authentication/email-verification @@ -959,8 +965,12 @@ export class BetterAuthService { console.log('[verifyEmail] Result:', result); + // Extract email from result if available + const email = result?.user?.email || result?.email; + return { success: true, + email, }; } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; @@ -1020,6 +1030,23 @@ export class BetterAuthService { } } + // ========================================================================= + // Source App URL Methods + // ========================================================================= + + /** + * Get and remove source app URL for an email + * + * Used after email verification to redirect user to the correct app. + * The entry is deleted after retrieval to prevent re-use. + * + * @param email - User's email address + * @returns Source app URL or null if not found + */ + getSourceAppUrl(email: string): string | null { + return sourceAppStore.getAndDelete(email); + } + // ========================================================================= // Private Helper Methods // ========================================================================= diff --git a/services/mana-core-auth/src/auth/stores/source-app.store.ts b/services/mana-core-auth/src/auth/stores/source-app.store.ts new file mode 100644 index 000000000..05c194f17 --- /dev/null +++ b/services/mana-core-auth/src/auth/stores/source-app.store.ts @@ -0,0 +1,104 @@ +/** + * Source App Store + * + * Temporary in-memory store for tracking which app a user registered from. + * This allows redirecting users back to the correct app's login page + * after email verification. + * + * TTL: 24 hours (matches verification token expiry) + */ + +interface SourceAppEntry { + sourceAppUrl: string; + expiresAt: number; +} + +// In-memory store: email -> { sourceAppUrl, expiresAt } +const store = new Map(); + +// TTL in milliseconds (24 hours) +const TTL_MS = 24 * 60 * 60 * 1000; + +// Cleanup interval (every hour) +const CLEANUP_INTERVAL_MS = 60 * 60 * 1000; + +// Start cleanup interval +setInterval(() => { + const now = Date.now(); + for (const [email, entry] of store.entries()) { + if (entry.expiresAt < now) { + store.delete(email); + } + } +}, CLEANUP_INTERVAL_MS); + +export const sourceAppStore = { + /** + * Store the source app URL for an email + */ + set(email: string, sourceAppUrl: string): void { + const normalizedEmail = email.toLowerCase().trim(); + store.set(normalizedEmail, { + sourceAppUrl, + expiresAt: Date.now() + TTL_MS, + }); + }, + + /** + * Get the source app URL for an email + * Returns null if not found or expired + */ + get(email: string): string | null { + const normalizedEmail = email.toLowerCase().trim(); + const entry = store.get(normalizedEmail); + + if (!entry) { + return null; + } + + // Check if expired + if (entry.expiresAt < Date.now()) { + store.delete(normalizedEmail); + return null; + } + + return entry.sourceAppUrl; + }, + + /** + * Get and remove the source app URL for an email + * This is used after verification to prevent re-use + */ + getAndDelete(email: string): string | null { + const normalizedEmail = email.toLowerCase().trim(); + const entry = store.get(normalizedEmail); + + if (!entry) { + return null; + } + + store.delete(normalizedEmail); + + // Check if expired + if (entry.expiresAt < Date.now()) { + return null; + } + + return entry.sourceAppUrl; + }, + + /** + * Remove entry for an email + */ + delete(email: string): void { + const normalizedEmail = email.toLowerCase().trim(); + store.delete(normalizedEmail); + }, + + /** + * Clear all entries (for testing) + */ + clear(): void { + store.clear(); + }, +}; diff --git a/services/mana-core-auth/src/auth/types/better-auth.types.ts b/services/mana-core-auth/src/auth/types/better-auth.types.ts index 2fca555b4..e36a5a85e 100644 --- a/services/mana-core-auth/src/auth/types/better-auth.types.ts +++ b/services/mana-core-auth/src/auth/types/better-auth.types.ts @@ -376,6 +376,7 @@ export interface RegisterB2CDto { name: string; referralCode?: string; sourceAppId?: string; + sourceAppUrl?: string; } /**