c# - ASP NET Core Twitter OAuth 请求 token 问题

标签 c# asp.net-core twitter oauth twitter-oauth

背景

我有一个具有 Twitter 应用程序设置的后端应用程序,我可以查询和提取用户推文/帖子数据。这很棒,但是,现在在前端我还没有完整的 Twitter 集成设置。我的意思是,在前端,用户可以输入任何 Twitter 用户名,并且我想确定输入的 Twitter 用户名实际上属于该用户。使用 Twitter 应用程序 key ,您可以提取任何 Twitter 帐户的公共(public) Twitter 数据,这非常适合大规模数据摄取,在我的情况下,可以进行概念验证工作。目前,我需要在后端强制执行这样的假设:为特定 Twitter 屏幕名称分析的数据也归我的 Web 应用程序上的帐户用户所有。

提议的 Twitter 解决方案

这是我一直在尝试遵循的一堆引用文档。

https://developer.twitter.com/en/docs/basics/authentication/guides/log-in-with-twitter https://developer.twitter.com/en/docs/basics/authentication/api-reference/request_token https://oauth.net/core/1.0/#anchor9 https://oauth.net/core/1.0/#auth_step1

我一直在尝试遵循这一点,并且对下面发布的代码进行了不同的排列(一种没有回调 URL 作为参数,一种带有等等),但在这一点上,并没有太大不同。我还没有取得任何成功,而且已经过去几天了,这让我很沮丧。

代码

这是我尝试遵循文档中上面提出的 OAuth 规范。请注意,这是 ASP.NET Core 2.2 + 代码。另外,这只是 Twitter OAuth 身份验证和授权指南中第 1 步的代码。

public async Task<string> GetUserOAuthRequestToken()
{
    int timestamp = (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
    string nonce = Convert.ToBase64String(Encoding.ASCII.GetBytes(timestamp.ToString()));

    string consumerKey = twitterConfiguration.ConsumerKey;
    string oAuthCallback = twitterConfiguration.OAuthCallback;

    string requestString =
        twitterConfiguration.EndpointUrl +
        OAuthRequestTokenRoute;

    string parameterString =
        $"oauth_callback={WebUtility.UrlEncode(twitterConfiguration.OAuthCallback)}&" +
        $"oauth_consumer_key={twitterConfiguration.ConsumerKey}&" +
        $"oauth_nonce={nonce}&" +
        $"oauth_signature_method=HMAC_SHA1&" +
        $"oauth_timestamp={timestamp}" +
        $"oauth_version=1.0";

    string signatureBaseString =
        "POST&" +
        WebUtility.UrlEncode(requestString) +
        "&" +
        WebUtility.UrlEncode(parameterString);

    string signingKey =
        twitterConfiguration.ConsumerSecret +
        "&" + twitterConfiguration.AccessTokenSecret;

    byte[] signatureBaseStringBytes = Encoding.ASCII.GetBytes(signatureBaseString);
    byte[] signingKeyBytes = Encoding.ASCII.GetBytes(signingKey);

    HMACSHA1 hmacSha1 = new HMACSHA1(signingKeyBytes);
    byte[] signature = hmacSha1.ComputeHash(signatureBaseStringBytes);

    string authenticationHeaderValue =
        $"oauth_nonce=\"{nonce}\", " +
        $"oauth_callback=\"{WebUtility.UrlEncode(twitterConfiguration.OAuthCallback)}\", " +
        $"oauth_signature_method=\"HMAC_SHA1\", " +
        $"oauth_timestamp=\"{timestamp}\", " +
        $"oauth_consumer_key=\"{twitterConfiguration.ConsumerKey}\", " +
        $"oauth_signature=\"{Convert.ToBase64String(signature)}\", " +
        $"oauth_version=\"1.0\"";

    HttpRequestMessage request = new HttpRequestMessage();
    request.Method = HttpMethod.Post;
    request.RequestUri = new Uri(
        baseUri: new Uri(twitterConfiguration.EndpointUrl),
        relativeUri: OAuthRequestTokenRoute);
    request.Content = new FormUrlEncodedContent(
        new Dictionary<string, string>() {
            { "oauth_callback", twitterConfiguration.OAuthCallback }
        });
    request.Headers.Authorization = new AuthenticationHeaderValue("OAuth",
        authenticationHeaderValue);

    HttpResponseMessage httpResponseMessage = await httpClient.SendAsync(request);

    if (httpResponseMessage.IsSuccessStatusCode)
    {
        return await httpResponseMessage.Content.ReadAsStringAsync();
    }
    else
    {
        return null;
    }
}

注释 我也尝试从参数中删除回调 URL,但没有成功。我已经尝试了各种略有不同的排列(对我的签名进行urlencode,在查询字符串中添加回调URL,将其删除等),但此时我已经失去了我已经尝试过但没有尝试过的排列(编码,引号等) .).

忽略我尚未将响应序列化到模型中的事实,因为目标是首先达到成功状态代码!

我也有一个针对此方法的集成测试设置,并且我不断收到 400 Bad Request,没有附加信息(这是有道理的),但绝对对调试没有帮助。

[Fact]
public async Task TwitterHttpClientTests_GetOAuthRequestToken_GetsToken()
{
    var result = await twitterHttpClient.GetUserOAuthRequestToken();

    Assert.NotNull(result);
}

