Oauth2 Implicit Flow使用单页面应用程序刷新访问令牌

g18*_*18c 30 javascript oauth-2.0 jwt thinktecture-ident-server

我使用的是Thinktecture AuthorizationServer(AS),它运行良好.

我想编写一个原生的javascript单页应用程序,可以直接调用WebAPI,但隐式流程不提供刷新令牌.

如果进行了AJAX调用,如果令牌已过期,API将向登录页面发送重定向,因为数据使用动态弹出窗口,这将中断用户.

Facebook或Stackoverflow如何做到这一点,仍然允许页面上运行的javascript调用API?

提出的解决方案

下面的场景是否合理(假设可以使用iframe):

我的SPA指示我到AS,我通过Implicit Flow获得一个令牌.在AS中,我单击允许Read data范围,然后单击Remember decision,然后单击Allow按钮.

由于我点击了Remember decision按钮,每当我点击AS作为令牌时,会自动传回一个新令牌,而我无需登录(我可以看到FedAuth cookie记住了我的决定并相信这使得它能够正常工作).

使用我的SPA(不受信任的应用程序),我没有刷新令牌只有一个访问令牌.所以相反我:

  1. 确保用户已登录并单击记住决定(否则iframe将无法工作)
  2. 调用WebAPI,如果401响应尝试并通过以下步骤获取新令牌...
  3. 在页面上有一个隐藏的iframe,我将设置URL以从Authorization Server获取新的访问令牌.
  4. 从iframe的哈希片段中获取新令牌,然后将其存储在SPA中,并用于所有未来的WebAPI请求.

如果FedAuth cookie被盗,我想我仍然会遇到麻烦.

针对上述场景的任何标准或推荐方式?

dan*_*ouz 5

我了解您的问题是,当访问令牌过期时,用户将通过重定向到授权服务器的登录页面而遇到中断。但是,我认为至少在使用隐式授予时,您不能并且应该避免这种情况。

就像我确定的那样,隐式授予应该由不能将其凭据保密的使用者使用。因此,授权服务器发出的访问令牌应具有有限的ttl。例如google在3600秒内使他们的访问令牌失效。当然,您可以增加ttl,但是它永远不应成为长期存在的令牌。

还有一点需要注意的是,我认为用户中断非常少,即,如果实施正确,则用户只需向授权服务器进行一次身份验证即可。完成此操作后(例如,第一次还同时授权应用程序访问用户控制的任何资源),将建立会话(基于Cookie或令牌),以及使用方的访问令牌(使用隐式授予的Web应用程序)过期后,将通知用户令牌已过期,并且需要与授权服务器重新进行身份验证。但是因为已经建立了会话,所以用户将立即重定向回Web应用程序。

但是,如果这不是您想要的,那么我认为应该考虑使用授权代码授予,而不是对iframe进行复杂的处理。在这种情况下,您需要一个服务器端Web应用程序,因为这样您就可以将凭据保密并使用刷新令牌。


Aha*_*iPK -2

在 Google o-Auth 中,访问令牌的有效期仅为 1 小时,因此您需要以编程方式每隔一小时更新一次访问令牌,简单地您可以创建 Web api 来执行此操作,您需要有一个刷新令牌,并且而且刷新令牌不会过期,使用 C# 代码,我已经做到了这一点。

 if (dateTimeDiff > 55)
            {
                var request = (HttpWebRequest)WebRequest.Create("https://www.googleapis.com/oauth2/v3/token");
                var postData = "refresh_token=your refresh token";
                postData += "&client_id=your client id";
                postData += "&client_secret=your client secrent";
                postData += "&grant_type=refresh_token";

                var data = Encoding.ASCII.GetBytes(postData);            
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = data.Length;
                request.UseDefaultCredentials = true;

                using (var stream = request.GetRequestStream())
                {
                    stream.Write(data, 0, data.Length);
                }
                var response = (HttpWebResponse)request.GetResponse();
                string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();

            }
Run Code Online (Sandbox Code Playgroud)

您需要将访问令牌的最后更新日期时间保存在某处(例如在数据库中),这样,每当您必须发出请求时,您就可以用当前日期时间减去它,如果超过 60 分钟,您需要调用webapi来获取新的token。

  • 刷新令牌用于服务器端客户端。提问者的客户端在用户代理中运行,因此它不应该使用刷新令牌。请参阅 Dominick Baier 的演示文稿 [Securing Web APIs – Patterns & Anti-Patterns](https://vimeo.com/131635255),尤其是第 45 分钟的演示文稿。 (3认同)