没有 LocalStorage 的带有弹出窗口的 OAuth2 隐式授权

OAuth2 Implicit Grant with Popup without LocalStorage

我目前正在将第 3 方服务集成到我们的系统中(AngularJS 在客户端和 ASP.NET Web API 2.0),这要求我们通过 OAuth2.0 对用户进行身份验证。

我目前正在使用隐式授权。但要求之一是同时支持 Edge 和 > IE10。

起初我使用以下流程:

  1. 客户端从 WebAPI
  2. 获取第 3 方服务登录 url
  3. WebAPI returns 第 3 方服务登录 url 然后客户端使用登录 url 打开一个新的弹出窗口 window(忽略浏览器弹出窗口拦截器) 对我们的应用程序 return url
  4. 身份验证后,用户将被重定向回我们的应用程序,这是一个空白页面,其中包含用于从哈希查询字符串中提取令牌然后将访问令牌存储到本地存储的 javascripts
  5. 关闭弹出窗口
  6. 在我的控制器中,我订阅了存储更改事件。因此,当访问令牌设置到本地存储时,我的控制器将从本地存储中提取访问令牌并将其移动到会话存储。

在我在 IE 和 Edge 上对其进行测试之前,这一切都运行良好。他们的本地存储不同步。 localStorage in win8.1 IE11 does not synchronize

为了让它在 IE 和 Edge 上运行,我换掉了本地存储并改用 cookie。然后我没有在更改事件上订阅存储,而是有一个类似于以下函数的函数来每秒检查一次 cookie:

setInterval(function(){
    // check cookie for cookie
    // if found, copy cookie to session storage
    // remove cookie
    // change state
}, 1000);

仅供参考:我们将访问令牌存储在会话存储中,以防止用户打开多个选项卡来访问我们的网站。

这种方法可行,但有没有更好的解决方案?

我过去实施的另一个选项是 windows.

之间直接通信

在父 window 上,在全局命名空间上公开一个函数:
window.oauthCallback = function(payload){ ... send to API }

在弹出窗口 window 中,在 oauth 重定向回的页面上,查找 window.opener 并尝试直接调用该函数:
window.opener.oauthCallback(payload)
有效负载是一个对象,由在查询字符串中传回给您的 oauth 数据构造而成。大多数框架都可以为您做这件事。

一个警告 - 如果在无法打开弹出窗口或 windows 无法通信的环境中(例如 ios webviews - 例如:从 facebook 应用程序单击 link)那么你可以在同一个 window 中进行重定向并将有效负载存储在 localstorage/cookies 中或通过 URL.

传递数据