Kıte
Kıte5mo ago

Convex Auth Google OAuth

Hello I've tried looking in the docs and can't find any relative to this problem. I'm trying to separate name and last name from Google Auth but when I do this code it doesn't let me login nor create new user. any idea for this?
export const { auth, signIn, signOut, store } = convexAuth({
providers: [
Google({
profile: (prof) => {
return {
...prof,
id: prof.id,
email: prof.email,
name: prof.give_name,
lastname: prof.last_name,
image: prof.picture
};
},
}),
],
});
export const { auth, signIn, signOut, store } = convexAuth({
providers: [
Google({
profile: (prof) => {
return {
...prof,
id: prof.id,
email: prof.email,
name: prof.give_name,
lastname: prof.last_name,
image: prof.picture
};
},
}),
],
});
this is my custom schema for user
users: defineTable({
email: v.optional(v.string()),
emailVerificationTime: v.optional(v.float64()),
image: v.optional(v.string()),
isAnonymous: v.optional(v.boolean()),
name: v.optional(v.string()),
lastname: v.optional(v.string()),
phone: v.optional(v.string()),
phoneVerificationTime: v.optional(v.float64()),
})
.index("email", ["email"])
.index("phone", ["phone"])
.searchIndex("search_by_email", {
searchField: "email",
})
.searchIndex("search_by_name", { searchField: "name" }),
users: defineTable({
email: v.optional(v.string()),
emailVerificationTime: v.optional(v.float64()),
image: v.optional(v.string()),
isAnonymous: v.optional(v.boolean()),
name: v.optional(v.string()),
lastname: v.optional(v.string()),
phone: v.optional(v.string()),
phoneVerificationTime: v.optional(v.float64()),
})
.index("email", ["email"])
.index("phone", ["phone"])
.searchIndex("search_by_email", {
searchField: "email",
})
.searchIndex("search_by_name", { searchField: "name" }),
30 Replies
erquhart
erquhart5mo ago
I believe you only have access to the properties on the provider's Profile. Here's Google's (source):
export interface GoogleProfile extends Record<string, any> {
aud: string
azp: string
email: string
email_verified: boolean
exp: number
family_name?: string
given_name: string
hd?: string
iat: number
iss: string
jti?: string
locale?: string
name: string
nbf?: number
picture: string
sub: string
}
export interface GoogleProfile extends Record<string, any> {
aud: string
azp: string
email: string
email_verified: boolean
exp: number
family_name?: string
given_name: string
hd?: string
iat: number
iss: string
jti?: string
locale?: string
name: string
nbf?: number
picture: string
sub: string
}
I'd expect type errors and possibly runtime errors in your case, are you seeing either?
Kıte
KıteOP5mo ago
Yeah I already saw that GoogleProfile Types, maybe I mistype the lastname because of github example. I'll try that later. Btw is there no wrong with my code? Ia just the family_name instead of last_name?
erquhart
erquhart5mo ago
There's no id or image field either unless there's some type extending that I missed in the source. Looks right, but if it's not logging the user in then something is off. Can you verify that there are no runtime or type errors on login? (or sign up)
Kıte
KıteOP5mo ago
If I didn't include id it will retrieve it by default ? there's a picture in google tho.
erquhart
erquhart5mo ago
It's supposed to deep merge, but the type does not include an id field. Google has picture, you used image.
Kıte
KıteOP5mo ago
yeah I have image in my DB and I call
image: prof.picture
image: prof.picture
is that wrong? Should I change my schema to picture also?
erquhart
erquhart5mo ago
Oh I was misreading, sorry - yeah you're fine there, just the keys on profile need to match the provider type The typos in your code are give_name -> given_name, and last_name -> family_name. You're spreading the profile so you don't need to explicitly add id.
Kıte
KıteOP5mo ago
still this doesn't let me login. I also add firstname in my schema, and even with or without spreading prof still doesn't work I am using, App Router with SSA. normal Google provider works perfectly.
export const { auth, signIn, signOut, store } = convexAuth({
providers: [
Google({
id: "google",
profile: (prof: GoogleProfile) => {
return {
firstname: prof.given_name,
lastname: prof.family_name,
image: prof.picture,
};
},
}),
],
});
export const { auth, signIn, signOut, store } = convexAuth({
providers: [
Google({
id: "google",
profile: (prof: GoogleProfile) => {
return {
firstname: prof.given_name,
lastname: prof.family_name,
image: prof.picture,
};
},
}),
],
});
erquhart
erquhart5mo ago
Can you give more info to help me understand what's happening. When you say it's not logging in, is there an error, what specifically is happening
Kıte
KıteOP5mo ago
there's no error, its just not redirecting to my dashboard and also did not create new user. Its like nothing happen why tagged this as resolve? I still can't set user firstname and lastname from google.
export const { auth, signIn, signOut, store } = convexAuth({
providers: [
Google({
profile: (prof: GoogleProfile, token: TokenSet) => {
const user: Awaitable<User> = {
firstname: prof.given_name,
lastname: prof.family_name,
} as User;
return user;
},
}),
],
});
export const { auth, signIn, signOut, store } = convexAuth({
providers: [
Google({
profile: (prof: GoogleProfile, token: TokenSet) => {
const user: Awaitable<User> = {
firstname: prof.given_name,
lastname: prof.family_name,
} as User;
return user;
},
}),
],
});
erquhart
erquhart5mo ago
Not sure why it got tagged resolved Just thinking how to narrow down possible causes. You mentioned it works if you don't pass a config, so try passing a minimal config. Like just a profile function that returns the profile unchanged.
Michal Srb
Michal Srb5mo ago
Does your schema have a firstname field? Have you been looking at your Convex dashboard logs to see what errors you're getting? https://dashboard.convex.dev/deployment/logs
Convex Dashboard
Manage your Convex apps
Kıte
KıteOP5mo ago
Yup, I changed my schema Yeah, it works without a config. Now I just made user onboard to make sure that they can fill up firstname and lastname.
Michal Srb
Michal Srb5mo ago
What errors are you seeing on your Convex dashboard?
Kıte
KıteOP5mo ago
No description
Kıte
KıteOP5mo ago
I also tried to spread prof
Michal Srb
Michal Srb5mo ago
You must return an id which is a string from the profile method.
Kıte
KıteOP5mo ago
should I return id like this
id: prof.sub,
id: prof.sub,
? if then I will update my schema to have id and _id ?
Michal Srb
Michal Srb5mo ago
id goes to the authAccounts, it doesn't flow to the users table (this is not very clear tbh).
Kıte
KıteOP5mo ago
yeah, even I followed Authjs instructions, I still getting the same error. Maybe I should go with onboarding for a while.
Michal Srb
Michal Srb5mo ago
@Kıte are you still blocked?
Kıte
KıteOP5mo ago
yep I'm using @convex-dev/auth 0.0.55
Michal Srb
Michal Srb5mo ago
It shouldn't matter but upgrade to latest. Then let me know what error you're getting in your Convex dashboard. And please share your Google provider setup from auth.ts
Kıte
KıteOP5mo ago
import { convexAuth } from "@convex-dev/auth/server";
import Google, { GoogleProfile } from "@auth/core/providers/google";
import { Awaitable, TokenSet, User } from "@auth/core/types";

