Authentication Cloud Functions¶
Overview¶
The authFunctions.ts module provides comprehensive user authentication and account management functionality for the Gemforce platform. This module handles user registration, email verification, password management, and administrative functions through Parse Server cloud functions.
Module Details¶
- File:
src/cloud-functions/authFunctions.ts - Framework: Parse Server Cloud Functions
- Language: TypeScript
- Dependencies: crypto, ejs, jsonwebtoken, @sendgrid/mail
Key Features¶
🔹 User Registration & Verification¶
- Secure user registration with email verification
- Duplicate email prevention
- Role-based access control setup
- Automated verification email sending
🔹 Password Management¶
- Password reset request and processing
- Secure token-based password reset
- Email notifications for password changes
- Admin UI password setup
🔹 User Account Management¶
- User profile updates with field validation
- Onboarding status tracking
- Wallet and identity integration
- Administrative user management
🔹 Email Integration¶
- SendGrid email service integration
- EJS template-based email rendering
- Multiple email types (verification, reset, success)
- Professional email templates
Cloud Functions¶
User Registration Functions¶
registerUser¶
Parse.Cloud.define("registerUser", async (request) => {
const { username, password, email, company, firstName, lastName } = request.params;
// Implementation details...
});
Purpose: Registers a new user account with email verification.
Parameters:
- username (string): Unique username for the account
- password (string): User's password
- email (string): User's email address
- company (string, optional): User's company name
- firstName (string, optional): User's first name
- lastName (string, optional): User's last name
Returns: Success message with verification instructions
Process: 1. Validates required fields (username, password, email) 2. Checks for existing users with the same email 3. Creates new Parse User with provided information 4. Sets up role-based ACL (user + admin access) 5. Generates secure verification token (24-hour expiry) 6. Sends verification email via SendGrid 7. Returns success response
Access Control: - User gets read/write access to their own data - Admin role gets read/write access to user data
Example Usage:
const result = await Parse.Cloud.run("registerUser", {
username: "john.doe",
password: "SecurePassword123!",
email: "john.doe@example.com",
company: "Acme Corp",
firstName: "John",
lastName: "Doe"
});
console.log(result.message); // "User registered successfully. Please verify your email."
Error Conditions: - Missing required fields - Email already exists - Admin role not found - Email sending failure
verifyEmail¶
Parse.Cloud.define("verifyEmail", async (request) => {
const { token } = request.params;
// Implementation details...
});
Purpose: Verifies user email address using verification token.
Parameters:
- token (string): Email verification token
Returns: Success message confirming email verification
Process: 1. Validates token parameter 2. Finds user associated with the token 3. Checks token expiration (24-hour limit) 4. Sets emailVerified flag to true 5. Removes verification token and expiration 6. Saves user with verified status
Example Usage:
const result = await Parse.Cloud.run("verifyEmail", {
token: "abc123def456..."
});
console.log(result.message); // "Email verified successfully."
Error Conditions: - Missing token - Invalid or expired token - Token expiration exceeded
retrieveEmailFromToken¶
Parse.Cloud.define("retrieveEmailFromToken", async (request) => {
const { token } = request.params;
// Implementation details...
});
Purpose: Retrieves email address associated with a verification token.
Parameters:
- token (string): Verification token
Returns: Email address associated with the token
Example Usage:
const result = await Parse.Cloud.run("retrieveEmailFromToken", {
token: "abc123def456..."
});
console.log(result.email); // "john.doe@example.com"
Password Management Functions¶
requestPasswordReset¶
Parse.Cloud.define("requestPasswordReset", async (request) => {
const { email } = request.params;
// Implementation details...
});
Purpose: Initiates password reset process by sending reset email.
Parameters:
- email (string): Email address of the account to reset
Returns: Success message confirming reset email sent
Process: 1. Validates email parameter 2. Finds user by email address 3. Generates secure reset token (1-hour expiry) 4. Saves token and expiration to user account 5. Sends password reset email with reset link 6. Returns success confirmation
Example Usage:
const result = await Parse.Cloud.run("requestPasswordReset", {
email: "john.doe@example.com"
});
console.log(result.message); // "Password reset email sent successfully."
Error Conditions: - Missing email parameter - No user found with email - Email sending failure
resetPassword¶
Parse.Cloud.define("resetPassword", async (request) => {
const { token, newPassword, skipEmail = false } = request.params;
// Implementation details...
});
Purpose: Completes password reset using reset token and new password.
Parameters:
- token (string): Password reset token
- newPassword (string): New password for the account
- skipEmail (boolean, optional): Skip sending success email
Returns: Success message confirming password update
Process: 1. Validates token and new password 2. Finds user with valid, non-expired token 3. Updates user password 4. Clears reset token and expiration 5. Optionally sends success confirmation email 6. Returns success response
Example Usage:
const result = await Parse.Cloud.run("resetPassword", {
token: "reset123token456...",
newPassword: "NewSecurePassword123!",
skipEmail: false
});
console.log(result.message); // "Password updated successfully. A confirmation email has been sent."
Error Conditions: - Missing token or new password - Invalid or expired token - Password update failure
User Management Functions¶
updateUserByEmail¶
Parse.Cloud.define("updateUserByEmail", async (request) => {
const { email, updates, secretKey } = request.params;
// Implementation details...
});
Purpose: Updates user account information using email and secret key authentication.
Parameters:
- email (string): Email address of user to update
- updates (object): Object containing fields to update
- secretKey (string): Pre-shared secret key for authorization
Allowed Update Fields:
- termsAccepted (Date): Terms acceptance timestamp
- email (string): Email address
- walletAddress (string): Blockchain wallet address
- walletId (string): Wallet identifier
- walletPreference (string): Preferred wallet type
- personaReferenceId (string): Persona verification ID
- username (string): Username
Returns: Success message with updated user data
Security: Requires valid secret key matching AUTH_SECRET_KEY environment variable
Example Usage:
const result = await Parse.Cloud.run("updateUserByEmail", {
email: "john.doe@example.com",
updates: {
walletAddress: "0x1234567890123456789012345678901234567890",
termsAccepted: new Date().toISOString()
},
secretKey: process.env.AUTH_SECRET_KEY
});
console.log(result.message); // "User updated successfully."
Error Conditions: - Unauthorized secret key - Missing email or updates - User not found - Invalid field updates - Invalid date format for termsAccepted
isUserOnboarded¶
Parse.Cloud.define("isUserOnboarded", async (request) => {
const { email } = request.params;
// Implementation details...
});
Purpose: Checks if user has completed onboarding process.
Parameters:
- email (string): Email address to check
Returns: Boolean indicating onboarding completion status
Onboarding Criteria: User is considered onboarded if they have both:
- walletAddress set (not null/undefined)
- personaReferenceId set (not null/undefined)
Example Usage:
const result = await Parse.Cloud.run("isUserOnboarded", {
email: "john.doe@example.com"
});
console.log(result.result); // true if onboarded, false otherwise
getUsersWithIdentityWallets¶
Parse.Cloud.define("getUsersWithIdentityWallets", async (request) => {
// Implementation details...
});
Purpose: Retrieves users who have wallet addresses matching Identity table records.
Returns: Array of user objects with wallet addresses and emails
Process: 1. Queries Identity table for all wallet addresses 2. Queries User table for users with matching wallet addresses 3. Returns filtered list with wallet address and email
Example Usage:
const users = await Parse.Cloud.run("getUsersWithIdentityWallets");
users.forEach(user => {
console.log(`User: ${user.email}, Wallet: ${user.walletAddress}`);
});
Administrative Functions¶
setupAdminUIPassword¶
Parse.Cloud.define("setupAdminUIPassword", async (request) => {
const { email } = request.params;
// Implementation details...
});
Purpose: Initiates admin UI password setup for existing users.
Parameters:
- email (string): Email address of admin user
Returns: Success message confirming setup email sent
Process: 1. Finds user by email address 2. Generates secure setup token (1-hour expiry) 3. Saves token to user account 4. Sends admin UI password setup email 5. Returns success confirmation
Example Usage:
const result = await Parse.Cloud.run("setupAdminUIPassword", {
email: "admin@example.com"
});
console.log(result.message); // "Setup Admin UI password email sent successfully."
generateOnboardingLink¶
Parse.Cloud.define("generateOnboardingLink", async (request) => {
const { jwtToken } = request.params;
// Implementation details...
});
Purpose: Creates user account and generates onboarding link from JWT token.
Parameters:
- jwtToken (string): JWT token containing user information
JWT Payload Structure:
{
email: string;
firstName: string;
lastName: string;
}
Returns: Onboarding link for email verification
Process: 1. Verifies JWT token with secret key 2. Extracts user information from token 3. Checks for existing user with same email 4. Creates new user account with default password 5. Sets up ACL permissions 6. Generates verification token 7. Returns onboarding link
Example Usage:
const payload = {
email: "newuser@example.com",
firstName: "New",
lastName: "User"
};
const jwtToken = jwt.sign(payload, secretKey, { expiresIn: '1h' });
const result = await Parse.Cloud.run("generateOnboardingLink", {
jwtToken: jwtToken
});
console.log(result.result); // "https://app.example.com/verify-email/abc123..."
Email Templates and Integration¶
SendGrid Configuration¶
The module uses SendGrid for email delivery with the following configuration:
- Sender: NomyxID.Registrations@nomyx.io
- Templates: EJS-based HTML templates
- Template Location: src/utils/emailTemplate/
Email Types¶
Verification Email¶
- Template:
verifyEmailTemplate.ejs - Purpose: Email address verification
- Link:
${PROJECT_WIZARD_URL}/verify-email/${token}
Password Reset Email¶
- Template:
resetPasswordTemplate.ejs - Purpose: Password reset request
- Link:
${PROJECT_WIZARD_URL}/reset-password/${token}
Password Reset Success Email¶
- Template:
resetPasswordSuccessTemplate.ejs - Purpose: Password reset confirmation
- Content: Success notification
Admin UI Password Setup Email¶
- Template:
createPasswordTemplate.ejs - Purpose: Admin UI password setup
- Link:
${ADMIN_UI_URL}/create-password/${token}
Integration Examples¶
User Registration Flow¶
// Complete user registration and verification flow
class UserRegistrationService {
async registerNewUser(userData) {
try {
// Step 1: Register user
const registrationResult = await Parse.Cloud.run("registerUser", {
username: userData.username,
password: userData.password,
email: userData.email,
company: userData.company,
firstName: userData.firstName,
lastName: userData.lastName
});
console.log("Registration successful:", registrationResult.message);
// Step 2: User receives email and clicks verification link
// This would be handled by frontend calling verifyEmail
return {
success: true,
message: "Registration initiated. Please check email for verification."
};
} catch (error) {
console.error("Registration failed:", error.message);
throw error;
}
}
async verifyUserEmail(token) {
try {
const verificationResult = await Parse.Cloud.run("verifyEmail", { token });
console.log("Email verification successful:", verificationResult.message);
return verificationResult;
} catch (error) {
console.error("Email verification failed:", error.message);
throw error;
}
}
}
Password Reset Flow¶
// Complete password reset flow
class PasswordResetService {
async requestReset(email) {
try {
const result = await Parse.Cloud.run("requestPasswordReset", { email });
console.log("Password reset request:", result.message);
return result;
} catch (error) {
console.error("Password reset request failed:", error.message);
throw error;
}
}
async resetPassword(token, newPassword) {
try {
const result = await Parse.Cloud.run("resetPassword", { token, newPassword });
console.log("Password reset:", result.message);
return result;
} catch (error) {
console.error("Password reset failed:", error.message);
throw error;
}
}
}
User Onboarding Integration¶
// Example of integrating user onboarding status check
class OnboardingService {
async checkOnboardingStatus(email) {
try {
const result = await Parse.Cloud.run("isUserOnboarded", { email });
console.log(`User ${email} onboarding status: ${result.result}`);
return result.result;
} catch (error) {
console.error("Failed to check onboarding status:", error.message);
throw error;
}
}
}
Admin User Management¶
// Example of administrative user management
class AdminUserService {
async setupAdminPassword(email) {
try {
const result = await Parse.Cloud.run("setupAdminUIPassword", { email });
console.log("Admin password setup initiated:", result.message);
return result;
} catch (error) {
console.error("Admin password setup failed:", error.message);
throw error;
}
}
async generateOnboardingLink(jwtToken) {
try {
const result = await Parse.Cloud.run("generateOnboardingLink", { jwtToken });
console.log("Onboarding link generated:", result.result);
return result;
} catch (error) {
console.error("Failed to generate onboarding link:", error.message);
throw error;
}
}
}
Security Considerations¶
Token Security¶
- JWT tokens are signed with a strong secret key.
- Tokens have a short expiration time (e.g., 1 hour).
- Refresh tokens can be implemented for longer sessions.
Access Control¶
- ACLs (Access Control Lists) are used to restrict data access.
- Master Key is required for privileged operations.
- Role-based access ensures proper permissions.
Data Protection¶
- Sensitive user data (e.g., passwords) is hashed.
- Email addresses are stored in lowercase for consistency.
- Input validation prevents injection attacks.
Email Security¶
- SendGrid API key is securely stored.
- Email templates are sanitized to prevent XSS.
- SPF/DKIM records are configured for email authenticity.
Error Handling¶
Validation Errors¶
- Missing or invalid parameters.
- Incorrect data types.
- Constraints violations (e.g., unique email).
User Errors¶
- Invalid credentials.
- Account not found.
- Email not verified.
- Too many login attempts.
System Errors¶
- Database connection issues.
- External API failures (e.g., SendGrid).
- Unexpected server errors.
Testing¶
Unit Tests¶
- Individual cloud functions are tested in isolation.
- Mock Parse SDK and external dependencies.
- Cover all success and error paths.
Integration Tests¶
- Test end-to-end flows (e.g., registration to login).
- Verify interactions with Parse Server and external services.
- Use a dedicated test environment.
Security Tests¶
- Penetration testing for common vulnerabilities.
- Brute force attack simulations.
- Session hijacking attempts.