Instagram oAuth 身份验证 postMessage 问题仅适用于移动浏览器
Instagram oAuth Authentication postMessage issue only with Mobile Browsers
我有一个 Ionic 2 应用程序 ("native"),它也可以在移动设备和桌面浏览器的浏览器上运行。
此应用程序通过 Instagram、Google、Facebook 和 Twitter 提供身份验证。
在 API 方面,这是由 hapi.js
和 bell
插件处理的。
现在,我在移动浏览器上进行 Instagram 身份验证时遇到了一个问题。
当此应用程序在浏览器上运行而不是依赖于 Ionic 提供的身份验证机制时,我们已经实现了 "browser" 回退来做到这一点。
除了 Instagram 之外,我们在任何实施方面都没有遇到重大问题,Instagram 之前运行良好。
我们有这段代码应该打开一个新的 window(浏览器上的选项卡)来处理社交网络登录页面,当我们取回授权令牌时,然后继续关闭选项卡并在应用程序上验证用户。
在应用程序端,处理此选项卡切换和通信行为基本上如下所示:
private requestToken(tokenEndpoint, resolve, reject) {
let messageReceived = false;
let win = window.open(this.globals.BASE_URL + tokenEndpoint,
'_blank', 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width=500, height=300');
// Await auth message
window.onmessage = (e) => {
let credentials;
messageReceived = true;
try {
credentials = JSON.parse(e.data);
}
catch (error) {
credentials = e.data;
}
return credentials ? resolve(credentials) : reject();
};
let interval = window.setInterval(() => {
try {
// win is already null after closing first tab
if (win == null || win.closed) {
window.clearInterval(interval);
if (!messageReceived) {
reject();
}
}
}
catch (e) { }
}, 1000);
}
我的 API 将 return 所需的数据发送到前端:
<script>window.opener.postMessage('{0}', '*');window.close();</script>
,其中 {0}
是我需要的身份验证数据。
对于任何其他社交网络,这将打开一个地址为 about:blank
的新选项卡,然后将更改为正确的 url
以输入 username/password。完成后,服务器会返回那个小脚本,phone 会关闭选项卡,将数据传回应用程序。它运行完美。
然而,
对于 Instagram,行为有所不同。将打开一个新选项卡,它会立即关闭并出现一个新选项卡,我将在其中输入我的数据。
问题是,当服务器返回脚本时,我的 window.opener
为空并且对原始页面的引用丢失,这使我无法取回身份验证数据。
我该如何克服这个问题?我怎样才能强制原来的选项卡不关闭,而是像其他选项卡一样运行,只导航到 IG 登录页面?
IG 是否发回 301 或 302 回复?如果是的话,我到现在都抓不到。
对于那些最终出现在这里的人,解决方案是使用 window.parent.parent.postMessage()
而不是依赖 window.opener.postMessage()
我有一个 Ionic 2 应用程序 ("native"),它也可以在移动设备和桌面浏览器的浏览器上运行。
此应用程序通过 Instagram、Google、Facebook 和 Twitter 提供身份验证。
在 API 方面,这是由 hapi.js
和 bell
插件处理的。
现在,我在移动浏览器上进行 Instagram 身份验证时遇到了一个问题。
当此应用程序在浏览器上运行而不是依赖于 Ionic 提供的身份验证机制时,我们已经实现了 "browser" 回退来做到这一点。
除了 Instagram 之外,我们在任何实施方面都没有遇到重大问题,Instagram 之前运行良好。
我们有这段代码应该打开一个新的 window(浏览器上的选项卡)来处理社交网络登录页面,当我们取回授权令牌时,然后继续关闭选项卡并在应用程序上验证用户。
在应用程序端,处理此选项卡切换和通信行为基本上如下所示:
private requestToken(tokenEndpoint, resolve, reject) {
let messageReceived = false;
let win = window.open(this.globals.BASE_URL + tokenEndpoint,
'_blank', 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width=500, height=300');
// Await auth message
window.onmessage = (e) => {
let credentials;
messageReceived = true;
try {
credentials = JSON.parse(e.data);
}
catch (error) {
credentials = e.data;
}
return credentials ? resolve(credentials) : reject();
};
let interval = window.setInterval(() => {
try {
// win is already null after closing first tab
if (win == null || win.closed) {
window.clearInterval(interval);
if (!messageReceived) {
reject();
}
}
}
catch (e) { }
}, 1000);
}
我的 API 将 return 所需的数据发送到前端:
<script>window.opener.postMessage('{0}', '*');window.close();</script>
,其中 {0}
是我需要的身份验证数据。
对于任何其他社交网络,这将打开一个地址为 about:blank
的新选项卡,然后将更改为正确的 url
以输入 username/password。完成后,服务器会返回那个小脚本,phone 会关闭选项卡,将数据传回应用程序。它运行完美。
然而,
对于 Instagram,行为有所不同。将打开一个新选项卡,它会立即关闭并出现一个新选项卡,我将在其中输入我的数据。
问题是,当服务器返回脚本时,我的 window.opener
为空并且对原始页面的引用丢失,这使我无法取回身份验证数据。
我该如何克服这个问题?我怎样才能强制原来的选项卡不关闭,而是像其他选项卡一样运行,只导航到 IG 登录页面? IG 是否发回 301 或 302 回复?如果是的话,我到现在都抓不到。
对于那些最终出现在这里的人,解决方案是使用 window.parent.parent.postMessage()
而不是依赖 window.opener.postMessage()