wangzhibo
2026-05-09 53418655c061ac26f66058253f39200aced1ab1d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License.
 */
 
import {
    Logger,
    IPerformanceClient,
    invoke,
    Authority,
    CommonAuthorizationUrlRequest,
} from "@azure/msal-common/browser";
import * as BrowserPerformanceEvents from "../telemetry/BrowserPerformanceEvents.js";
import {
    createBrowserAuthError,
    BrowserAuthErrorCodes,
} from "../error/BrowserAuthError.js";
import { BrowserConfiguration } from "../config/Configuration.js";
import { getCodeForm, getEARForm } from "../protocol/Authorize.js";
 
/**
 * Creates a hidden iframe to given URL using user-requested scopes as an id.
 * @param urlNavigate
 * @param userRequestScopes
 */
export async function initiateCodeRequest(
    requestUrl: string,
    performanceClient: IPerformanceClient,
    logger: Logger,
    correlationId: string
): Promise<HTMLIFrameElement> {
    if (!requestUrl) {
        // Throw error if request URL is empty.
        logger.info("Navigate url is empty", correlationId);
        throw createBrowserAuthError(BrowserAuthErrorCodes.emptyNavigateUri);
    }
 
    return invoke(
        loadFrameSync,
        BrowserPerformanceEvents.SilentHandlerLoadFrameSync,
        logger,
        performanceClient,
        correlationId
    )(requestUrl);
}
 
export async function initiateCodeFlowWithPost(
    config: BrowserConfiguration,
    authority: Authority,
    request: CommonAuthorizationUrlRequest,
    logger: Logger,
    performanceClient: IPerformanceClient
): Promise<HTMLIFrameElement> {
    const frame = createHiddenIframe();
    if (!frame.contentDocument) {
        throw "No document associated with iframe!";
    }
    const form = await getCodeForm(
        frame.contentDocument,
        config,
        authority,
        request,
        logger,
        performanceClient
    );
    form.submit();
    return frame;
}
 
export async function initiateEarRequest(
    config: BrowserConfiguration,
    authority: Authority,
    request: CommonAuthorizationUrlRequest,
    logger: Logger,
    performanceClient: IPerformanceClient
): Promise<HTMLIFrameElement> {
    const frame = createHiddenIframe();
    if (!frame.contentDocument) {
        throw "No document associated with iframe!";
    }
    const form = await getEARForm(
        frame.contentDocument,
        config,
        authority,
        request,
        logger,
        performanceClient
    );
    form.submit();
    return frame;
}
 
/**
 * @hidden
 * Loads the iframe synchronously when the navigateTimeFrame is set to `0`
 * @param urlNavigate
 * @param frameName
 * @param logger
 */
function loadFrameSync(urlNavigate: string): HTMLIFrameElement {
    const frameHandle = createHiddenIframe();
 
    frameHandle.src = urlNavigate;
 
    return frameHandle;
}
 
/**
 * @hidden
 * Creates a new hidden iframe or gets an existing one for silent token renewal.
 * @ignore
 */
function createHiddenIframe(): HTMLIFrameElement {
    const authFrame = document.createElement("iframe");
 
    authFrame.className = "msalSilentIframe";
    authFrame.style.visibility = "hidden";
    authFrame.style.position = "absolute";
    authFrame.style.width = authFrame.style.height = "0";
    authFrame.style.border = "0";
    authFrame.setAttribute(
        "sandbox",
        "allow-scripts allow-same-origin allow-forms"
    );
    authFrame.setAttribute("allow", "local-network-access *");
    document.body.appendChild(authFrame);
 
    return authFrame;
}
 
/**
 * @hidden
 * Removes a hidden iframe from `document.body` if it is a direct child.
 * @param iframe - The iframe element to remove.
 */
export function removeHiddenIframe(iframe: HTMLIFrameElement): void {
    if (document.body === iframe.parentNode) {
        document.body.removeChild(iframe);
    }
}