-
Notifications
You must be signed in to change notification settings - Fork 47
fix(javascript-sdk): use-prompt-none #329
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
Conversation
| const error_description_query_param = | ||
| new URL(response.url).searchParams.get('error_description') !== undefined; | ||
|
|
||
| if (error_description_query_param) { | ||
| throw new Error(allowedErrors.PromptError); | ||
| } |
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.
honestly unsure if this was really a great way to handle this. need to look into this more
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 don't think this is needed. The parseError method used just a few lines down should already grab the error and throw with the right message.
|
Your preview environment pr-329-ryanbas21 has been deployed. Preview environment endpoints are available at: |
☁️ Nx Cloud ReportCI is running/has finished running commands for commit f9e2622. As they complete they will appear below. Click to see the status, the terminal output, and the build insights. 📂 See all runs for this branch ✅ Successfully ran 5 targetsSent with 💌 from NxCloud. |
cerebrl
left a comment
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.
Just a few comments.
| CORSError: 'Cross-origin redirection', | ||
|
|
||
| //Prompt error | ||
| PromptError: 'User is not authenticated or session cookie not sent to the server', |
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 think the error parameter may be better than the error_description parameter. Rather than this long sentence, you'd look for this: interaction_required.
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.
Actually, looking at this now, the most minimal code change would be to use both the error and error_description as defined by this parseError method: https://github.com/ForgeRock/forgerock-javascript-sdk/blob/develop/packages/javascript-sdk/src/oauth2-client/index.ts#L293.
| const error_description_query_param = | ||
| new URL(response.url).searchParams.get('error_description') !== undefined; | ||
|
|
||
| if (error_description_query_param) { | ||
| throw new Error(allowedErrors.PromptError); | ||
| } |
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 don't think this is needed. The parseError method used just a few lines down should already grab the error and throw with the right message.
| * Options used when requesting the authorization URL. | ||
| */ | ||
| interface GetAuthorizationUrlOptions extends ConfigOptions { | ||
| interface GetAuthorizationUrlOptions extends GetTokensOptions { |
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.
Was this intentional?
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 was because of the above cahnge of passing login, i dont think its needed now, however its more correct from the type perspective i think.
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 doesn't feel right to me as the hierarchy of this is in reverse. The TokenManager class, on which getTokens is found, internally uses the OAuthClient class. So, if one inherited from the other, I would think GetTokensOptions would extend GetAuthorizationUrlOptions, not the other way around, yeah? But, ultimately, I don't think either extend the other. For example, forceRenew and login are not properties of GetAuthorizationUrlOptions as the createAuthorizeUrl doesn't use them.
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.
we resolved this on slack. its right and wrong and i've created a ticket to complete a fix for this.
03dc439 to
d1ff4f9
Compare
d1ff4f9 to
38c386b
Compare
use the prompt=none query parameter.
38c386b to
cc8c879
Compare
cc8c879 to
38e35fb
Compare
| state?: string; | ||
| verifier?: string; | ||
| query?: StringDict<string>; | ||
| prompt?: 'none' | 'redirect' | 'consent'; |
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 think you meant "login", rather than "redirect", yeah? Ref: https://backstage.forgerock.com/docs/am/7/oauth2-guide/oauth2-authorize-endpoint.html
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.
d'oh. yes.
| * Options used when requesting the authorization URL. | ||
| */ | ||
| interface GetAuthorizationUrlOptions extends ConfigOptions { | ||
| interface GetAuthorizationUrlOptions extends GetTokensOptions { |
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 doesn't feel right to me as the hierarchy of this is in reverse. The TokenManager class, on which getTokens is found, internally uses the OAuthClient class. So, if one inherited from the other, I would think GetTokensOptions would extend GetAuthorizationUrlOptions, not the other way around, yeah? But, ultimately, I don't think either extend the other. For example, forceRenew and login are not properties of GetAuthorizationUrlOptions as the createAuthorizeUrl doesn't use them.
| CORSError: 'Cross-origin redirection', | ||
|
|
||
| // prompt=none errors | ||
| InteractionNotAllowed: 'The request requires some interaction that is not allowed.', |
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'm a bit confused here. Being that the parseError method concatenates the error and error_description, I would think this string would start with interaction_required: : https://github.com/ForgeRock/forgerock-javascript-sdk/blob/develop/packages/javascript-sdk/src/oauth2-client/index.ts#L296. Am I misunderstanding what happens here?
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 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.
Ah, okay, you're right. Sorry for the confusion.
38e35fb to
310fdab
Compare
| const authorizeUrlOptions = { ...options, responseType: ResponseType.Code, state, verifier }; | ||
| const authorizeUrl = await OAuth2Client.createAuthorizeUrl(authorizeUrlOptions); | ||
|
|
||
| const authorizeUrlOptions = { |
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 got formatted /shrug
| // Since `login` is configured for "redirect", store authorize values and redirect | ||
| window.sessionStorage.setItem(clientId as string, JSON.stringify(authorizeUrlOptions)); | ||
|
|
||
| const authorizeUrl = await OAuth2Client.createAuthorizeUrl(authorizeUrlOptions); |
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 moved this from above, not needed but its closer to where its used now
BREAKING CHANGE: commit 48cc494 didn't get picked up for breaking change, unsure why so i'm adding it here. there isn o breaking change in this commit
310fdab to
f9e2622
Compare
daveadams56
left a comment
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 this was merged before I hit 'submit' on my review so apologies for not getting feedback to you before this, however I have a couple of questions around the implementation. Could both be things that I missed, but it would be good to discuss these here or in slack when you get time. Thanks.
| state?: string; | ||
| verifier?: string; | ||
| query?: StringDict<string>; | ||
| prompt?: 'none' | 'login' | 'consent'; |
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.
My understanding is that the requirement in the ticket was for none to mean that ?prompt=none is passed in the authorize call, login and would be used for centralized login. Maybe a silly question, but what does consent mean here - what is the consequence of specifying this option?
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 is a good point. These three values for the /authorize endpoint are valid, but we are likely unable to support the 'consent' option. Should remove this option as to not confuse the dev?
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 think this is misleading if it doesn't actually do anything or isn't compatible in the context of the SDK and should be removed. I'd worry that it might inadvertently trick developers into thinking some action should occur if they specify consent, for example showing a consent collection page.
| */ | ||
| public static async getAuthCodeByIframe(options: GetAuthorizationUrlOptions): Promise<string> { | ||
| const url = await this.createAuthorizeUrl(options); | ||
| const url = await this.createAuthorizeUrl({ ...options, prompt: 'none' }); |
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.
Given that we are setting prompt=none as a default, does it make sense to make this something the developer can specify? As I understand it, setting prompt: 'login' overrides this but if nothing is set then it's prompt: 'none'. Maybe I'm overthinking this but what do you think?
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.
Good question. This is how I look at it: since this is within the hidden iframe, I don't believe there is ever a reason to NOT use prompt=none as any prompt, aka UI, would be hidden and therefore unusable.
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.
Yes. Given this and my point about the value consent further up, perhaps we should rethink this. Maybe we should obscure this entirely from the user and always pass prompt=none unless the developer specifies they want to do centralized login using login: 'redirect'? That way we avoid introducing a "thing" that the developer has to think about.

use the prompt=none query parameter.
JIRA Ticket
https://bugster.forgerock.org/jira/browse/SDKS-2060
Description
prompt none provides a better experience when errors occur in an iframe during /authorize
Type of Change
Please Delete options that are not relevant
How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration
Definition of Done
Check all that apply
Documentation