信息
我尝试在弹出窗口中实现 * OAuth with Twitter , 同样的实现适用于Google和Discord *,目前我正在做的是,在一个名为openOAuthWindow
的函数中我正在创建一个新的窗口弹出与OAuth URL,然后创建一个Promise
*并将resolve
和reject
函数保存在window
对象中。之后, * 在子窗口中当服务重定向到我的redirect_uri
时,我的页面调用父窗口中保存的resolve
或reject
(通过从window.opener
引用)取决于OAuth结果并关闭OAuth窗口。关闭子项后I '我正在从父窗口中清除resolve
和reject
函数,并相应地解决或拒绝承诺。此外,我还为setInterval
设置了一个间隔,用于检查oAuthWindow.closed === true
(指示窗口是否已关闭)。在oAuthWindow.closed === true
和Promise
未满足的情况下,指示用户手动关闭OAuth窗口,并返回OAuthError
作为Promise的结果。
∮问题是
正如我前面提到的,Google和Discord都很好,问题出在Twitter上,当Twitter OAuth页面完全加载时,oAuthWindow.closed
返回true
(当Windows还开着的时候),我的逻辑失败了(因为我抛出的错误表明用户手动关闭了OAuth窗口)。另外,当我转到oAuthWindow
中的DevTools时,window.opener
属性等于null
。2所以我对父窗口的引用也丢失了。
∮真正的问题∮
1.有没有其他方法可以检查Windows是开着还是关着?(我试着找一些解决方法,但找不到)
1.有没有其他的解决方案可以在弹出窗口中实现OAuth?(欢迎提供)
1.也有任何安全缺陷,以避免在弹出窗口中使用OAuth 2?(我已经做了这方面的研究,我已经做了OAuth安全的调查,我发现的唯一安全问题可能是从网站访问子窗口,但该链接是不可能的,由于同源政策)
public static async openOAuthWindow(url: string, windowFeatures: string = "width=500,height=600,popup=true"): Promise<CodeAndState> {
if(!windowFeatures.includes("noopener")) {
const oAuthWindow: Window = window.open(url, "_blank", windowFeatures)!;
let fulfilled = false;
const removePromiseCallbacksAndFullfill = () => {
delete window.returnAuthCode;
delete window.returnOAuthError;
fulfilled = true;
};
let resultPromise: Promise<CodeAndState> = new Promise<CodeAndState>((resolve, reject) => {
window.returnAuthCode = resolve;
window.returnOAuthError = reject;
}).then((codeAndState: CodeAndState) => {
removePromiseCallbacksAndFullfill();
return codeAndState;
}).catch((error) => {
removePromiseCallbacksAndFullfill();
return Promise.reject(error);
});
let windowAliveInterval = setInterval(() => {
if (oAuthWindow.closed) {
clearInterval(windowAliveInterval);
if(!fulfilled) {
const error = new OAuthError("User closed the window", ERROR_STATUSES.USER_CLOSED_OAUTH_WINDOW);
window.returnOAuthError!(error);
}
}
}, 500);
return resultPromise;
}
throw new Error("OAuth window sends code to the parent window, so it must be opened without 'noopener' feature");
}
1条答案
按热度按时间ru9i0ody1#
我最近也遇到了这个问题,在弹出窗口中打开GoogleOAuth提示被错误地认为是“关闭”。
您可以考虑的一种解决方案是使用broadcast channel:当父窗口打开oauth弹出窗口时,也打开一个广播频道。在Oauth登录后,重定向到一个页面,该页面在弹出窗口关闭之前向父页面发送一条消息。
如果父窗口在广播通道上没有接收到任何消息,则表明登录在成功之前已关闭。