W
Wasp•4w ago
BeReal

Get email from user auth by google

Hi I just have Google Auth activated as a means of authenticating, how can I get the e-mail? import type { GenerateCheckoutSession, GetCustomerPortalUrl } from 'wasp/server/operations'; import type { FetchCustomerPortalUrlArgs } from './paymentProcessor'; import { PaymentPlanId, paymentPlans } from '../payment/plans'; import { paymentProcessor } from './paymentProcessor'; import { HttpError } from 'wasp/server'; export type CheckoutSession = { sessionUrl: string | null; sessionId: string; }; export const generateCheckoutSession: GenerateCheckoutSession<PaymentPlanId, CheckoutSession> = async ( paymentPlanId, context ) => { if (!context.user) { throw new HttpError(401); } const userId = context.user.id; const userEmail = context.user.email; if (!userEmail) { throw new HttpError( 403, 'User needs an email to make a payment. If using the usernameAndPassword Auth method, switch to an Auth method that provides an email.' ); } const paymentPlan = paymentPlans[paymentPlanId]; const { session } = await paymentProcessor.createCheckoutSession({ userId, userEmail, paymentPlan, prismaUserDelegate: context.entities.User }); return { sessionUrl: session.url, sessionId: session.id, }; }; export const getCustomerPortalUrl: GetCustomerPortalUrl<void, string | undefined> = async (_args, context) => { if (!context.user) { throw new HttpError(401); } return paymentProcessor.fetchCustomerPortalUrl({ userId: context.user.id, prismaUserDelegate: context.entities.User, }); }; Here I get the error: User needs an email to make a payment. If using the usernameAndPassword Auth method, switch to an Auth method that provides an email. How could I get the email from the user here?
10 Replies
kapa.ai
kapa.ai•4w ago
Hi @BeReal. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To get the email from a user authenticated with Google Auth in Wasp, you can use the getEmail helper function provided by Wasp. Here's how you can modify your code to retrieve the email:
import { getEmail } from 'wasp/auth'

export const generateCheckoutSession: GenerateCheckoutSession<PaymentPlanId, CheckoutSession> = async (
paymentPlanId,
context
) => {
if (!context.user) {
throw new HttpError(401);
}
const userId = context.user.id;
const userEmail = getEmail(context.user);
if (!userEmail) {
throw new HttpError(
403,
'User needs an email to make a payment. Please ensure your Google account has an associated email.'
);
}

// Rest of your code...
}
import { getEmail } from 'wasp/auth'

export const generateCheckoutSession: GenerateCheckoutSession<PaymentPlanId, CheckoutSession> = async (
paymentPlanId,
context
) => {
if (!context.user) {
throw new HttpError(401);
}
const userId = context.user.id;
const userEmail = getEmail(context.user);
if (!userEmail) {
throw new HttpError(
403,
'User needs an email to make a payment. Please ensure your Google account has an associated email.'
);
}

// Rest of your code...
}
The getEmail function is designed to retrieve the user's email from their auth identities, including Google Auth. This function will return the user's email or null if no email is found Accessing the Auth Fields (https://wasp-lang.dev/docs/auth/entities#accessing-the-auth-fields). It's important to note that when using Google Auth, the email should be available as long as you've requested the appropriate scopes. By default, Wasp doesn't specify any scopes for Google Auth, so you might need to configure this in your main.wasp file Google Auth Overrides (https://wasp-lang.dev/docs/auth/social-auth/google#overrides):
auth: {
userEntity: User,
methods: {
google: {
configFn: import { googleAuthConfig } from "@server/auth/googleAuth.js",
}
},
// ...
}
auth: {
userEntity: User,
methods: {
google: {
configFn: import { googleAuthConfig } from "@server/auth/googleAuth.js",
}
},
// ...
}
Then in your googleAuth.js file:
export const googleAuthConfig = {
scope: ['profile', 'email']
}
export const googleAuthConfig = {
scope: ['profile', 'email']
}
This configuration ensures that you request the 'email' scope from Google, which should make the email available in your application. If you're still encountering issues after making these changes, you might want to double-check your Google Auth configuration and ensure that the email scope is being properly requested and received. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @BeReal, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
miho
miho•4w ago
Google | Wasp
Wasp supports Google Authentication out of the box.
BeReal
BeRealOP•4w ago
Thanks! @kapa.ai your suggestion results in a type error: [ Wasp ] ext-src/payment/operations.ts(23,30): error TS2345: Argument of type 'AuthUser' is not assignable to parameter of type 'UserEntityWithAuth'. [ Wasp ] Property 'auth' is missing in type 'AuthUser' but required in type '{ auth: MakeAuthEntityWithIdentities<Pick<GetResult<{ providerName: string; providerUserId: string; providerData: string; authId: string; }, unknown> & {}, "providerName" | "providerUserId">>; }'. const userEmail = getEmail(context.user);
kapa.ai
kapa.ai•4w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I apologize for the confusion in my previous answer. You're right, and the error message provides important information about the type mismatch. Let's address this issue with a more accurate solution based on the Wasp documentation. The getEmail function expects a UserEntityWithAuth type, which includes the auth property. However, the context.user in your case is of type AuthUser, which doesn't have the auth property directly accessible. To resolve this, we need to use a different approach. Wasp provides a findUserIdentity helper function that can be used to find the Google auth identity and extract the email from there. Here's how you can modify your code:
import { findUserIdentity } from 'wasp/auth'

export const generateCheckoutSession: GenerateCheckoutSession<PaymentPlanId, CheckoutSession> = async (
paymentPlanId,
context
) => {
if (!context.user) {
throw new HttpError(401);
}
const userId = context.user.id;

const googleIdentity = findUserIdentity(context.user, 'google');
const userEmail = googleIdentity?.providerUserId;

if (!userEmail) {
throw new HttpError(
403,
'User needs an email to make a payment. Please ensure your Google account has an associated email.'
);
}

// Rest of your code...
}
import { findUserIdentity } from 'wasp/auth'

export const generateCheckoutSession: GenerateCheckoutSession<PaymentPlanId, CheckoutSession> = async (
paymentPlanId,
context
) => {
if (!context.user) {
throw new HttpError(401);
}
const userId = context.user.id;

const googleIdentity = findUserIdentity(context.user, 'google');
const userEmail = googleIdentity?.providerUserId;

if (!userEmail) {
throw new HttpError(
403,
'User needs an email to make a payment. Please ensure your Google account has an associated email.'
);
}

// Rest of your code...
}
This solution uses the findUserIdentity function, which is designed to work with the AuthUser type Accessing the Auth Fields (https://wasp-lang.dev/docs/auth/entities#finduseridentity). The providerUserId for Google auth is typically the user's email address. If you're still encountering issues, you might want to check the structure of your context.user object. You can log it to the console to see what fields are available:
console.log(JSON.stringify(context.user, null, 2));
console.log(JSON.stringify(context.user, null, 2));
This will help you understand the exact structure of the user object you're working with. Remember, the availability of the email depends on the scopes you've requested from Google. Ensure you've configured the correct scopes as mentioned in the previous answer Google Auth API Reference (https://wasp-lang.dev/docs/auth/social-auth/google#api-reference-part-1). If you're still facing issues after these changes, please provide more details about your auth configuration in main.wasp and any relevant server-side auth setup. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @BeReal, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
BeReal
BeRealOP•4w ago
Module '"wasp/auth"' has no exported member 'findUserIdentity'.ts(2305) @kapa.ai
kapa.ai
kapa.ai•4w ago
Let me check the knowledge base for you again. One moment! :books:
MEE6
MEE6•4w ago
Wohooo @BeReal, you just became a Waspeteer level 2!
kapa.ai
kapa.ai•4w ago
---------------------- I apologize for the confusion in my previous answer. It seems that the findUserIdentity function is not available in the way I suggested. Let's try a different approach using the correct imports and functions available in Wasp. Based on the latest Wasp documentation, we should use the getEmail function from the client-side auth module. Here's how you can modify your code:
import { getEmail } from 'wasp/client/auth'

export const generateCheckoutSession: GenerateCheckoutSession<PaymentPlanId, CheckoutSession> = async (
paymentPlanId,
context
) => {
if (!context.user) {
throw new HttpError(401);
}
const userId = context.user.id;

const userEmail = getEmail(context.user);

if (!userEmail) {
throw new HttpError(
403,
'User needs an email to make a payment. Please ensure your Google account has an associated email.'
);
}

// Rest of your code...
}
import { getEmail } from 'wasp/client/auth'

export const generateCheckoutSession: GenerateCheckoutSession<PaymentPlanId, CheckoutSession> = async (
paymentPlanId,
context
) => {
if (!context.user) {
throw new HttpError(401);
}
const userId = context.user.id;

const userEmail = getEmail(context.user);

if (!userEmail) {
throw new HttpError(
403,
'User needs an email to make a payment. Please ensure your Google account has an associated email.'
);
}

// Rest of your code...
}
The getEmail function should be imported from wasp/client/auth as shown in the Discord support thread (https://discord.com/channels/686873244791210014/1215383457392238662) where a community member suggested this import path. If you're still encountering issues, it's possible that your Wasp version might be different from the latest documentation. In that case, you might want to check your package.json file to verify the Wasp version you're using and consult the documentation specific to that version. Also, make sure that your main.wasp file is correctly configured for Google authentication. Here's an example of how it should look:
app myApp {
auth: {
userEntity: User,
methods: {
google: {}
},
onAuthFailedRedirectTo: "/login"
}
}
app myApp {
auth: {
userEntity: User,
methods: {
google: {}
},
onAuthFailedRedirectTo: "/login"
}
}
If you continue to face issues, please provide more details about your Wasp version and the contents of your main.wasp file related to authentication. This will help in providing a more accurate solution tailored to your specific setup. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @BeReal, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
miho
miho•4w ago
I'd recommend reading the docs because Kapa sometimes gets things wrong and you might be trying to use code that is made up 🙂 sometimes it's correct and very useful!
BeReal
BeRealOP•4w ago
Haha tahnsk @miho that certainly seems the case here, the docs are not entirely clear to me becuase I do not fully understand what is implied. Perhaps you might know? Are the docs suggesting me to use the Google API to get the email from the user or is it suggesting to use userSignupFields to get the email?
Want results from more Discord servers?
Add your server