rgz
rgz5mo ago

Using orCreateOrUpdate user in callback

Two problems here: 1. How can I get the tokenIdentity when creating a user, I need to get authSessionsId but I keep getting null. my approach was ${url}/${userId}/${tokenId} 2. I keep getting a 302 error but everything is still working correctly. GET /api/auth/signin/* 302 GET /api/auth/callback/* 302 This is the callback url I added on google: https://my-stuff-123.convex.site/api/auth/callback/google
callbacks: {
async createOrUpdateUser(ctx, args) {
let userId: Id<"users">;
const profile = args.profile as ExtendedProfile;
const provider = args.provider;

const existingUser = await ctx.db.query("users")
.filter((q) => q.eq(q.field("email"), args.profile.email))
.first();

if (existingUser) {
userId = existingUser._id as Id<"users">;

await ctx.db.patch<Id<"users">>(existingUser._id, {
providers: [...existingUser.providers, provider.id],
});

} else {
const newUser = await ctx.db.insert("users", {
email: profile?.email,
emailVerified: true,
emailVerificationTime: new Date().getTime(),
name: profile?.name,
firstName: profile?.given_name,
lastName: profile?.family_name,
image: profile?.image,
isOnboardingComplete: false,
orgIds: [],
providers: [provider.id],
tokenIdentifier: "",
});

userId = newUser as Id<"users">;
}

return userId;
},
},
callbacks: {
async createOrUpdateUser(ctx, args) {
let userId: Id<"users">;
const profile = args.profile as ExtendedProfile;
const provider = args.provider;

const existingUser = await ctx.db.query("users")
.filter((q) => q.eq(q.field("email"), args.profile.email))
.first();

if (existingUser) {
userId = existingUser._id as Id<"users">;

await ctx.db.patch<Id<"users">>(existingUser._id, {
providers: [...existingUser.providers, provider.id],
});

} else {
const newUser = await ctx.db.insert("users", {
email: profile?.email,
emailVerified: true,
emailVerificationTime: new Date().getTime(),
name: profile?.name,
firstName: profile?.given_name,
lastName: profile?.family_name,
image: profile?.image,
isOnboardingComplete: false,
orgIds: [],
providers: [provider.id],
tokenIdentifier: "",
});

userId = newUser as Id<"users">;
}

return userId;
},
},
5 Replies
rgz
rgzOP5mo ago
When an account is created, from the authTables - these are created - authAccounts created (with no emailVerified) - authRefreshTokens - authSessions - authVerifiers args response:
'args' {
existingUserId: null,
type: 'oauth',
provider: {
id: 'google',
name: 'Google',
type: 'oidc',
issuer: 'https://accounts.google.com',
style: {
brandColor: '#1a73e8'
},
options: {
authorization: {
params: {
authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth?prompt=consent&access_type=offline&response_type=code',
scope: 'https://mail.google.com https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/gmail.labels'
}
}
},
authorization: {
params: {
authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth?prompt=consent&access_type=offline&response_type=code',
scope: 'https://mail.google.com https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/gmail.labels'
}
},
wellKnown: 'https://accounts.google.com/.well-known/openid-configuration',
checks: [ 'pkce' ],
profile: [Function: defaultProfile],
account: [Function: defaultAccount],
clientId: ':key:',
clientSecret: ':closed_lock_with_key: '
},
profile: {
email: ':thumbsup:',
image: ':thumbsup:',
name: ':thumbsup:'
}
}
'args' {
existingUserId: null,
type: 'oauth',
provider: {
id: 'google',
name: 'Google',
type: 'oidc',
issuer: 'https://accounts.google.com',
style: {
brandColor: '#1a73e8'
},
options: {
authorization: {
params: {
authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth?prompt=consent&access_type=offline&response_type=code',
scope: 'https://mail.google.com https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/gmail.labels'
}
}
},
authorization: {
params: {
authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth?prompt=consent&access_type=offline&response_type=code',
scope: 'https://mail.google.com https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/gmail.labels'
}
},
wellKnown: 'https://accounts.google.com/.well-known/openid-configuration',
checks: [ 'pkce' ],
profile: [Function: defaultProfile],
account: [Function: defaultAccount],
clientId: ':key:',
clientSecret: ':closed_lock_with_key: '
},
profile: {
email: ':thumbsup:',
image: ':thumbsup:',
name: ':thumbsup:'
}
}
Any help would be insanely appreciated!
Michal Srb
Michal Srb5mo ago
I keep getting a 302 error
302 is not an error, it's a redirect (unfortunately our dashboard shows anything that's not 200 as red)
rgz
rgzOP5mo ago
@Michal Srb Yeah I just realized earlier ;P, thank you. But question while I have you here. What's the best way to get the tokenIdentity of a user being created through here? I noticed its site_url/user_id/session_id but I can't seem to get the session ID on creation.
Michal Srb
Michal Srb5mo ago
Why do you need the tokenIdentifier? The session hasn't been created yet when createOrUpdateUser runs, because the session stores the user ID, and the user might not have been created yet.
rgz
rgzOP5mo ago
It seemed standard from what I've been reading, bu no problem I can do without Thank you again for your help!