Generic oauth failing on missing email

Ouath providers that do not offer an email claim fail when using the generic oauth plugin with email_is_missing. Seeing how both Twitter and Tiktok allow for null emails, I would expect similar behavior in the generic oauth plugin as well. Or, alternatively, a way (a la Auth.js) to write and use custom providers. Moreover, mapProfileToUser has no affect on the above as this method is being invoked after the email check fails. One must use a custom getUserInfo method to get around this restriction. See here: https://github.com/better-auth/better-auth/blob/6a0898fa88d1a49163b711fdbfa05489e0301a2c/packages/better-auth/src/plugins/generic-oauth/index.ts#L606 Edit* the last part has been fixed in 1.2.6 so mapProfileToUser now works as expected. Still the outstanding issue of handling missing emails
13 Replies
thederezz
thederezz4w ago
Ran into the same problem, spent the last 2 days trying to figure it out and your comment helped me. Since in the code it's only checking if the email is there, you can literally put anything. In my case I just put the username.
getUserInfo: async (tokens) => {
const profile = await getUserProfile(tokens.accessToken);

return {
id: profile.id,
name: profile.name,
email: profile.username,
image: profile.threads_profile_picture_url,
emailVerified: true,
createdAt: new Date(),
updatedAt: new Date(),
};
}
getUserInfo: async (tokens) => {
const profile = await getUserProfile(tokens.accessToken);

return {
id: profile.id,
name: profile.name,
email: profile.username,
image: profile.threads_profile_picture_url,
emailVerified: true,
createdAt: new Date(),
updatedAt: new Date(),
};
}
shu-sin
shu-sinOP4w ago
Yes but I have proposed this in another place and haven't yet received a response. This is our current approach too however I am not sure if this has a knock-on effect in other areas of auth where the email is expected to be resolvable (invite emails, etc) I am looking now into options using the username plugin and/or remapping user.email attribute to something like a uniqueId that could be an email or username I do still think email should be nullable personally
xephyr
xephyr2w ago
Bumping this, email being required is a frustrating limitation.
xephyr
xephyr2w ago
Clerk get around this by presenting the user with a mandatory form to enter their email address after the first successful OAuth sign in, but before the user creation is successfully completed.
No description
xephyr
xephyr2w ago
If we insist on email being required, this UX would be acceptable to me. However since better-auth is headless, some API by which we can intercept the failure state => display a form of our choosing to the user => and subsequently resume the OAuth user creation flow would be ideal. @daveycodez Sorry for the unexpected ping, but looking through the code for better-auth-ui I don't see anything that would handle this state on your side. Is that correct?
shu-sin
shu-sinOP7d ago
I think this would be a more ideal solution and would prefer this. I haven't explored it much yet but this might be achievable with hooks, state and handling email_is_missing but I can't think of a clean way. Ideally the generic oauth plugin wouldn't fail before user creation and we could instead mark the user.email prop as optional but unique. I need to look at hooks during the callback lifecycle and see if there's anything usable. Looking breifly at the source code makes me think it's currently not possible Looks like there is no way to hook into this. An option I am exploring now is creating a temp email (similar to the anonymous plugin) and redirecting users into an onboarding flow with hooks if the user email is both unverified and contains a temp- string. Then I can push the user into an email and email verification flow
xephyr
xephyr7d ago
yeah my temporary solution is probably going to be email: fakeemail+{accountId}@whatever.com emailVerified: false and redirect to some UI to accept an email, and show a non-dismissible dialog asking for email on any other page if they try and circumvent it would prefer it to be baked in to better-auth but for now it should do the job
shu-sin
shu-sinOP7d ago
yeah similar. I believe they talked about this elsewhere that they planned on revamping the oauth flow for more control but no roadmap
daveycodez
daveycodez7d ago
What state exactly?
xephyr
xephyr7d ago
A genericOAuth2 provider not returning email, it doesn't look like its possible with the base library anyway but I thought I'd ask since if better-auth-ui found a way to handle it we could look at that
daveycodez
daveycodez7d ago
Oh no I think that's a backend thing
bekacru
bekacru6d ago
the problem with making email optional currently is typescript. You would need to sync that information between the auth server and client. We want to avoid requiring adding configs on both places for these things unless it's like very logical. We're palnning to make the user table to be user defined at somepoint until then assigning temp email should be the best option :))
xephyr
xephyr6d ago
Thanks for the clarification. From my perspective it isn't necessarily a need for email to be optional (though perhaps it is a need for other people). For me it is that I'd like authClient.signIn.oauth2()/auth.api.oauth2 to return a "partially complete" status with some identifier/token if: 1. The OAuth login was successful 2. The OAuth response did not include email This way we could handle requiring an email from the user, and then we could call something like authClient.signIn.resumeOauth2({ resumeToken, email }); to fully complete the auth. The fact it's required means we have to set a fake email as their email, then add a bunch of client code to block users from doing anything on the site until they give us their email (which people will try to avoid), etc.

Did you find this page helpful?