commerce icon indicating copy to clipboard operation
commerce copied to clipboard

Customer Cookie

Open kogan007 opened this issue 3 years ago • 12 comments

Bigcommerce changed the cookie header in the response from doing login mutation. You get 2 cookies, you need to concat them. Until this is fixed, login won't work on the preview site

Also a separate question, have you guys come up with any way to login the customer on the bigcommerce frontend? A logged in customer on the nextjs frontend will not be logged in at checkout.

kogan007 avatar Apr 13 '21 21:04 kogan007

I am also having these issues! Very frustrating.

zachary-horvath avatar Apr 21 '21 14:04 zachary-horvath

I am also having these issues! Very frustrating.

Before when the cookie came from bigcommerce it came as a string, now it is an array, I think one called shop_token and the other one is called shopper-pref, so you just have to set those as cookies on your frontend, and then you can send it as a header with graphql query to get the current customer

kogan007 avatar Apr 22 '21 14:04 kogan007

I believe this may be a duplicate: https://github.com/vercel/commerce/issues/299

clockelliptic avatar May 06 '21 04:05 clockelliptic

I am also having these issues! Very frustrating.

Before when the cookie came from bigcommerce it came as a string, now it is an array, I think one called shop_token and the other one is called shopper-pref, so you just have to set those as cookies on your frontend, and then you can send it as a header with graphql query to get the current customer

the new token uses the key Shopper-Pref, but now SHOP_TOKEN is missing from cookies.... basically, this breaks wishlist and login functionality.

clockelliptic avatar May 06 '21 05:05 clockelliptic

I am also having these issues! Very frustrating.

Before when the cookie came from bigcommerce it came as a string, now it is an array, I think one called shop_token and the other one is called shopper-pref, so you just have to set those as cookies on your frontend, and then you can send it as a header with graphql query to get the current customer

the new token uses the key Shopper-Pref, but now SHOP_TOKEN is missing from cookies.... basically, this breaks wishlist and login functionality.

https://gist.github.com/jorgemasta/c709b63501344970026f3a3e7646cc77

try using this instead of the graphql cookie, it returns 3 cookies

kogan007 avatar May 06 '21 06:05 kogan007

I just solved the problem for myself. I set the Shopper-Pref cookie like so:

I changed the async function login(){...} definition in the file framework/bigcommerce/auth/login.ts (lines 32-71) to the following:

async function login({
  query = loginMutation,
  variables,
  res: response,
  config,
}: {
  query?: string
  variables: LoginVariables
  res: ServerResponse
  config?: BigcommerceConfig
}): Promise<LoginResult> {
  config = getConfig(config)

  const { data, res } = await config.fetch<RecursivePartial<LoginMutation>>(
    query,
    { variables }
  )

   // Set-Cookie returns several cookies, we want SHOP_TOKEN and Shopper-pref
   let shopToken = getCookie(res.headers.get('Set-Cookie'), 'SHOP_TOKEN');
   let prefToken = getCookie(res.headers.get('Set-Cookie'), 'Shopper-Pref');
   if (shopToken && typeof shopToken === 'string') {
     // In development, don't set a secure shopToken or the browser will ignore it
     if (process.env.NODE_ENV !== 'production') {
       shopToken = shopToken.replace(/; Secure/gi, '')
       shopToken = shopToken.replace(/; SameSite=none/gi, '; SameSite=lax')
     }
     response.setHeader(
       'Set-Cookie',
       concatHeader(response.getHeader('Set-Cookie'), shopToken)!
     )
     response.setHeader(
       'Set-Cookie',
       concatHeader(response.getHeader('Set-Cookie'), `${prefToken}`)!
     )
    }
    
    return {
      result: data.login?.result,
    }
}

clockelliptic avatar May 07 '21 02:05 clockelliptic

I just solved the problem for myself. I set the Shopper-Pref cookie like so:

I changed the async function login(){...} definition in the file framework/bigcommerce/auth/login.ts (lines 32-71) to the following:

async function login({
  query = loginMutation,
  variables,
  res: response,
  config,
}: {
  query?: string
  variables: LoginVariables
  res: ServerResponse
  config?: BigcommerceConfig
}): Promise<LoginResult> {
  config = getConfig(config)

  const { data, res } = await config.fetch<RecursivePartial<LoginMutation>>(
    query,
    { variables }
  )

   // Set-Cookie returns several cookies, we want SHOP_TOKEN and Shopper-pref
   let shopToken = getCookie(res.headers.get('Set-Cookie'), 'SHOP_TOKEN');
   let prefToken = getCookie(res.headers.get('Set-Cookie'), 'Shopper-Pref');
   if (shopToken && typeof shopToken === 'string') {
     // In development, don't set a secure shopToken or the browser will ignore it
     if (process.env.NODE_ENV !== 'production') {
       shopToken = shopToken.replace(/; Secure/gi, '')
       shopToken = shopToken.replace(/; SameSite=none/gi, '; SameSite=lax')
     }
     response.setHeader(
       'Set-Cookie',
       concatHeader(response.getHeader('Set-Cookie'), shopToken)!
     )
     response.setHeader(
       'Set-Cookie',
       concatHeader(response.getHeader('Set-Cookie'), `${prefToken}`)!
     )
    }
    
    return {
      result: data.login?.result,
    }
}

This did it for me. Using the getCookie function from @kogan007 I got this to work. Thank you all!

zachary-horvath avatar May 07 '21 13:05 zachary-horvath

@clockelliptic I have updated my code to cater for the multiple cookies as per your code above. However, when I'm redirected to the Bigcommerce checkout url, the customer is not logged in.

Any additional steps I need to take to make this work? Is your implementation based on using redirecting to Bigcommerce store checkout url as well?

srahman99 avatar Jun 16 '21 22:06 srahman99

@clockelliptic I have updated my code to cater for the multiple cookies as per your code above. However, when I'm redirected to the Bigcommerce checkout url, the customer is not logged in.

Any additional steps I need to take to make this work? Is your implementation based on using redirecting to Bigcommerce store checkout url as well?

https://github.com/bigcommerce/storefront-data-hooks

For starters the checkout needs to be on a subdomain of your headless implementation

kogan007 avatar Jun 17 '21 13:06 kogan007

Any news or merged request as been made on this issue ?

In my side, even using the getCookie from @kogan007's answer with @clockelliptic's code it does not work.

If I am already logged in when I proceed to checkout I got an error.

Capture d’écran 2021-10-17 à 22 40 59

And as @kogan007 said

For starters the checkout needs to be on a subdomain of your headless implementation

my stores domain are, I think, well configured, regarding https://github.com/bigcommerce/storefront-data-hooks#checkout

Capture d’écran 2021-10-17 à 23 43 18

Am I missing something else ?

Florian-crg avatar Oct 17 '21 20:10 Florian-crg

@Florian-crg Don't use the cookie code anymore. See this https://github.com/vercel/commerce/issues/531

You need to implement server session. Use the graphql login mutation and get the customer ID. Use the ID to create a customer impersonation token, and store it along with any other customer information you need in a secure session. Check out https://github.com/vvo/next-iron-session or Next Auth for implementing this.

Also for checkout code make sure the customer ID is an Int and not a string, and console.log the payload to make sure all the variables are there. You might be missing some environment variables.

kogan007 avatar Oct 18 '21 01:10 kogan007

Yes you're right one of my variables had something. When you mean create a customer impersonation token you're talking about the BC route /storefront/api-token-customer-impersonation ?

Because I do not see any mention in the storefront customer impersonation token about the customer ID.

I feel lost between the doc and what I understand in the issues opened about the login.

Florian-crg avatar Nov 09 '21 22:11 Florian-crg

Hey there! Thank you for your contribution. We have decided to take Next.js Commerce in a new direction and will be closing out current PRs and issues due to this change. Please see this PR for more details: #966

manovotny avatar Apr 18 '23 02:04 manovotny