export const { auth, signIn, signOut, store } = convexAuth({
providers: [
Google({
profile: (prof: GoogleProfile, token: TokenSet) => {
return {
googleId: prof.sub,
firstname: prof.given_name,
lastname: prof.family_name,
image: prof.picture,
};
},
}),
],
});

// export const { auth, signIn, signOut, store } = convexAuth({
// providers: [Google],
// });
import { convexAuth } from "@convex-dev/auth/server";
import Google, { GoogleProfile } from "@auth/core/providers/google";
import { Awaitable, TokenSet, User } from "@auth/core/types";

export const { auth, signIn, signOut, store } = convexAuth({
providers: [
Google({
profile: (prof: GoogleProfile, token: TokenSet) => {
return {
googleId: prof.sub,
firstname: prof.given_name,
lastname: prof.family_name,
image: prof.picture,
};
},
}),
],
});

// export const { auth, signIn, signOut, store } = convexAuth({
// providers: [Google],
// });
When I start clicking google login button it shows the 302 error from "api/auth/signIn/*" when I select google account the other 2 error will show.
No description
Michal Srb
Michal Srb5mo ago
Try this:
import { convexAuth } from "@convex-dev/auth/server";
import Google, { GoogleProfile } from "@auth/core/providers/google";
import { Awaitable, TokenSet, User } from "@auth/core/types";

export const { auth, signIn, signOut, store } = convexAuth({
providers: [
Google({
profile: (prof: GoogleProfile, token: TokenSet) => {
return {
id: prof.sub,
googleId: prof.sub,
firstname: prof.given_name,
lastname: prof.family_name,
image: prof.picture,
};
},
}),
],
});
import { convexAuth } from "@convex-dev/auth/server";
import Google, { GoogleProfile } from "@auth/core/providers/google";
import { Awaitable, TokenSet, User } from "@auth/core/types";

export const { auth, signIn, signOut, store } = convexAuth({
providers: [
Google({
profile: (prof: GoogleProfile, token: TokenSet) => {
return {
id: prof.sub,
googleId: prof.sub,
firstname: prof.given_name,
lastname: prof.family_name,
image: prof.picture,
};
},
}),
],
});
(You can console.log the prof.sub to check it's a string, but I suspect the above will unblock you)
Kıte
KıteOP5mo ago
it can't detect id because I don't have id in my schema, (actually I already done this.)
No description
Kıte
KıteOP5mo ago
and
console.log(prof.sub === typeof String);
console.log(prof.sub === typeof String);
return false I also even try .toString() or as String.
Kıte
KıteOP5mo ago
No description
Michal Srb
Michal Srb5mo ago
I think it's a string already. The check would be console.log(typeof prof.sub === "string"). But if it wasn't a string you'd get a specific error message about it. The other error can be unrelated. Can you clear any auth documents and try the flow from scratch? I expect the "nonexisting document" error is coming from account linking. You have an account in the authAccounts table pointing to a deleted user. If you delete a user you must also delete all its accounts. (something the library should provide an affordance for, that's tbd)
Kıte
KıteOP5mo ago
thanks, I didn't realize clrearing docs will solve the problem

Did you find this page helpful?