Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
0e9e1c4
- Update popup client with a minimal functionality to handle popup CO…
konstantin-msft Oct 29, 2025
8da953b
- Update popup client with a minimal functionality to handle popup CO…
konstantin-msft Oct 30, 2025
9759da1
- Update popup client with a minimal functionality to handle popup CO…
konstantin-msft Oct 30, 2025
b785cbb
- Code size optimizations
konstantin-msft Oct 31, 2025
125588f
- Code optimizations
konstantin-msft Nov 3, 2025
7eb65d7
- Refactor silent client to use redirect bridge for both popup and SS…
konstantin-msft Nov 4, 2025
1be20ef
- Refactor silent client to use redirect bridge for both popup and SS…
konstantin-msft Nov 4, 2025
d72ba13
Merge branch 'msal-v5' into popup_coop_support
konstantin-msft Nov 4, 2025
2b46d6a
Update package-lock.json
konstantin-msft Nov 4, 2025
da8168d
- Update unit tests.
konstantin-msft Nov 6, 2025
f186235
Merge branch 'msal-v5' into popup_coop_support
konstantin-msft Nov 6, 2025
afae280
Fix post-merge errors.
konstantin-msft Nov 6, 2025
e7e5c54
Change files
konstantin-msft Nov 6, 2025
40b8e3e
Add redirectBridgeEmptyResponse error code and update waitForBridgeRe…
konstantin-msft Nov 7, 2025
2a28584
- Update redirect page for samples
konstantin-msft Nov 11, 2025
afe6890
- Remove redundant "unloadWindow" listener
konstantin-msft Nov 12, 2025
240757c
Merge branch 'msal-v5' into popup_coop_support
konstantin-msft Nov 12, 2025
c3a5ed9
Merge branch 'msal-v5' of https://github.com/AzureAD/microsoft-authen…
lalimasharda Nov 15, 2025
a4c9ce5
Merge branch 'popup_coop_support' of https://github.com/AzureAD/micro…
lalimasharda Nov 19, 2025
8a167fc
Merge branch 'msal-v5' of https://github.com/AzureAD/microsoft-authen…
lalimasharda Nov 19, 2025
49b3506
- Add navigation to broadcastResponseToMainFrame
konstantin-msft Nov 19, 2025
2895e20
- Add error description.
konstantin-msft Nov 19, 2025
076df1d
- Resolve dep cycle
konstantin-msft Nov 19, 2025
5cb8ca8
- Add support for overriding ongoing interactions in popup flows
konstantin-msft Nov 19, 2025
bb9480a
Merge branch 'msal-v5' into popup_coop_support
konstantin-msft Nov 20, 2025
6636748
- Update core e2e tests
konstantin-msft Nov 20, 2025
48e01bf
- Address review comments
konstantin-msft Nov 21, 2025
b42be72
- Update COOP migration guide
konstantin-msft Nov 21, 2025
15086a0
- Update error doc
konstantin-msft Nov 21, 2025
2780349
- Handle hybrid URL response format
konstantin-msft Nov 21, 2025
4c1a103
Merge branch 'msal-v5' into popup_coop_support
konstantin-msft Nov 21, 2025
def925e
- Update migration doc
konstantin-msft Nov 21, 2025
704968f
Merge branch 'msal-v5' into popup_coop_support
konstantin-msft Nov 24, 2025
5ffe984
Update docs/errors.md
konstantin-msft Nov 24, 2025
ba93bd2
Update lib/msal-browser/docs/v4-migration.md
konstantin-msft Nov 24, 2025
f786341
Update lib/msal-browser/docs/v4-migration.md
konstantin-msft Nov 24, 2025
7d7bdd3
Update lib/msal-browser/docs/v4-migration.md
konstantin-msft Nov 24, 2025
0aadd91
Update lib/msal-browser/docs/v4-migration.md
konstantin-msft Nov 24, 2025
4c73bbd
Update lib/msal-browser/docs/v4-migration.md
konstantin-msft Nov 24, 2025
18b1e4f
- Pick up clientId from the session storage interaction key instead o…
konstantin-msft Nov 24, 2025
348c75e
- Formatting
konstantin-msft Nov 24, 2025
d45e1d4
- Use `AuthError` to throw in the redirect bridge
konstantin-msft Nov 24, 2025
2644d40
- Update API doc
konstantin-msft Nov 24, 2025
25996a0
- Update e2e tests
konstantin-msft Nov 24, 2025
48ba45d
Merge branch 'msal-v5' of https://github.com/AzureAD/microsoft-authen…
lalimasharda Nov 24, 2025
b58bd67
Merge branch 'popup_coop_support' of https://github.com/AzureAD/micro…
lalimasharda Nov 24, 2025
9a7bd3d
- Update e2e tests
konstantin-msft Nov 25, 2025
ece3225
Merge remote-tracking branch 'origin/popup_coop_support' into popup_c…
konstantin-msft Nov 25, 2025
9c32ec0
- Add visual examples on how to handle interaction override flag.
konstantin-msft Nov 25, 2025
a5572f0
- Update API doc
konstantin-msft Nov 25, 2025
cfef9f8
- Update redirect URI switch for express sample.
konstantin-msft Nov 25, 2025
be545c8
- Address review comments
konstantin-msft Nov 25, 2025
f5b340c
- Update API doc
konstantin-msft Nov 25, 2025
7c088ed
- Increase version switch timeout for express sample
konstantin-msft Nov 25, 2025
22be0a0
- Update redirect URI documentation
konstantin-msft Nov 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Implement redirect bridge to support COOP [#8118](https://github.com/AzureAD/microsoft-authentication-library-for-js/pull/8118)",
"packageName": "@azure/msal-browser",
"email": "kshabelko@microsoft.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Implement redirect bridge to support COOP [#8118](https://github.com/AzureAD/microsoft-authentication-library-for-js/pull/8118)",
"packageName": "@azure/msal-common",
"email": "kshabelko@microsoft.com",
"dependentChangeType": "patch"
}
229 changes: 144 additions & 85 deletions docs/errors.md

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion lib/msal-browser/FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,9 @@ When you attempt to authenticate MSAL will navigate to your IDP's sign in page e