顺便说一句,我还有其他一些问题:

  1. 有没有一种方法可以验证用户的 Twitter 帐户而无需访问 通过 OAuth 流程?我问这个的原因是因为 事实证明,通过 OAuth 流程很困难
  2. 在后端执行 Twitter 登录工作流程的第一步并将响应返回到前端是否安全?响应 将携带敏感 token 和 token secret 。 (如果我回答 我本人会说你必须这样做,否则你 必须将应用程序 secret 硬编码到前端配置中 哪个更糟)。我问这个是因为这一直在我的意识中 自从我开始做这件事以来,我有点担心。
  3. 是否有适用于 C# ASP.NET Core 的 OAuth 帮助程序库可以让这一切变得更容易?

最佳答案

我通过编写单元测试并阅读 Creating A Signature 上的 Twitter 文档解决了这个问题。 。由于该示例提供了键和结果,因此可以验证您的代码是否正确。

既然你询问了图书馆 - 我写了 LINQ to Twitter希望能帮助像我这样的人完成这项艰巨的任务。

除了签名之外,当您的代码通过 OAuth 流程工作时,页面导航也可能具有挑战性。请查看 Obtaining user access tokens 上的 Twitter 文档为了更好地理解这一点。我还在 LINQ to Twitter Wiki Securing your Applications 上记录了这一点。 。以下是如何与 LINQ to Twitter 配合使用:

  1. 首先,我有一个带有 Begin 操作的 OAuthController,用于将用户重定向到以启动身份验证过程:
public async Task<ActionResult> Begin()
{
    //var auth = new MvcSignInAuthorizer
    var auth = new MvcAuthorizer
    {
        CredentialStore = new SessionStateCredentialStore(HttpContext.Session)
        {
            ConsumerKey = configuration["Twitter:ConsumerKey"],
            ConsumerSecret = configuration["Twitter:ConsumerSecret"]
        }
    };

    string twitterCallbackUrl = Request.GetDisplayUrl().Replace("Begin", "Complete");
    return await auth.BeginAuthorizationAsync(new Uri(twitterCallbackUrl));
}

请注意,它使用 MvcSignInAuthorizer,通过 CredentialStore 属性传入凭据。如果您使用自己的原始代码,则需要使用 Authorization header 设置 HTTP 请求。

接下来,请注意我正在修改当前 URL,以便它将引用相同的 Controller ,但具有 Complete 端点。这是发送到 Twitter 授权的 oauth_callback

  • 该流程会将用户重定向到 Twitter 网站,他们会授权您的应用,然后使用 oauth_callback 将用户重定向回您的网站。处理方法如下:
  • public async Task<ActionResult> Complete()
    {
        var auth = new MvcAuthorizer
        {
            CredentialStore = new SessionStateCredentialStore(HttpContext.Session)
        };
    
        await auth.CompleteAuthorizeAsync(new Uri(Request.GetDisplayUrl()));
    
        // This is how you access credentials after authorization.
        // The oauthToken and oauthTokenSecret do not expire.
        // You can use the userID to associate the credentials with the user.
        // You can save credentials any way you want - database, 
        //   isolated storage, etc. - it's up to you.
        // You can retrieve and load all 4 credentials on subsequent 
        //   queries to avoid the need to re-authorize.
        // When you've loaded all 4 credentials, LINQ to Twitter will let 
        //   you make queries without re-authorizing.
        //
        //var credentials = auth.CredentialStore;
        //string oauthToken = credentials.OAuthToken;
        //string oauthTokenSecret = credentials.OAuthTokenSecret;
        //string screenName = credentials.ScreenName;
        //ulong userID = credentials.UserID;
        //
    
        return RedirectToAction("Index", "Home");
    }
    

    您再次可以看到我正在使用 MvcAuthorizer 并完成请求。完成请求后,您将能够提取 oauth_tokenoauth_token_secret,以及 screen_nameuser_id.您可以保存这些工件并在该用户的所有后续事件中重复使用它们,从而使他们的体验更好,因为他们不必在每次您需要发出请求时都登录。

    关于您的验证问题,有一个 Verify Credentials端点。

    LINQ to Twitter 有一个 ASP.NET Core Sample , API Samples 100% API 覆盖率,以及 Wiki 上的完整文档如果您想了解更多信息。

    关于c# - ASP NET Core Twitter OAuth 请求 token 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60688871/

    相关文章:

    C# 类字段声明中的 this 运算符

    c# - 如何检测动态绘制图形的点击?

    python - 使用 Tweepy (4.10.0) Tweet_id 获取推文回复

    c# - 如何从http header 获取文件大小

    c# - CreateProcessAsUser 进程以 -1073741502 退出

    c# - DNX SDK版本 'dnx-clr-win-x86.1.0.0-beta8-15530'安装失败

    asp.net-core - 无法解析类型 'Microsoft.AspNetCore.SignalR.Hub` 1[IXXXX ]' while attempting to activate ' XXXXX' 的服务

    c# - 注销后重定向在 Asp.net Core 2 中不起作用

    java - 从网络(Twitter)读取 JSON 数据

    ios - iOS SLComposeViewController“黑客”