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

Make signinPopup work when calling window is iframe #1744

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

thejurassic
Copy link

Closes/fixes #issue

Checklist

  • This PR makes changes to the public API
  • I have included links for closing relevant issue numbers

When using signinPopup and your app is within an iframe, the popup cannot access the local storage of the calling window due to fairly recent changes with partitioning local storage. As such the popup window cant access the stored state in storage from the main calling window.

What my changes do, is if the popup window cant find the SigninState in storage , then it returns undefined for State.
so readSigninResponseState in OidcClient.ts now returns Promise<{ state: SigninState|undefined; response: SigninResponse }
This prevents the Popup window from throwing an error that it couldnt find the state. And it returns the URL which includes the state and the calling window can verify the state instead of doing it in the popup window.

Then in UserManager.ts signinCallback function:
if state returned from await this._client.readSigninResponseState(url); is undefined, we assume we should call signinPopupCallback which sends the url back to the calling window, which itself then verifies state from the url.

I have confirmed that this now works when the calling window is in an iframe, when it previously failed at stage readSigninResponseState. I have also confirmed that auth fails if the response provides a bad state.

To summarize, the popup window was trying to verify the state in the response from the state in storage, and then when the calling window receives the URL it also verifies the state from storage. Now, if the popup cant get the state from storage it passes the url back and the main window only verifies the url and state from storage.

This allows the library to work when the popup window doesnt have access to the same partitioned local storage as the main calling window when the main calling window is in an iframe.

@thejurassic
Copy link
Author

See issues:
#1743
#1202

@@ -152,7 +152,7 @@ export class OidcClient {
return signinRequest;
}

public async readSigninResponseState(url: string, removeState = false): Promise<{ state: SigninState; response: SigninResponse }> {
public async readSigninResponseState(url: string, removeState = false): Promise<{ state: SigninState|undefined; response: SigninResponse }> {
Copy link
Member

Choose a reason for hiding this comment

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

please add spaces in-between: SigninState | undefined

@@ -183,6 +179,11 @@ export class OidcClient {
extraHeaders = { ...extraHeaders, "DPoP": dpopProof };
}

if (!state) {
logger.throw(new Error("No state was found in storage or response"));
throw null; //
Copy link
Member

Choose a reason for hiding this comment

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

please re-add comment from above // https://github.com/microsoft/TypeScript/issues/46972

@@ -394,6 +394,13 @@ export class UserManager {
*/
public async signinCallback(url = window.location.href): Promise<User | undefined> {
const { state } = await this._client.readSigninResponseState(url);

// if no state from storage, assume signin popup
if (state === undefined) {
Copy link
Member

Choose a reason for hiding this comment

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

state === undefined -> !state

Copy link
Member

Choose a reason for hiding this comment

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

How are we sure it was a "signin popup request" here? What about "No matching state found in storage" in the non "signin popup" request case?

@pamapa
Copy link
Member

pamapa commented Dec 10, 2024

Thanks for taking care of this feature!

@pamapa
Copy link
Member

pamapa commented Dec 10, 2024

I guess using sessionStorage would make it still work without this changes...

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.

2 participants