Add JWT configuration and improve email error handling
Build And Push Image / docker (push) Successful in 2m51s Details

- Add jwtSecret to runtime config with fallback to sessionSecret
- Enhance email error tracking in portal account creation API
- Fix jsonwebtoken imports and improve type safety
- Include detailed email error information in API responses
This commit is contained in:
Matt 2025-08-09 16:55:59 +02:00
parent 97653b7307
commit bff89bd89d
3 changed files with 19 additions and 10 deletions

View File

@ -127,6 +127,7 @@ export default defineNuxtConfig({
},
sessionSecret: process.env.NUXT_SESSION_SECRET || "",
encryptionKey: process.env.NUXT_ENCRYPTION_KEY || "",
jwtSecret: process.env.NUXT_JWT_SECRET || process.env.NUXT_SESSION_SECRET || "",
public: {
// Client-side configuration
appName: "MonacoUSA Portal",

View File

@ -119,6 +119,8 @@ export default defineEventHandler(async (event) => {
// 9. Send welcome/verification email using our custom email system
console.log('[api/members/[id]/create-portal-account.post] Attempting to send welcome/verification email...');
let emailSent = false;
let emailError: string | null = null;
try {
const { getEmailService } = await import('~/server/utils/email');
const { generateEmailVerificationToken } = await import('~/server/utils/email-tokens');
@ -137,8 +139,13 @@ export default defineEventHandler(async (event) => {
emailSent = true;
console.log('[api/members/[id]/create-portal-account.post] Welcome email sent successfully');
} catch (emailError: any) {
console.error('[api/members/[id]/create-portal-account.post] Failed to send welcome email:', emailError.message);
} catch (error: any) {
emailError = error.message || 'Unknown email error';
console.error('[api/members/[id]/create-portal-account.post] Failed to send welcome email:', emailError);
// Log the full error for debugging
console.error('[api/members/[id]/create-portal-account.post] Full email error:', error);
// Don't fail the account creation if email fails - user can resend verification email later
}
@ -148,13 +155,14 @@ export default defineEventHandler(async (event) => {
success: true,
message: emailSent
? 'Portal account created successfully. The member will receive an email to verify their account and set their password.'
: 'Portal account created successfully. Email sending is not configured - the member will need to request a password reset to access their account.',
: `Portal account created successfully. Email sending failed: ${emailError || 'Unknown error'}. The member can use "Forgot Password" to access their account.`,
data: {
keycloak_id: keycloakId,
member_id: memberId,
email: member.email,
name: `${member.first_name} ${member.last_name}`,
email_sent: emailSent
email_sent: emailSent,
email_error: emailError
}
};

View File

@ -1,4 +1,4 @@
import { sign, verify } from 'jsonwebtoken';
import jwt from 'jsonwebtoken';
export interface EmailVerificationTokenPayload {
userId: string;
@ -27,7 +27,7 @@ export async function generateEmailVerificationToken(userId: string, email: stri
iat: Date.now()
};
const token = sign(payload, runtimeConfig.jwtSecret, {
const token = jwt.sign(payload, runtimeConfig.jwtSecret as string, {
expiresIn: '24h',
issuer: 'monacousa-portal',
audience: 'email-verification'
@ -62,10 +62,10 @@ export async function verifyEmailToken(token: string): Promise<{ userId: string;
try {
// Verify JWT signature and expiration
const decoded = verify(token, runtimeConfig.jwtSecret, {
const decoded = jwt.verify(token, runtimeConfig.jwtSecret as string, {
issuer: 'monacousa-portal',
audience: 'email-verification'
}) as EmailVerificationTokenPayload;
}) as any as EmailVerificationTokenPayload;
// Validate token purpose
if (decoded.purpose !== 'email-verification') {
@ -118,10 +118,10 @@ export async function isTokenValid(token: string): Promise<boolean> {
return false;
}
const decoded = verify(token, runtimeConfig.jwtSecret, {
const decoded = jwt.verify(token, runtimeConfig.jwtSecret as string, {
issuer: 'monacousa-portal',
audience: 'email-verification'
}) as EmailVerificationTokenPayload;
}) as any as EmailVerificationTokenPayload;
return decoded.purpose === 'email-verification' && activeTokens.has(token);
} catch (error) {