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

feat(javascript-sdk): include raw response to OAuth token return #400

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

cerebrl
Copy link
Contributor

@cerebrl cerebrl commented Nov 1, 2023

DO NOT MERGE

JIRA Ticket

SDKS-2790

Description

Adjust OAuth2Client class to attach the raw response from the server as an additional property that propagates through to the application layer and also is stored along with the traditional tokens.

Details

  • add raw response to returned value in OAuth2Client.getOAuth2Tokens
  • this raw response is the original serialized JSON body
  • this new property will be persisted with the tokens in Web Storage

Type of Change

Please Delete options that are not relevant

  • New feature (non-breaking change which adds functionality)

How Has This Been Tested?

Manually tested with the e2e autoscript apps (screenshot included) as well as added a test assertion for our automated e2e test suite as well.

Screenshot of manual test with localStorage with rawResponse containing the original response body

CleanShot 2023-11-01 at 15 38 23

Definition of Done

Check all that apply

  • Acceptance criteria is met.
  • All tasks listed in the user story have been completed.
  • Coded to standards.
  • Code peer-reviewed.
  • Ensure backward compatibility (special attention).
  • API reference docs is updated.
  • Unit tests are written.
  • Integration tests are written.
  • e2e tests are written.
  • CI build passing on the feature branch.
  • Functional spec is written/updated
  • contains example code snippets.
  • Change log updated.
  • Documentation story is created and tracked.
  • UI is completed or ticket is created.
  • Demo to PO and team.
  • Tech debts and remaining tasks are tracked in separated ticket(s).

Documentation

  • Acceptance criteria met
  • Spell-check run
  • Peer reviewed
  • Proofread

- add raw response to returned value in OAuth2Client
- this raw response is the original serialized JSON body
- this new property will be persisted with the tokens in WebStorage
Copy link

changeset-bot bot commented Nov 1, 2023

⚠️ No Changeset found

Latest commit: b4ba91e

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@cerebrl cerebrl temporarily deployed to Preview November 1, 2023 21:22 — with GitHub Actions Inactive
Copy link

nx-cloud bot commented Nov 1, 2023

☁️ Nx Cloud Report

CI is running/has finished running commands for commit b4ba91e. As they complete they will appear below. Click to see the status, the terminal output, and the build insights.

📂 See all runs for this CI Pipeline Execution


✅ Successfully ran 5 targets

Sent with 💌 from NxCloud.

@@ -88,6 +88,7 @@ function autoscript() {
} else {
throw new Error('Session_Error');
}
console.log(tokens.rawResponse);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Adding a log of the raw response, so the test suite can pick it up and ensure the original response has the correct values.

Copy link
Contributor

Choose a reason for hiding this comment

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

Should probably use the Logger class?

Comment on lines +33 to +37
messageArray.forEach((message) => {
if (message.includes('access_token')) {
rawResponse = message;
}
});
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the new code that tests the existence of the raw response, which uses snake_case. Because this is a live capable test, I just want to test the existence of keys, not values.

Comment on lines +22 to +30
expect(messageArray.includes('OAuth login successful'), 'oauth success').toBe(true);
expect(messageArray.includes('Logout successful'), 'logout success').toBe(true);
expect(messageArray.includes('Calling authorize endpoint'), 'call /authorize').toBe(true);
expect(
messageArray.includes('Calling access token exchange endpoint'),
'call /access_token',
).toBe(true);
expect(messageArray.includes('Get user info from OAuth endpoint'), 'call /userinfo').toBe(true);
expect(messageArray.includes('New OAuth tokens retrieved'), 'tokens received').toBe(true);
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'm adding secondary messages here, so if the test fails, it will print the message to help inform which expectation failed. Without this, the test just says, "expected true and got false" or something like that.

Comment on lines +19 to +34
expect(
messageArray.includes('IG resource requires additional authorization'),
'add. auth required',
).toBe(true);
expect(
messageArray.includes('Request to IG resource successfully responded'),
'successful response',
).toBe(true);
expect(
messageArray.includes('Starting authentication with composite advice'),
'start auth with advice',
).toBe(true);
expect(
messageArray.includes('Continuing authentication with composite advice'),
'continue with advice',
).toBe(true);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This randomly failed, and I was motivated to add the secondary messages here to, but there's no actual code change here.

@@ -160,6 +160,7 @@ abstract class OAuth2Client {
};

const response = await this.request('accessToken', undefined, false, init, options);
const responseClone = response.clone();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cloning the response here since we want to both grab the response text as well as create parsed JSON out of it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Can you point me to what you mean? I don't understand why the clone is necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good question! This is something that took me a bit to wrap my head around (I had to do this a lot in the Token Vault plugin). The tl;dr of is any time you call a method off of body, you "attach" a "reader" to the underlying ReadableStream of the body. Only one reader can be attached to a stream at a time, so if you have two different places in the code that need to "attach" to the stream of the body, then you have to clone it.

The other location where we read the body is here: https://github.com/ForgeRock/forgerock-javascript-sdk/blob/develop/packages/javascript-sdk/src/oauth2-client/index.ts#L301.

Ref for the above: https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams#attaching_a_reader

Copy link
Contributor

Choose a reason for hiding this comment

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

wow havent used this before at all. interesting stuff

Copy link
Contributor

@ryanbas21 ryanbas21 left a comment

Choose a reason for hiding this comment

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

thoughts for discussion

@@ -88,6 +88,7 @@ function autoscript() {
} else {
throw new Error('Session_Error');
}
console.log(tokens.rawResponse);
Copy link
Contributor

Choose a reason for hiding this comment

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

Should probably use the Logger class?

@@ -160,6 +160,7 @@ abstract class OAuth2Client {
};

const response = await this.request('accessToken', undefined, false, init, options);
const responseClone = response.clone();
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you point me to what you mean? I don't understand why the clone is necessary?

@@ -185,6 +186,7 @@ abstract class OAuth2Client {
idToken: responseObject.id_token,
refreshToken: responseObject.refresh_token,
tokenExpiry: tokenExpiry,
rawResponse: await responseClone.text(),
Copy link
Contributor

Choose a reason for hiding this comment

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

so the basic ask is to just include the entire response object in addition to how we structure it normally.

i'm curious if we should include this as an opt in configuration? it may be overkill to add as a config but i also think we are adding a lot to what was previously a very thin api that could add noise for many who just don't need this info

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, we discussed enabling/disabling this with a config flag, but since this was just a test branch, we decided to minimize the work. If this is brought in as an official feature, we can consider more sophisticated implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

2 participants