Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@W-15490276@ Better refresh token error logging for V3 #2028

Merged
merged 13 commits into from
Oct 1, 2024

Conversation

vcua-mobify
Copy link
Contributor

@vcua-mobify vcua-mobify commented Sep 25, 2024

Related to #1829

There are a few ways in which a call to SLAS to consume a refresh token can fail. For example, the client id the refresh token is associated with might be different from the client id included with the request.

Before this change, the error logging for a failed refresh token call only triggered when SLAS returned the error message 'invalid refresh token'.

This change opens up the logging so that any failed refresh token call error message is logged.

This change also updates new guest login to also log error messages.

Testing the changes:
Refresh login (note: the refresh login request happens client side only):

  1. Start the app with these changes locally (this will start the app against zzrf-001)
  2. Delete the access token in your local store
  3. On a different browser window, open up https://test.phased-launch-testing.com/ and grab the refresh token
  4. Copy the refresh token from test.phased-launch-testing into the cc-nx-g cookie on the tab that is open on zzrf-001
  5. Refresh the tab on zzrf-001
  6. See in the browser console that there is a log entry for commerce-sdk-react ERROR invalid organizationId
  7. Verify that your refresh token was replaced with a new one that is usable for zzrf-001

New guest login:

  1. In default.js, set an invalid client ID
  2. Start the app (make sure you don't have an existing refresh token or access token)
  3. In server logs, see that there is a log entry for 400 Bad Request with a descriptive SLAS error message (ie. client_id must be 36 chars)
  4. In browser console, see the same message.

@vcua-mobify vcua-mobify requested a review from a team as a code owner September 25, 2024 23:23
@bfeister bfeister changed the title @W-15490276@ Better refresh token error logging @W-15490276@ Better refresh token error logging for V3 Sep 27, 2024
Comment on lines 565 to 566
await this.logTokenRequestError(error as Error)
throw error
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because error.response has been consumed with json(), when we throw an error here, the caller can no longer read what's inside error.response anymore.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, inspired by what's seen in your other PR: rather than reusing the same error, let's create a new error (with HTTPError) and throw that one instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated this to throw a new Error (since commerce-sdk-react currently does not have access to HTTPError).

Comment on lines 453 to 457
const json = await (error['response'] as Response).json()
const status_code: string = json.status_code
const responseMessage: string = json.message

this.logger.error(`${status_code} ${responseMessage}`)
Copy link
Contributor

@vmarta vmarta Sep 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the previous comment, do we really need to log the response details?

I think as long as we handle any refresh token errors (rather than one with a specific error message), then this is already better error handling than before.

Another way to put it is that in the case of refresh token errors, IMO gracefully handling those errors (by clearing storage and then restarting the login flow) is more important than the logging part.

Copy link
Collaborator

@bfeister bfeister Sep 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we do need to log the response details because there are a variety of different types of problems that SLAS could respond with and we don't want this to happen in a place where developers can't get into our SDK to get those clarifying response error messages that are missing

In "development mode" they can look at the Network tab in Chrome, but if a customer hits an error and can't reproduce it / the dev tools weren't already open, seeing the verbose message would become critical in catching and fixing errors in production

Copy link
Contributor

@vmarta vmarta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI done reviewing.

Comment on lines 414 to 415
expect(refreshAccessTokenSpy).toHaveBeenCalled()
expect(helpers.loginGuestUser).toHaveBeenCalled()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we also want to check whether the storage or refresh token has been updated properly afterwards?

Copy link
Contributor Author

@vcua-mobify vcua-mobify Sep 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a check to verify that the storage has been cleared after the refresh attempt.

Testing that the loginGuestUser has updated the refresh token isn't too valuable since it's a mock method that we'd define and control in the test. Testing that the token has been replaced is better done in an e2e test that involves actual SLAS calls.

I think for our unit tests, it is enough to verify that loginGuestUser has been invoked.

Comment on lines +562 to +564
try {
return await this.queueRequest(callback, isGuest)
} catch (error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for catching and handling this additional scenario 👍

// ie. 'Bad Request' for 400. We need to drill specifically into the ResponseError
// to get a more descriptive error message from SLAS
if (error instanceof Error && 'response' in error) {
// commerce-sdk-isomorphic throws a `ResponseError`, but doesn't export the class.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We control this package so there's nothing stopping from exporting it :D

but the release wouldn't make it in time for this PR, so maybe we can export it in the next release and follow up in another PR if we really want to

// We catch the error here to do logging but we still need to
// throw an error to stop the login flow from continuing.
await this.logTokenRequestError(err)
throw new Error(`New guest user could not be logged in. ${err.message}`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This way the caller would also not have access to read the response details. How can we pass along those details to them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've made changes for extracting the status code and message from the ResponseError so that they can be passed around.

Comment on lines +511 to +512
// clean up storage and restart the login flow
this.clearStorage()
Copy link
Contributor

@vmarta vmarta Sep 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: how about us console.loging here to tell others that we've handled the error by doing a guest login? I think it'd be useful for them to see that in the log too... not just the errors.

@@ -1,5 +1,6 @@
## v3.1.0-dev (Aug 08, 2024)

- Better refresh token error logging [#2028](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2028)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Better refresh token error logging [#2028](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2028)
- Improve refresh token error logging [#2028](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2028)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied!

@vcua-mobify vcua-mobify enabled auto-merge (squash) October 1, 2024 20:25
@vcua-mobify vcua-mobify merged commit ccb17bf into develop Oct 1, 2024
23 of 29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants