【问题标题】:How does a SPA extract access token in OAuth2 implicit flowSPA 如何在 OAuth2 隐式流中提取访问令牌
【发布时间】:2018-10-21 10:56:06
【问题描述】:

我有一个基于 Angular 的 SPA,并希望利用 OAuth2 隐式流 OAuth2 implicit flow

当授权服务器建立后,如果我与它有一个活跃的会话并且我发送把这个 URL 放在浏览器地址栏中

https://server.example.com/authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1

我使用 access_token 正确重定向到

 HTTP/1.1 302 Found
 Location: http://client.example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAAs&state=xyz&token_type=example&expires_in=3600
 

规范规定client.example.com/cb 应该返回一个能够访问完整重定向 URI 的网页(通常是带有嵌入脚本的 HTML 文档),包括用户代理保留的片段,并提取访问令牌。我已经实现了一个页面,脚本从window.location.hash 获取 access_token 并且它可以工作。

现在,由于 SPA 已经加载,而且我还需要为令牌续订执行此操作,因此我想使用 ajax 请求来执行此操作。但是,使用 ajax 时,会自动执行重定向,我只得到 HTML 页面,但 access_token 丢失了。我可以在响应的 Location 标头中看到 access_token,但不知道如何访问它。

Auth0Okta 似乎支持使用隐式流的静默身份验证,它们是如何做到的?

任何帮助将不胜感激。

【问题讨论】:

    标签: javascript angular oauth-2.0


    【解决方案1】:

    access_token 只能通过location.hash 访问,而 ajax 请求不会更新它,因此无法通过 ajax 请求来实现。

    查看了其他库的做法,发现: https://github.com/damienbod/angular-auth-oidc-client#silent-renew

    诀窍是创建一个隐藏的iframe,并且每当需要令牌时,将src 属性更新为构造的URL。令牌将在 iframe 中可用,只需将其传递给 window.parent

    要实现这一点,首先将一个事件监听器附加到window

    window.addEventListener("message", receiveToken, false);
    
    function receiveToken(event) {
      // event.data will contain hash value
      console.log ('token received ' + event.data) ;
    }
    

    并在需要新令牌时调用此函数

    function fetchToken() {
        document.getElementById('iframe').src='https://server.example.com/authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb'
    }
    

    http://client.example.com/cb 应该返回类似这样的内容

    <!DOCTYPE html>
    <html>
    <head>
    <script type="text/javascript">
        window.parent.postMessage(location.hash, "http://client.example.com");
    </script>
    </head>
    <body></body>
    </html>
    

    这里postMessage 的第二个参数是targetOrigin,它应该匹配托管SPA 的主机名。如果你不想要这个安全限制,可以设置为'*'

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-02
      • 1970-01-01
      • 2012-01-17
      • 2013-07-29
      • 2016-07-07
      • 2014-06-24
      • 1970-01-01
      • 2021-11-10
      相关资源
      最近更新 更多