钥匙斗篷 | 无法在异步函数中等待 updateToken()

BJa*_*usz 5 javascript jboss reactjs keycloak

我们正在使用 React/Redux 前端开发 Spring 应用程序。我们成功地将其与 Keycloak 身份验证服务集成。但是,我们在访问令牌超时后遇到了不需要的行为。我们的 restMiddleware 看起来像这样(简化):

    function restMiddleware() {
    return (next) => async (action) => {
       try{

            await keycloak.updateToken(5);

            res = await fetch(restCall.url, {
                ...restCall.options, ...{
                    credentials: 'same-origin',
                    headers: {
                        Authorization: 'Bearer ' + keycloak.token
                    }
                }
            });

       }catch(e){}
    }
Run Code Online (Sandbox Code Playgroud)

问题是,在令牌过期并执行 updateToken() 后,异步函数不会停止并在收到新访问令牌之前立即调用 fetch()。这当然会阻止 fetch 请求成功并导致响应代码为 401。updateToken() 返回一个 Promise,所以我看不出为什么 await 不起作用,这肯定正在发生。

我确认函数 inupdateToken().success(*function*)将在成功刷新令牌后执行,并将 fetch() 放入其中可以解决问题,但由于我们的中间件构造,我无法这样做。我开发了这个解决方法:

    function refreshToken(minValidity) {

        return new Promise((resolve, reject) => {

            keycloak.updateToken(minValidity).success(function () {
                resolve()
            }).error(function () {
                reject()
            });
        });
    }

    function restMiddleware() {
    return (next) => async (action) => {
       try{
            await refreshToken(5);

            res = await fetch(restCall.url, {
                ...restCall.options, ...{
                    credentials: 'same-origin',
                    headers: {
                        Authorization: 'Bearer ' + keycloak.token
                    }
                }
            });

       }catch(e){}
    }
Run Code Online (Sandbox Code Playgroud)

它有效,但并不优雅。

问题是:为什么第一个解决方案不起作用?为什么我不能等待 updateToken() 而必须使用 updateToken().success() 代替?

我怀疑这可能是一个错误,并确认这是这个问题的主要目的。

小智 3

updateToken方法的文档指出它返回 a Promise,但它实际上不是thenaable ,因此await关键字不认为它是有效的Promise。我就是这样说的。:)

您的解决方案对我来说似乎很优雅,我也做了完全相同的事情,以便Promise在调用updateToken函数后正确地继续在链上。

Keycloak JavaScript 适配器文档:https://keycloak.gitbooks.io/documentation/securing_apps/topics/oidc/javascript-adapter.html

  • 我刚刚查看了 keycloak.js,其中定义了此方法,我可以明白这一点。updateToken() 返回的根本不是 Promise(根据 ECMAScript 规范)。它是一些仅包含 success() 和 error() 函数的自定义对象,Keycloak 创建者将其命名为...“promise 对象”-.-“updateToken 方法返回一个 Promise 对象,这使得仅当令牌被调用时才可以轻松调用服务。刷新成功,例如,如果刷新失败,则向用户显示错误。” 这非常令人困惑,在我看来他们不应该使用这个描述。 (4认同)