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
Expose identity token for oauth2 #3211
Expose identity token for oauth2 #3211
Conversation
This pull request is being automatically deployed with Vercel (learn more). 🔍 Inspect: https://vercel.com/teaminsomnia/insomnia-storybook/6RWqWc3Kfcrud3HMf2XmKo97aX3E [Deployment for ff90aef canceled] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally looks good but a couple of changes to make here 😄
I am also not set up to be able to QA this, if you could outline some of your QA steps to show this works and fails correctly that would be very much appreciated.
packages/insomnia-app/app/ui/components/editors/auth/o-auth-2-auth.js
Outdated
Show resolved
Hide resolved
@sayoojs is attempting to deploy a commit to the Insomnia Team on Vercel. A member of the Team first needs to authorize it. |
@develohpanda The QA I've done so far is
I've also made the requested changes and pushed the commit, but since I forked, Vercel, is asking for authentication. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the quick turnaround and your notes! 🙌🏽
I am happy with the code and usability though I'm not sure about the expectation for token expiry (should it be the same as the access token?). We may also need to explore how to QA this, maybe allowing users from the parent issue to QA a beta build.
@DMarby may have some thoughts on QA as well.
I've pushed another commit which addresses handling the Identity Token expiry separately. Also, any updates on including this in a beta build? Thanks in advance! 😃 |
Awesome! I will review again, and I'll raise it with the team next week to make sure we get some more reviews on this PR and figure out a way forward. 🤗 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice 🎉
make it exactly 13 digits. As the 'TimeFromNow' component only seems to | ||
render 13 digit epochs correctly. | ||
*/ | ||
const expDigitCount = exp.toString().length; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like it's using moment
to create the timestamp.
What does the expiry extracted from the token look like/represent? Feels like the padding or removing of digits could cause some strange behavior 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The extracted expiry for identityToken was a 10 digit epoch representation in my case (Eg: 1617202697
Precision up to seconds).
For accessToken's expires_in
key its 13 digit epoch (Eg: 1617202697111
Precision up to milliseconds).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see! Reading some docs about the JWT exp
property it seems this is usually in seconds. Is this always the case or situational? If always, I'd be more comfortable with a solution what converts seconds to milliseconds by multiplying by 1000, rather than removing or padding digits 🤔 since we're working with numbers the multiplication seems easier to follow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh no, by padding (as shown in snippet below) that's what I'm doing.
I'm essentially dividing or multiplying by 10^n, where n is calculated as the difference between the number 13 and the actual digit count of epoch generated from the JWT exp property.
exp = exp * 10 ** (13 - expDigitCount);
So in cases of epoch seconds, that code multiplies by 10^3.
In case of epoch microseconds, that code multiplies by 10^-3. Which essentially remove the digits that representing the microseconds.
Maybe I should force cast the result to big int to prevent floating points on x10^-n
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahhhh okay, thanks for explaining that!!
Maybe I should force cast the result to big int to prevent floating points on x10^-n
That sounds reasonable.
I think it would be good to extract these few lines into a standalone utility method somewhere and writing a few tests as a way to document input/output of this logic. 🙌🏽
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which lines specifically? The padding/trimming part?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep! The padding and trimming
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a file with preexisting util functions? Where I can export this to? Or do I just create a static method within this class itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might be a good place! Looks like there a similar helper here too, for snapping a number to a minimum or maximum.
export function snapNumberToLimits(value: number, min?: number, max?: number): number { |
The associated tests would go in here: https://github.com/Kong/insomnia/blob/develop/packages/insomnia-app/app/common/__tests__/misc.test.js
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved this functionality to misc.js and added tests. (Do review the tests, this is the first time I've written JS tests)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a bug here such that window.atob()
fails fatally if the identity token is not encoded correctly (if you just type anything into the input field). The field has a requirement to be encoded in a particular way from what I can see, which is fine, but there shouldn't be a UI failure if it's not encoded as expected. 🤔
Another bug in comments below. Once these are fixed up I can trigger an alpha build, or you can bundle it locally for your OS by running npm run app-package:smoke
and fetching artefacts from the packages/insomnia-app/dist
folder.
static renderExpiryFromJWT(token: string): React.Element<*> | string | null { | ||
if (!token) { | ||
return null; | ||
} | ||
|
||
const base64Url = token.split('.')[1]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just pulled this down locally to test and the Oauth2 tab fails to render for a brand new request as a result of this implementation. The following suggestion matches how renderExpireAt
is written
static renderExpiryFromJWT(token: string): React.Element<*> | string | null { | |
if (!token) { | |
return null; | |
} | |
const base64Url = token.split('.')[1]; | |
static renderExpiryFromJWT(token: ?OAuth2Token): React.Element<*> | string | null { | |
if (!token || !token.identitiyToken) { | |
return null; | |
} | |
const base64Url = token.identitiyToken.split('.')[1]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll make this change.
I was trying to keep the function generic, to be able to be used with any JWT 😅
I guess since accessToken already has an expiry function, i'll make this one dedicated to identityToken.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough 😅 it fails because likely somewhere in the render loop this logic is reached while token is undefined
, and the previous code would fail with an error like identityToken cannot be found on undefined
@@ -541,7 +580,8 @@ class OAuth2Auth extends React.PureComponent<Props, State> { | |||
const { request, oAuth2Token: tok } = this.props; | |||
const { loading, error, showAdvanced } = this.state; | |||
|
|||
const expireLabel = OAuth2Auth.renderExpireAt(tok); | |||
const accessExpireLabel = OAuth2Auth.renderExpireAt(tok); | |||
const identityExpireLabel = OAuth2Auth.renderExpiryFromJWT(tok.identityToken); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const identityExpireLabel = OAuth2Auth.renderExpiryFromJWT(tok.identityToken); | |
const identityExpireLabel = OAuth2Auth.renderExpiryFromJWT(tok); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fix is implemented.
@develohpanda I've implemented the requested changes. Any idea why the Ubuntu tests might be failing? I couldn't infer anything from the logs. Could you try re-triggering it? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you so much 🙏🏽 Sometimes Spectron (the E2E test framework we use for Electron) fails to connect to the chrome driver and gives cryptic errors like that. I have re-triggered, no action needed from your side 🤗
What an amazing feature! Thank you so much 👏 |
Kong#3211 Allowed for using an identity token for auth rather than auth token. When using that feature, the GraphQL schema could not be fetched due to `throw new Error('No OAuth 2.0 identity tokens found for request');`. This commit moves the normalization of the request ID further up the chain so it can be used where this error would otherwise be thrown.
Kong#3211 Allowed for using an identity token for auth rather than auth token. When using that feature, the GraphQL schema could not be fetched due to `throw new Error('No OAuth 2.0 identity tokens found for request');`. This commit moves the normalization of the request ID further up the chain so it can be used where this error would otherwise be thrown.
Kong#3211 Allowed for using an identity token for auth rather than auth token. When using that feature, the GraphQL schema could not be fetched due to `throw new Error('No OAuth 2.0 identity tokens found for request');`. This commit moves the normalization of the request ID further up the chain so it can be used where this error would otherwise be thrown.
Closes #1423
Exposed identity token in the UI for all grant types in Oauth2.

Shows both identity token and refresh token in the Ctrl+Space autocomplete list for ease of use.

Made sure to handle populating identity token on clicking the
Refresh Token
button.