Add JWT configuration and improve email error handling
Build And Push Image / docker (push) Successful in 2m51s
Details
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:
parent
97653b7307
commit
bff89bd89d
|
|
@ -127,6 +127,7 @@ export default defineNuxtConfig({
|
||||||
},
|
},
|
||||||
sessionSecret: process.env.NUXT_SESSION_SECRET || "",
|
sessionSecret: process.env.NUXT_SESSION_SECRET || "",
|
||||||
encryptionKey: process.env.NUXT_ENCRYPTION_KEY || "",
|
encryptionKey: process.env.NUXT_ENCRYPTION_KEY || "",
|
||||||
|
jwtSecret: process.env.NUXT_JWT_SECRET || process.env.NUXT_SESSION_SECRET || "",
|
||||||
public: {
|
public: {
|
||||||
// Client-side configuration
|
// Client-side configuration
|
||||||
appName: "MonacoUSA Portal",
|
appName: "MonacoUSA Portal",
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,8 @@ export default defineEventHandler(async (event) => {
|
||||||
// 9. Send welcome/verification email using our custom email system
|
// 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...');
|
console.log('[api/members/[id]/create-portal-account.post] Attempting to send welcome/verification email...');
|
||||||
let emailSent = false;
|
let emailSent = false;
|
||||||
|
let emailError: string | null = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { getEmailService } = await import('~/server/utils/email');
|
const { getEmailService } = await import('~/server/utils/email');
|
||||||
const { generateEmailVerificationToken } = await import('~/server/utils/email-tokens');
|
const { generateEmailVerificationToken } = await import('~/server/utils/email-tokens');
|
||||||
|
|
@ -137,8 +139,13 @@ export default defineEventHandler(async (event) => {
|
||||||
|
|
||||||
emailSent = true;
|
emailSent = true;
|
||||||
console.log('[api/members/[id]/create-portal-account.post] Welcome email sent successfully');
|
console.log('[api/members/[id]/create-portal-account.post] Welcome email sent successfully');
|
||||||
} catch (emailError: any) {
|
} catch (error: any) {
|
||||||
console.error('[api/members/[id]/create-portal-account.post] Failed to send welcome email:', emailError.message);
|
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
|
// 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,
|
success: true,
|
||||||
message: emailSent
|
message: emailSent
|
||||||
? 'Portal account created successfully. The member will receive an email to verify their account and set their password.'
|
? '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: {
|
data: {
|
||||||
keycloak_id: keycloakId,
|
keycloak_id: keycloakId,
|
||||||
member_id: memberId,
|
member_id: memberId,
|
||||||
email: member.email,
|
email: member.email,
|
||||||
name: `${member.first_name} ${member.last_name}`,
|
name: `${member.first_name} ${member.last_name}`,
|
||||||
email_sent: emailSent
|
email_sent: emailSent,
|
||||||
|
email_error: emailError
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { sign, verify } from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
|
|
||||||
export interface EmailVerificationTokenPayload {
|
export interface EmailVerificationTokenPayload {
|
||||||
userId: string;
|
userId: string;
|
||||||
|
|
@ -27,7 +27,7 @@ export async function generateEmailVerificationToken(userId: string, email: stri
|
||||||
iat: Date.now()
|
iat: Date.now()
|
||||||
};
|
};
|
||||||
|
|
||||||
const token = sign(payload, runtimeConfig.jwtSecret, {
|
const token = jwt.sign(payload, runtimeConfig.jwtSecret as string, {
|
||||||
expiresIn: '24h',
|
expiresIn: '24h',
|
||||||
issuer: 'monacousa-portal',
|
issuer: 'monacousa-portal',
|
||||||
audience: 'email-verification'
|
audience: 'email-verification'
|
||||||
|
|
@ -62,10 +62,10 @@ export async function verifyEmailToken(token: string): Promise<{ userId: string;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Verify JWT signature and expiration
|
// Verify JWT signature and expiration
|
||||||
const decoded = verify(token, runtimeConfig.jwtSecret, {
|
const decoded = jwt.verify(token, runtimeConfig.jwtSecret as string, {
|
||||||
issuer: 'monacousa-portal',
|
issuer: 'monacousa-portal',
|
||||||
audience: 'email-verification'
|
audience: 'email-verification'
|
||||||
}) as EmailVerificationTokenPayload;
|
}) as any as EmailVerificationTokenPayload;
|
||||||
|
|
||||||
// Validate token purpose
|
// Validate token purpose
|
||||||
if (decoded.purpose !== 'email-verification') {
|
if (decoded.purpose !== 'email-verification') {
|
||||||
|
|
@ -118,10 +118,10 @@ export async function isTokenValid(token: string): Promise<boolean> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const decoded = verify(token, runtimeConfig.jwtSecret, {
|
const decoded = jwt.verify(token, runtimeConfig.jwtSecret as string, {
|
||||||
issuer: 'monacousa-portal',
|
issuer: 'monacousa-portal',
|
||||||
audience: 'email-verification'
|
audience: 'email-verification'
|
||||||
}) as EmailVerificationTokenPayload;
|
}) as any as EmailVerificationTokenPayload;
|
||||||
|
|
||||||
return decoded.purpose === 'email-verification' && activeTokens.has(token);
|
return decoded.purpose === 'email-verification' && activeTokens.has(token);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue