Description
Description
When using the Email OTP provider (@convex-dev/auth/providers/Email
), there's currently no way to pass additional user profile information during the authentication process, unlike other providers such as Password authentication which support a profile
method.
Current Behavior
Currently, when using Email OTP authentication:
- We can pass data from client to backend using FormData
- The
createOrUpdateUser
callback receives this data, but custom fields are not accessible throughargs.profile
- This forces us to implement workarounds like updating the user document after authentication
Example of current implementation:
// Client side (verify-email.tsx)
const formData = new FormData();
formData.append('email', email);
formData.append('firstName', firstName); // Custom field
await signIn('resend-otp', formData);
// Server side (ResendOTP.ts)
export const ResendOTP = Email<DataModel>({
id: "resend-otp",
apiKey: process.env.AUTH_RESEND_KEY,
maxAge: 60 * 20,
// No way to access custom fields here
});
Desired Behavior
Similar to the Password provider, it would be helpful to have a profile
method in the Email provider configuration:
export const ResendOTP = Email<DataModel>({
id: "resend-otp",
apiKey: process.env.AUTH_RESEND_KEY,
maxAge: 60 * 20,
profile(params, ctx) {
// ctx can also be used here to update other user fields
return {
email: params.email as string,
firstName: params.firstName as string,
// Other custom fields
};
},
});
This would allow:
- Type-safe access to custom fields
- Validation of fields during authentication
- Consistent behavior with other authentication providers
- Cleaner implementation without needing post-authentication updates
Use Cases
- Collecting user details during registration (name, preferences, etc.)
- Setting user roles or permissions during signup
- Storing additional metadata about the authentication process
- Creating complete user profiles during the initial authentication
Workaround
Currently using a workaround by updating the user document after authentication is successful:
useEffect(() => {
if (isAuthenticated) {
updateUser({
firstName: params.firstName,
lastName: params.lastName,
// Other fields
});
}
}, [isAuthenticated]);
This works but:
- Requires an additional database operation
- Creates a small delay in having complete user data
- Could potentially lead to race conditions
- Less elegant than handling it during the authentication process
Additional Context
This feature would bring the Email OTP provider in line with other authentication providers - Anonymous and Password in terms of functionality and would improve the developer experience when implementing email-based authentication flows.