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
276 stars 124 forks source link

[FEATURE] Ability to have private proxy URL by default in useCommerceApi #1877

Open TayyabSalmanMRM1996 opened 3 days ago

TayyabSalmanMRM1996 commented 3 days ago

We've enabled useSLASPrivateClient on our side and would like to use the Password-less login (slasClient.authorizePasswordlessCustomer & slasClient.getPasswordLessAccessToken) on the client side.

As per the documentation: https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/use-a-slas-private-client.html, we need to add additional endpoints in ssr.js to have password-less login feature work.

But when we execute the slasClient.authorizePasswordlessCustomer/ slasClient.getPasswordLessAccessToken, these are taking us to the proxy: /mobify/proxy/api rather than /mobify/slas/private. That's not what we expect because we have enabled useSLASPrivateClient.

image

For now, we've manually set the proxy as follows, but we would like it to use /mobify/slas/private by default as it's using in oauth2/token call:

slasClient.clientConfig.proxy = ${appOrigin}/mobify/slas/private

const tokenPromise = slasClient.getPasswordLessAccessToken({
                body: {
                    pwdless_login_token: code,
                    grant_type: 'client_credentials',
                    hint: 'pwdless_login',
                    usid: cookie.get('usid')                
                },
                headers: {
                    'Authorization': 'Basic ' + btoa(${clientId}:${SLAS_SECRET_PLACEHOLDER}),
                    'Content-Type': 'application/x-www-form-urlencoded'
                }
            })

Can you look into this matter?

bendvc commented 3 days ago

@TayyabSalmanMRM1996 Thanks for reaching out!

Can you give me a little more information on your project details? Is your project a PWA generated with our generator? Can you give me a little more insight as to where slasClient object is coming from?

There are 2 thing that might be causing your issue:

  1. This is required in your case if you haven't set it already. But internally we have a setting that will only apply the private client proxy to a set of paths that pass a regex (below). You might have to modify this in order to have the proxy applied to your requests. (This is a setting in your ssr.js)
// A regex for identifying which SLAS endpoints the custom SLAS private
// client secret handler will inject an Authorization header.
// Do not modify unless a project wants to customize additional SLAS
// endpoints that we currently do not support (ie. /oauth2/passwordless/token)
applySLASPrivateClientToEndpoints: /\/oauth2\/token/
  1. The private proxy path is only set if you are using the client via commerce-sdk-react.

I can only guess, but its possible that the slasClient object isn't the client object that resides in the commerce-sdk-react lib and as such would not have the proxy set to use the /mobify/slas/private path.

If you are working within a PWA Kit project that was generated via our generator and not a custom headless solution, you would want to do something like below in order to use the client that has the correct proxy path value set on it.

const MyReactComponent = () => {
    const getPasswordLessAccessToken = useShopperLoginMutation('getPasswordLessAccessToken')

    useEffect(() => {
         getPasswordLessAccessToken.mutate({...})
    }, [])

    return (<div>Hi 👋</div>)
}

Please let me know if you have any question.

TayyabSalmanMRM1996 commented 3 days ago

Thanks @bendvc - I have the following setting in the srr.js:

const options = {
    ...
    ...
    useSLASPrivateClient: true,
    applySLASPrivateClientToEndpoints: /oauth2\/(token|passwordless\/(login|token))/
}

I'm triggering the password-less API in the following way:

const sendToken = useShopperLoginMutation('authorizePasswordlessCustomer')
await sendToken.mutate({
                body: {
                    userId: email,
                    channel_id: site?.id,
                    mode: 'callback',
                    callback_uri: ${hostUrl}/s/US/passwordlesslogin/callback?secret=${SLAS_SECRET_PLACEHOLDER},
                    user_id: email,
                    usid: cookie.get('usid')                
                },
                headers: {
                    'Authorization': 'Basic ' + btoa(`${clientId}:${SLAS_SECRET_PLACEHOLDER}`),
                    'Content-Type': 'application/x-www-form-urlencoded'
                }
            })

But It's still not going to correct proxy /mobify/slas/private:

image
bendvc commented 2 days ago

/mobify/slas/private

@TayyabSalmanMRM1996 I took your example and was able to get it to work by setting the enablePWAKitPrivateClient prop on the CommerceSDKReactProvider. I found these comment in the code below:

 * Note: The provider can enable SLAS Private Client mode in 2 ways.
 * `enablePWAKitPrivateClient` sets commerce-sdk-react to work with the PWA proxy
 * `/mobify/slas/private` to set the private client secret. PWA users should use
 * this option.
 *
 * Non-PWA Kit users can enable private client mode by passing in a client secret
 * directly to the provider. However, be careful when doing this as you will have
 * to make sure the secret is not unexpectedly exposed to the client.
 *
 * @returns Provider to wrap your app with
 */

You'll find the provider in you _app-config component and you can add the above prop there, setting the value to true.

If you've already done this, please let me know.

TayyabSalmanMRM1996 commented 2 days ago

@bendvc yes, we've already done this, but it is still not calling /mobify/slas/private:

<CommerceApiProvider .... clientId={commerceApiConfig.parameters.clientId} .... redirectURI={${appOrigin}/callback`} proxy={${appOrigin}${commerceApiConfig.proxyPath}} .... enablePWAKitPrivateClient={true}

....

`