【问题标题】:AuthFlow.CreateCredentialsFromVerifierCode throws error only on load balancerAuthFlow.CreateCredentialsFromVerifierCode 仅在负载均衡器上引发错误
【发布时间】:2016-10-02 02:54:26
【问题描述】:

我正在使用 Tweetinvi 将图像发布到 Twitter。 从我们的应用服务器可以正常发布到 Twitter。 但是,当尝试从我们的负载均衡器中得到这个错误时 -

错误:需要凭据,因为 URL 不包含 凭据标识符。

堆栈跟踪:在 Tweetinvi.AuthFlow.CreateCredentialsFromVerifierCode(String 验证者代码、字符串 authenticationId、IAuthenticationContext authContext)

我的代码sn-p是这样的-

var verifierCode = Request.Params.Get("oauth_verifier");
var authorizationId = Request.Params.Get("authorization_id");
var userCreds = AuthFlow.CreateCredentialsFromVerifierCode(verifierCode, authorizationId);

我看到这些参数(oauth_verifier、authorization_id、..)被传递到回调页面。但是在回调页面还是看到了上面的错误。

注意:仅当我尝试在我们的负载平衡器上发布到 Twitter 时(使用运行良好的单个服务器)时才会出现此问题。 我应该使用不同的重载函数吗?

【问题讨论】:

    标签: twitter twitter-oauth tweetinvi


    【解决方案1】:

    所以问题出在您实际上使用的是负载平衡器这一事实。但让我解释一下身份验证的工作原理以及如何解决您的问题。

    var appCredentials = new ConsumerCredentials("", "");
    var authContext = AuthFlow.InitAuthentication(appCredentials, "");
    

    当您调用AuthFlow.InitAuthentication 时,它会返回一个IAuthenticationContext。此上下文包含处理来自 Twitter 的回调所需的所有信息。

    但除此之外,Tweetinvi 在回调中添加了一个参数authorization_id,以便它可以将回调请求映射到实际的IAuthenticationContext

    var authorizationId = Request.Params.Get("authorization_id");
    var userCreds = AuthFlow.CreateCredentialsFromVerifierCode(verifierCode, authorizationId);
    

    当您使用authorization_id 作为参数调用AuthFlow.CreateCredentialsFromVerifierCode 时,它会查找本地字典并尝试获取IAuthenticationContext

    因为您使用的是负载均衡器,所以执行AuthFlow.InitAuthentication 的服务器可能与您接收回调请求的服务器不同。

    因为您的回调到达不同的服务器,它实际上导致AuthenticationContext 为空。

    这是我在documentation中试图解释的。

    如何解决?

    您需要做的是存储CreateCredentialsFromVerifierCode 在收到回调时继续工作所需的IAuthenticationContext 信息。我建议您将其存储在您的数据库中。

    当您收到回拨时,您必须从您的数据库中取回这些信息。为此,我建议您在最初调用 `` 时向回调 url 添加一个参数,该参数的值将身份验证 ID 存储在数据库中(例如 my_auth_db_id=42)。

    var authContext = AuthFlow.InitAuthentication(appCredentials, "http://mywebsite.com?my_auth_db_id=42");
    

    当您的回调到达时,您将能够:

    var myDBAuthId = Request.Params.Get("my_auth_db_id");
    

    使用此值,您现在可以使用所需信息(存储在数据库中)创建新令牌。

    var token = new AuthenticationToken()
    {
        AuthorizationKey = "<from_db>",
        AuthorizationSecret = "<from_db>",
        ConsumerCredentials = creds
    };
    

    现在您可以完成操作了:

    var userCreds = AuthFlow.CreateCredentialsFromVerifierCode(verifierCode, token );
    

    我知道这是一篇大文章,但我想解释一下它是如何工作的。 如果有任何不妥之处,请告诉我。

    【讨论】:

    • 感谢 Linvi,但是,从负载均衡器成功 - AuthFlow.InitAuthentication(applicationCredentials, callBackURL);加载回调页面时, AuthFlow.CreateCredentialsFromVerifierCode(verifierCode, authorizationId);失败了。您确定这与负载均衡器上的设置(时间和区域设置正确)有关吗?
    • 作为我们谈话的结果,将在 Tweetinvi 0.9.13.0 中添加一个新功能,该功能将使用户能够指定 authorization_id 的值。这样您就可以决定如何将 id 存储在数据库中(int、long、guid...)
    • 感谢 Linvi 的宝贵时间。所以,如果我理解正确 - 在第一步中,通过调用 - AuthFlow.InitAuthentication(applicationCredentials, callBackURL) 获取 authContext 后,我​​需要将 authContext 对象存储在我们的数据库中(并映射到一个 id)?相反,如果我只在我们的数据库中存储 authContext.Token.AuthorizationKey、authContext.Token.AuthorizationSecret 就足够了吗?在第二步(在回调中)- 从 DB 中检索这些值并创建 AuthenticationToken 对象。并将其传递给 AuthFlow.CreateCredentialsFromVerifierCode()
    • 没错。您唯一需要存储的是AuthorizationKeyAuthorizationSecret。虽然确保在重建 AuthenticationToken 时设置 ConsumerCredentials
    • 我们可以使用这个重载函数吗 - AuthFlow.CreateCredentialsFromVerifierCode(verifierCode, authKeyFromCookie, authSecretFromCookie, key, secret)
    猜你喜欢
    • 2021-12-07
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    • 2021-10-14
    相关资源
    最近更新 更多