### RedirectUri for popup and silent flows

When using popup and silent APIs we recommend setting the `redirectUri` to a blank page, a page that does not implement MSAL, or a page that does not itself require a user be authenticated. This will help prevent potential issues as well as improve performance. If your application is only using popup and silent APIs you can set this on the `PublicClientApplication` config. If your application also needs to support redirect APIs you can set the `redirectUri` on a per request basis.
When using popup and silent APIs, the `redirectUri` must point to a dedicated page that implements the MSAL redirect bridge. This page handles the authentication response and communicates it back to the main application using the BroadcastChannel API. If your application is only using popup and silent APIs you can set this on the `PublicClientApplication` config. If your application also needs to support redirect APIs you can set the `redirectUri` on a per request basis.

For detailed setup instructions, see [redirectUri considerations](./docs/login-user.md#redirecturi-considerations).

### RedirectUri for redirect flows

Expand Down
89 changes: 71 additions & 18 deletions lib/msal-browser/apiReview/msal-browser.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { CommonEndSessionRequest } from '@azure/msal-common/browser';
import { CommonSilentFlowRequest } from '@azure/msal-common/browser';
import { Constants } from '@azure/msal-common/browser';
import { ExternalTokenResponse } from '@azure/msal-common/browser';
import { ICrypto } from '@azure/msal-common/browser';
import { IdTokenClaims } from '@azure/msal-common/browser';
import { ILoggerCallback } from '@azure/msal-common/browser';
import { INetworkModule } from '@azure/msal-common/browser';
Expand Down Expand Up @@ -225,11 +226,11 @@ declare namespace BrowserAuthErrorCodes {
unableToParseState,
stateInteractionTypeMismatch,
interactionInProgress,
interactionInProgressCancelled,
popupWindowError,
emptyWindowError,
userCancelled,
monitorPopupTimeout,
monitorWindowTimeout,
redirectBridgeEmptyResponse,
redirectInIframe,
blockIframeReload,
blockNestedPopups,
Expand Down Expand Up @@ -264,7 +265,8 @@ declare namespace BrowserAuthErrorCodes {
failedToBuildHeaders,
failedToParseHeaders,
failedToDecryptEarResponse,
timedOut
timedOut,
emptyResponse
}
}
export { BrowserAuthErrorCodes }
Expand Down Expand Up @@ -384,15 +386,13 @@ export type BrowserSystemOptions = SystemOptions & {
loggerOptions?: LoggerOptions;
networkClient?: INetworkModule;
navigationClient?: INavigationClient;
windowHashTimeout?: number;
iframeHashTimeout?: number;
loadFrameTimeout?: number;
popupBridgeTimeout?: number;
iframeBridgeTimeout?: number;
redirectNavigationTimeout?: number;
navigatePopups?: boolean;
allowRedirectInIframe?: boolean;
allowPlatformBroker?: boolean;
nativeBrokerHandshakeTimeout?: number;
pollIntervalMilliseconds?: number;
protocolMode?: ProtocolMode;
};

Expand All @@ -406,10 +406,13 @@ export type BrowserTelemetryOptions = {

declare namespace BrowserUtils {
export {
parseAuthResponseFromUrl,
clearHash,
replaceHash,
isInIframe,
isInPopup,
cancelPendingBridgeResponse,
waitForBridgeResponse,
getCurrentUri,
getHomepage,
blockReloadInHiddenIframes,
Expand Down Expand Up @@ -452,6 +455,11 @@ export type CacheOptions = {
cacheRetentionDays?: number;
};

// Warning: (ae-missing-release-tag) "cancelPendingBridgeResponse" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
function cancelPendingBridgeResponse(logger: Logger, correlationId: string): void;

// Warning: (ae-missing-release-tag) "ClearCacheRequest" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
Expand Down Expand Up @@ -544,6 +552,11 @@ const earJwkEmpty = "ear_jwk_empty";
// @public (undocumented)
const emptyNavigateUri = "empty_navigate_uri";

// Warning: (ae-missing-release-tag) "emptyResponse" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const emptyResponse = "empty_response";

// Warning: (ae-missing-release-tag) "emptyWindowError" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
Expand Down Expand Up @@ -755,6 +768,11 @@ export { InProgressPerformanceEvent }
// @public (undocumented)
const interactionInProgress = "interaction_in_progress";

// Warning: (ae-missing-release-tag) "interactionInProgressCancelled" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const interactionInProgressCancelled = "interaction_in_progress_cancelled";

export { InteractionRequiredAuthError }

export { InteractionRequiredAuthErrorCodes }
Expand Down Expand Up @@ -996,16 +1014,6 @@ export class MemoryStorage<T> implements IWindowStorage<T> {
setUserData(key: string, value: T): Promise<void>;
}

// Warning: (ae-missing-release-tag) "monitorPopupTimeout" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const monitorPopupTimeout = "monitor_popup_timeout";

// Warning: (ae-missing-release-tag) "monitorWindowTimeout" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const monitorWindowTimeout = "monitor_window_timeout";

// Warning: (ae-missing-release-tag) "nativeConnectionNotEstablished" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
Expand Down Expand Up @@ -1081,6 +1089,40 @@ const noTokenRequestCacheError = "no_token_request_cache_error";
// @public (undocumented)
export const OIDC_DEFAULT_SCOPES: string[];

// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag
// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@"
// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag
// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@"
// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag
// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@"
// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag
// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@"
// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag
// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@"
// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag
// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@"
// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag
// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@"
// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag
// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@"
// Warning: (tsdoc-escape-right-brace) The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag
// Warning: (tsdoc-malformed-inline-tag) Expecting a TSDoc tag starting with "{@"
// Warning: (ae-missing-release-tag) "parseAuthResponseFromUrl" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
function parseAuthResponseFromUrl(): {
params: URLSearchParams;
payload: string;
urlHash: string;
urlQuery: string;
hasResponseInHash: boolean;
hasResponseInQuery: boolean;
libraryState: {
id: string;
meta: Record<string, string>;
};
};

export { PerformanceCallbackFunction }

export { PerformanceEvent }
Expand Down Expand Up @@ -1112,6 +1154,7 @@ export type PopupRequest = Partial<Omit<CommonAuthorizationUrlRequest, "response
scopes: Array<string>;
popupWindowAttributes?: PopupWindowAttributes;
popupWindowParent?: Window;
overrideInteractionInProgress?: boolean;
Copy link
Member

Choose a reason for hiding this comment

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

What is the default? And if user does not set this and we somehow lose the timeout from bridge, we expect the user to resend the request?

Whatever is the expected follow up, can we have this in the docs?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

overrideInteractionInProgress is described in login-user.md

};

// Warning: (ae-missing-release-tag) "PopupSize" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
Expand Down Expand Up @@ -1247,6 +1290,11 @@ export class PublicClientApplication implements IPublicClientApplication {
ssoSilent(request: SsoSilentRequest): Promise<AuthenticationResult>;
}

// Warning: (ae-missing-release-tag) "redirectBridgeEmptyResponse" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const redirectBridgeEmptyResponse = "redirect_bridge_empty_response";

// Warning: (ae-missing-release-tag) "redirectInIframe" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
Expand Down Expand Up @@ -1440,6 +1488,11 @@ const userCancelled = "user_cancelled";
// @public (undocumented)
export const version = "5.0.0-alpha.0";

// Warning: (ae-missing-release-tag) "waitForBridgeResponse" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
function waitForBridgeResponse(timeoutMs: number, logger: Logger, browserCrypto: ICrypto, request: CommonAuthorizationUrlRequest | CommonEndSessionRequest): Promise<string>;

// Warning: (ae-missing-release-tag) "WrapperSKU" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "WrapperSKU" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
Expand All @@ -1457,7 +1510,7 @@ export type WrapperSKU = (typeof WrapperSKU)[keyof typeof WrapperSKU];
// src/cache/LocalStorage.ts:366:8 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
// src/cache/LocalStorage.ts:429:8 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
// src/cache/LocalStorage.ts:460:8 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
// src/config/Configuration.ts:211:5 - (ae-forgotten-export) The symbol "InternalAuthOptions" needs to be exported by the entry point index.d.ts
// src/config/Configuration.ts:199:5 - (ae-forgotten-export) The symbol "InternalAuthOptions" needs to be exported by the entry point index.d.ts
// src/event/EventHandler.ts:114:8 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
// src/event/EventHandler.ts:141:8 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
// src/index.ts:8:12 - (tsdoc-characters-after-block-tag) The token "@azure" looks like a TSDoc tag but contains an invalid character "/"; if it is not a tag, use a backslash to escape the "@"
Expand Down
8 changes: 4 additions & 4 deletions lib/msal-browser/docs/iframe-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Iframed and parent apps with the same-origin may have access to the same MSAL.js

### Apps with cross-origin

Iframed and parent apps with cross-origin can make use of the [ssoSilent()](./login-user.md#silent-login-with-ssosilent) API to achieve single sign-on. To do so, the parent app should pass down either an **account**, a **loginHint** (username) or a **session id** (sid) to the iframed app.
Iframed and parent apps with cross-origin can make use of the [ssoSilent()](./login-user.md#silent-login-with-ssosilent) API to achieve single sign-on. To do so, the parent app should pass down either an **account**, a **loginHint** (username) or a **session id** (sid) to the iframed app.

Apps can attempt to use `ssoSilent` without any of the above parameters. However be aware that there are [additional considerations](./login-user.md#silent-login-with-ssosilent) when using `ssoSilent` without providing any information about the user's session.

Expand All @@ -40,15 +40,15 @@ const myMSALObj = new msal.PublicClientApplication({
auth: {
clientId: "ENTER_CLIENT_ID",
authority: "https://login.microsoftonline.com/ENTER_TENANT_ID",
redirectUri: "/redirect", // set to a blank page for handling auth code response via popups
redirectUri: "/redirect", // must point to a page that implements the redirect bridge
},
cache: {
cacheLocation: "localStorage", // set your cache location to local storage
},
});

window.onload = () => {

const urlParams = new URLSearchParams(window.location.search);
const sid = urlParams.get("sid");

Expand All @@ -72,7 +72,7 @@ const myMSALObj = new msal.PublicClientApplication({
auth: {
clientId: "ENTER_CLIENT_ID",
authority: "https://login.microsoftonline.com/ENTER_TENANT_ID",
redirectUri: "/redirect", // set to a blank page for handling auth code response via popups
redirectUri: "/redirect", // must point to a page that implements the redirect bridge
},
cache: {
cacheLocation: "localStorage", // set your cache location to local storage
Expand Down
6 changes: 4 additions & 2 deletions lib/msal-browser/docs/initialization.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,13 @@ The popup APIs use ES6 Promises that resolve when the authentication flow in the

#### RedirectUri Considerations

When using popup APIs we recommend setting the `redirectUri` to a blank page or a page that does not implement MSAL. This will help prevent potential issues as well as improve performance. If your application is only using popup and silent APIs you can set this on the `PublicClientApplication` config. If your application also needs to support redirect APIs you can set the `redirectUri` on a per request basis:
When using popup APIs, the `redirectUri` must point to a dedicated page that implements the MSAL redirect bridge. This page handles the authentication response and communicates it back to the main application.

For detailed guidance on setting up the redirect page, see [RedirectUri considerations](./login-user.md#redirecturi-considerations).

```javascript
msalInstance.loginPopup({
redirectUri: "http://localhost:3000/blank.html",
redirectUri: "http://localhost:3000/redirect",
});
```

Expand Down
Loading