SalesforceCommerceCloud / pwa-kit

React-based JavaScript frontend framework to create a progressive web app (PWA) storefront for Salesforce B2C Commerce.
https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/pwa-kit-overview.html
BSD 3-Clause "New" or "Revised" License
285 stars 138 forks source link

[BUG] Reset Password is not working #363

Open stm-dschulz opened 2 years ago

stm-dschulz commented 2 years ago

Summary

When using "Reset Password" the app returns the error "Your access-token is invalid and could not be used to identify the API client.". This happens regardless if the email is known to the system or not.

screenshot 2022-01-28 um 11 10 16

Steps To Reproduce

Expected result

Actual result

System Information (as applicable)

Browser: Chrome Version 97.0.4692.99 Node version: pwa-kit version: 1.3 Desktop OS: Mobile Device Info:

Happens on the official test system, on our test system and locally.

Additional information

I tried to trace down this to myself but was not successful.

It seems that the underlying call

https://{{short_code}}.api.commercecloud.salesforce.com/customer/shopper-customers/v1/organizations/{{organization_id}}/customers/password/actions/create-reset-token?siteId={{site_id}}

is executed with the SLAS token and this does not work. I can reproduce the same error in Postman.

The documentation actually says to use the AM based token (https://account.demandware.com/dwsso/oauth2/access_token). But this did also not work for me and returns

"Your access-token is valid, but you have no permissions to access the resource.".

The related OCAPI permission is set but there is no related AuthZ Scope that could be set.

kevinxh commented 2 years ago

Hi @stm-dschulz! This is a known issue/gap that the SLAS password reset flow currently doesn't work in the PWA.

My understanding is that the SLAS password reset endpoint (/customers/password/actions/create-reset-token?siteId={{site_id}}) doesn't support shopper JWT. This endpoint is for admins to reset password on behalf of shoppers.

I believe SLAS team is actively working on this issue. For now, if you need to implement this feature, you need to create a server side endpoint that grabs AM OAuth token, call the endpoint and create a password reset token, then you use that token to reset password using another endpoint /reset.

johnboxall commented 2 years ago

To offer an alternative, you can also bridge the current API gap using OCAPI hooks.

https://github.com/SalesforceCommerceCloud/ocapi_hooks_collection shows how to do this.

  1. It extends the dw.ocapi.shop.customers.password_reset.afterPOST to send a password reset email.
  2. It extends dw.ocapi.shop.auth.beforePOST to accept the reset token and attempt to set the users password.

You can review the tests for the basic flow:

https://github.com/SalesforceCommerceCloud/ocapi_hooks_collection/blob/main/test/integration/ocapi/04_passwordReset.js

I'm going to leave this issue open until we've resolved it in the default generated PWA.

stm-dschulz commented 2 years ago

Hi @kevinxh , @johnboxall , thx for the reply.

We will use the OCAPI solution to fix this. Whats your opinion - makes sense to contribute this fix?

johnboxall commented 2 years ago

Hey @stm-dschulz,

I don't believe a fix can be contributed in the scope of this repo right now.

Going forward, one of three things will happen:

  1. SLAS will add a password reset feature which we will adopt in the PWA Kit. When the feature drops, a PR that integrates it would be accepted.
  2. We'll adopt a DW hooks cartridges that will always be deployed alongside the PWA Kit.
  3. The underlying SCAPI/OCAPI will change to remove the requirement for a non-shopper OAuth token.

Until one of these three things happen, I believe this issue is blocked.

If yah'll do end up going the OCAPI route, I'd appreciate if you upstreamed any changes to https://github.com/SalesforceCommerceCloud/ocapi_hooks_collection, as if we choose to formally adopt a hooks cartridge for PWA Kit, this will most likely be our starting point.

echessman commented 1 year ago

Hello @stm-dschulz Thank you for the feedback. We will be looking into this in the first half of 2023.

johnboxall commented 1 year ago

Quick note, the OCAPI Shop /customers/password_reset endpoint has "different" authentication than most other APIs and does not respect SLAS JWTs passed to it.

To call it, you'll need to use regular OCAPI Auth:

https://documentation.b2c.commercecloud.salesforce.com/DOC2/topic/com.demandware.dochelp/content/b2c_commerce/topics/account_manager/b2c_account_manager_add_api_client_id.html

A trick I commonly use is to create a "super" API Client that can be used both for SLAS and OCAPI calls.

To do this:

  1. Create an API Client in AM, noting it's client ID
  2. Create an API Client in SLAS, using the AM client ID

Thanks!

ashwinrath commented 1 year ago

A following question is : what OCPI api is to be used to actually reset the password after obtaining the reset token using the afterPOST hook described above ?

johnboxall commented 1 year ago

Once "Environment Variables" ships in Managed Runtime ~2023 June, our recommended approach will likely to be to use the SLAS Password Reset API with a callback URI to MRT:

https://developer.salesforce.com/docs/commerce/commerce-api/guide/slas-password-reset.html

Then MRT can send the email using a configured email service provider.

Alternatively, you could set a B2C Commerce controller as callback URI, and use its email sending capabilities.

johnboxall commented 1 year ago

Environment Variables for Managed Runtime has now shipped: https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/managed-runtime-administration.html#environment-variables

You can use environment variables to inject the Client ID + Secret of a SLAS Private client into your code, then create an Express.js handler to forward requests to the relevant password reset APIs and optionally send a password reset email through your ESP.

https://developer.salesforce.com/docs/commerce/commerce-api/guide/slas-password-reset.html

anmolsri15 commented 1 year ago

To fix the Password Reset functionality in your Progressive Web App (PWA), follow these steps: Step 1: Generate an Admin token by accessing the following URL: https://account.demandware.com/dw/oauth2/access_token Note: Make sure to set the scope in the request Body to SALESFORCE_COMMERCE_API: sfcc.shopper-customers.login Step 2: Once you have the token generated in Step 1, use it for Authorization and refer to the documentation provided at the following link: https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-customers?meta=getResetPasswordToken At this step, you will receive a resetToken, which will be used for the password reset process in Step 3. Step 3: Again, use the Token generated in Step 1(or generate a new one) for Authorization and follow the documentation provided at the following link: https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-customers?meta=resetPassword (edited)

Thanks Anmol Srivastava

lisa-mcgerr commented 1 year ago

Hello,

I am working on correcting the password reset functionality and I have tried implementing the above 3 steps. I am able to get the admin access token from the dwoauth/dwsso/oauth2/access_token call with the scope as mentioned in step one. However, when I try to use this token for authorization for step two /create-reset-token?siteId=SiteExample I am getting a 401 Unauthorized error "Your access-token is invalid and could not be used to identify the API client." Does anyone know how I can fix this? And am I able to add an authorization header to the SCAPI packages/template-retail-react-app/app/commerce-api/hooks/useCustomer.js getResetPasswordToken call?

Thanks!

wjhsf commented 1 year ago

@lisa-mcgerr it seems like you may have not set up the access token correctly. But, as per @johnboxall's comment, you should be able to do this by following the SLAS Password Reset guide, which should not require an OCAPI access token.

BeqaLobzhanidze commented 6 months ago

Hi , still have this problem . does someone has working example how can I fix this 401 unauthorised error during "reset-password" flow ?

git2gus[bot] commented 5 months ago

This issue has been linked to a new work item: W-15953350