Skip to content

Comments

Feature/updates#61

Merged
chemist-god merged 13 commits intomainfrom
feature/updates
Nov 27, 2025
Merged

Feature/updates#61
chemist-god merged 13 commits intomainfrom
feature/updates

Conversation

@chemist-god
Copy link
Owner

Update: Auth endpoints, verification UI, email service

Fixes recent edge cases in the verification flow (resend/verify) and tightens registration behavior around invite/verification handling.

Improves verification email formatting/handling to reduce deliverability and UX issues.

Adds a small helper endpoint to extract identifiers from tokens for downstream flows.

@chemist-god chemist-god requested a review from Copilot November 27, 2025 18:11
@vercel
Copy link

vercel bot commented Nov 27, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
smart-todo Ready Ready Preview Comment Nov 27, 2025 9:14pm
smart-todo-wum3 Error Error Nov 27, 2025 9:14pm

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enhances the verification flow by adding better handling of identifier (email/phone) management during registration and resend flows. The changes include updating the email sender domain, adding identifier URL parameters for improved resend functionality, adding defensive null checks, and creating a new helper endpoint to retrieve identifiers from tokens.

Key Changes:

  • Updated email sender from test domain to production domain (auth@soulledger.app)
  • Added identifier parameter passing in verification URLs and improved resend functionality with token-based identifier lookup
  • Added defensive validation for userId in verification flow and improved phone verification logging

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/lib/email-service.ts Updated sender email address from test domain to production domain
src/app/auth/verify-request/page.tsx Added identifier state management and token-based identifier lookup for resend functionality
src/app/api/auth/verify/route.ts Added defensive null check for userId before database operations
src/app/api/auth/resend-verification/route.ts Improved phone verification logging and added token return in development mode
src/app/api/auth/register/route.ts Added identifier URL parameters for verification flow and improved phone verification logging
src/app/api/auth/get-identifier-from-token/route.ts New helper endpoint to retrieve identifier from verification token for resend flows

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

setType(lookupData.type);
}
}
} catch (err) {
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The error handling here silently fails and proceeds to show a generic error message. However, the actual API call to /api/auth/get-identifier-from-token might fail for legitimate reasons (network error, server error) that should be distinguished from a missing identifier.

Consider logging the error for debugging purposes:

} catch (err) {
    console.error('Failed to fetch identifier from token:', err);
    // Silently fail - we'll show error below if identifier is still missing
}
Suggested change
} catch (err) {
} catch (err) {
console.error('Failed to fetch identifier from token:', err);

Copilot uses AI. Check for mistakes.
redirectUrl += `?identifier=${encodeURIComponent(identifierParam)}&type=${email ? 'EMAIL_VERIFICATION' : 'PHONE_VERIFICATION'}`;

if (invitationAccepted && inviterName) {
redirectUrl = `/welcome?accepted=true&inviterName=${encodeURIComponent(inviterName)}`;
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the invitation is accepted, the redirectUrl is overwritten on line 221, losing the identifier and type parameters that were added on line 218. This means that users who register via invitation won't have the identifier available for the resend verification functionality, breaking the resend flow for invited users.

Consider preserving the query parameters when setting the welcome redirect:

if (invitationAccepted && inviterName) {
    redirectUrl += `&accepted=true&inviterName=${encodeURIComponent(inviterName)}`;
    redirectUrl = redirectUrl.replace('/auth/verify-request', '/welcome');
}
Suggested change
redirectUrl = `/welcome?accepted=true&inviterName=${encodeURIComponent(inviterName)}`;
// Preserve existing query parameters and append accepted/inviterName
redirectUrl = redirectUrl.replace('/auth/verify-request', '/welcome') + `&accepted=true&inviterName=${encodeURIComponent(inviterName)}`;

Copilot uses AI. Check for mistakes.
// Build redirect URL if invitation was accepted
let redirectUrl = '/auth/verify-request';
// Pass identifier in URL for resend functionality
const identifierParam = email || phone!;
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The non-null assertion operator ! is used here, but it's unsafe since this code path executes when email is falsy. While TypeScript's type narrowing should ensure phone is defined, using the non-null assertion is risky and could lead to runtime errors if the logic changes.

Consider using an explicit check or optional chaining with a fallback:

const identifierParam = email || phone || '';
if (!identifierParam) {
    throw new Error('Either email or phone must be provided');
}

Copilot uses AI. Check for mistakes.
Comment on lines 1 to 53
import { NextRequest, NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";

/**
* Helper endpoint to get identifier (email/phone) from a verification token
* This is used by the resend verification flow when identifier is not in URL
*/
export async function POST(request: NextRequest) {
try {
const { token } = await request.json();

if (!token) {
return NextResponse.json(
{ error: "Token is required" },
{ status: 400 }
);
}

// Find verification token
const verificationToken = await prisma.verificationToken.findUnique({
where: { token },
include: { user: true },
});

if (!verificationToken) {
return NextResponse.json(
{ error: "Invalid verification token" },
{ status: 400 }
);
}

// Check if token is expired
if (verificationToken.expires < new Date()) {
return NextResponse.json(
{ error: "Verification token has expired" },
{ status: 400 }
);
}

// Return identifier and type
return NextResponse.json({
identifier: verificationToken.identifier,
type: verificationToken.type,
});
} catch (error) {
console.error("Get identifier from token error:", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 }
);
}
}

Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new helper endpoint /api/auth/get-identifier-from-token exposes a potential security risk. It allows anyone with a valid (even expired within 24 hours) token to query for user identifiers (email/phone), which could be exploited for user enumeration or information disclosure.

Consider adding rate limiting to this endpoint and/or requiring additional authentication. Additionally, consider whether this endpoint is necessary - the identifier could be stored in localStorage/sessionStorage during registration instead of fetching it from the server.

Copilot uses AI. Check for mistakes.
Comment on lines 93 to 102
if (type === "PHONE_VERIFICATION") {
// SMS implementation will be added later
console.log(`📱 SMS verification for phone numbers will be implemented soon`);
// For now, log the token in development mode
if (process.env.NODE_ENV === 'development') {
console.log(`📱 PHONE VERIFICATION TOKEN (RESEND) for ${identifier}:`, token);
console.log(`📱 SMS verification for phone numbers will be implemented soon`);
}
// In production, this should return an error or be handled differently
// For now, we'll return success but note that SMS wasn't actually sent
}
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In production, when NODE_ENV !== 'development', the phone verification flow silently succeeds without actually sending any SMS. This creates a confusing user experience where users receive a success message but never get their verification code.

The code should either:

  1. Return an error in production indicating SMS is not yet implemented
  2. Implement the SMS sending functionality
  3. Clearly document this limitation in the API response

Consider:

if (process.env.NODE_ENV === 'development') {
    console.log(`📱 PHONE VERIFICATION TOKEN (RESEND) for ${identifier}:`, token);
} else {
    return NextResponse.json(
        { error: "Phone verification is not yet implemented" },
        { status: 501 } // Not Implemented
    );
}

Copilot uses AI. Check for mistakes.
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback

Comment on lines 205 to 212
if (phone) {
// SMS implementation will be added later
console.log(`📱 SMS verification for phone numbers will be implemented soon`);
// For now, log the token in development mode
if (process.env.NODE_ENV === 'development') {
console.log(`📱 PHONE VERIFICATION TOKEN for ${phone}:`, token);
console.log(`📱 SMS verification for phone numbers will be implemented soon`);
}
}
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as in the resend-verification route: in production, phone verification silently succeeds without sending SMS, creating a confusing user experience where registration appears successful but users never receive their verification code.

Consider returning an error in production or implementing the SMS functionality:

if (process.env.NODE_ENV === 'development') {
    console.log(`📱 PHONE VERIFICATION TOKEN for ${phone}:`, token);
} else {
    return NextResponse.json(
        { error: "Phone verification is not yet implemented" },
        { status: 501 } // Not Implemented
    );
}

Copilot uses AI. Check for mistakes.
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link

Copilot AI commented Nov 27, 2025

@chemist-god I've opened a new pull request, #62, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link

Copilot AI commented Nov 27, 2025

@chemist-god I've opened a new pull request, #63, to work on those changes. Once the pull request is ready, I'll request review from you.

@chemist-god chemist-god merged commit 32f564d into main Nov 27, 2025
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants