-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Asterisks not encoded properly and result in error 32 "Could not authenticate you." #677
Comments
I'm having the same issue when posting @ or # in my search terms. I can't figure out where the conflict is, so I had to revert to 5.13.0 for my app to run properly. |
I've found that the same results occur using the https://dev.twitter.com/rest/tools/console. This seems to be an issue with the API, not with the gem. Any thoughts? |
Is there a work around for this? I thought I would be able to URL encode it manually if this gem doesn't do it but I don't get |
Sorry to re-raise this topic, but I'm getting the same on master. I am going around temporarily by replacing asterisk by *. I also tried what dredenba suggested of using the url encoded version and it does not work. |
I think I've figured out the cause of "Could not authenticate you" with https://github.com/sferik/twitter/blob/master/lib/twitter/rest/request.rb#L28 contains a call to @headers = Twitter::Headers.new(@client, @request_method, @uri, options).request_headers This creates the oauth http headers, which signs the contents of the request, including the options. When the request is sent response = http_client.headers(@headers).public_send(@request_method, @uri.to_s, options_key => @options) the http library encodes the form data, which is fine in most cases, but with Since the request is now different, the twitter api rejects the request with a 401 Unauthorized. |
Actually, after reading #888, it's the other way around, it's not being encoded. It seems related to httprb/http#449 , which suggests a workaround. This patch works for me.
|
Interesting patch @alzeih. However, this passes the tweet body into the URL as a GET parameter. So there are chances that we receive a |
@CedricBm it also doesn't work with image uploads - although not because of length, but due to how |
I'm also running into the same issue and can confirm that |
Hi, The 2.1.1 version of It allows to override the The following snippet overrides the encoding to act like the require "uri"
# The encoder method of the http gem needs to be overriden because of the twitter gem.
# Without that, there's an incompatibility between the simple_oauth gem which encodes asterisks and the http one which does not.
# Cf. https://github.com/httprb/form_data/issues/22 and https://github.com/sferik/twitter/issues/677
HTTP::FormData::Urlencoded.encoder = lambda do |enum|
unescaped_chars = /[^a-z0-9\-\.\_\~]/i
enum.map do |k, v|
if v.nil?
::URI::DEFAULT_PARSER.escape(k.to_s, unescaped_chars)
elsif v.respond_to?(:to_ary)
v.to_ary.map do |w|
str = ::URI::DEFAULT_PARSER.escape(k.to_s, unescaped_chars)
unless w.nil?
str << '='
str << ::URI::DEFAULT_PARSER.escape(w.to_s, unescaped_chars)
end
end.join('&')
else
str = ::URI::DEFAULT_PARSER.escape(k.to_s, unescaped_chars)
str << '='
str << ::URI::DEFAULT_PARSER.escape(v.to_s, unescaped_chars)
end
end.join('&')
end It's been a few weeks we're using this method and it seems fine so far. Be careful though, it can have some side effects if some of the other gems you're using depend on |
Reviving this one to say it's still affecting the latest version |
Open issue here: sferik/twitter-ruby#677 An * in a Tweet breaks authentication and the accepted fix ([c.f. Mastaton -> Twitter](renatolond/mastodon-twitter-poster#134) is to replace `*` with the wide-asterisk `*`. There is [some old evidence](sferik/twitter-ruby#677 (comment)) that the problem is actually with Twitter's API, not the twitter gem.
Running into this issue as well. Does anyone know if it's just asterisks leading to problems, or other characters as well? |
For me, the issue is only for asteriks. Other chars gets posted. |
Like @FabienChaynes said, the issue here is that oauth has different rules for escaping characters than the standard for application/x-www-form-urlencoded. The http lib and simpleoauth both work as intended, Twitter just still wants x-www-form-urlencoded requests to be encoded by oauth rules, which doesn't work. (Actually it almost always works, except if your Message has an Asterisk...) I came up with a solution that is basically the snippet from @FabienChaynes but this also checks if you are calling from inside the Twitter gem and decides based on that if it uses the default, or the decoding Twitter wants. That way we won't break the FormData Module for other libraries. Also, I tried to make simpleoauth build the signature without encoding the *. Building the signature this way worked, but the Twitter API still didn't accept Tweets with * in them. It seems like the only way to get Twitter to accept tweets is to encode the request forms using oauth escaping rules. I would have opened a pull request for this, but I don't really know where to put this, since I didn't find any obvious initialization that is done by the twitter gem. Maybe someone who is more familiar with the code has some idea about this? require "uri"
# The encoder method of the http gem needs to be overriden because of the twitter gem.
# Without that, there's an incompatibility between the simple_oauth gem which encodes asterisks and the http one which does not.
# Cf. https://github.com/httprb/form_data/issues/22 and https://github.com/sferik/twitter/issues/6# 77
# I added a check to see if this method has been called from inside the twitter gem, so that other libraries can still use the default behavior
HTTP::FormData::Urlencoded.encoder = lambda do |enum, enc = nil|
call_regex = Regexp.new(
'gems/twitter-[^/]+/lib/twitter/rest/request.rb:\d+:in `public_send\'')
if caller.any? call_regex
unescaped_chars = /[^a-z0-9\-\.\_\~]/i
enum.map do |k, v|
if v.nil?
::URI::DEFAULT_PARSER.escape(k.to_s, unescaped_chars)
elsif v.respond_to?(:to_ary)
v.to_ary.map do |w|
str = ::URI::DEFAULT_PARSER.escape(k.to_s, unescaped_chars)
unless w.nil?
str << '='
str << ::URI::DEFAULT_PARSER.escape(w.to_s, unescaped_chars)
end
end.join('&')
else
str = ::URI::DEFAULT_PARSER.escape(k.to_s, unescaped_chars)
str << '='
str << ::URI::DEFAULT_PARSER.escape(v.to_s, unescaped_chars)
end
end.join('&')
else
::URI.encode_www_form(enum, enc)
end
end |
Just for the record, I'm aware that including this snippet in the twitter lib isn't the best solution possible, even with the check for the calling function this could still break if some other lib also decides to override the default encoder, but I think this solution is still better than having this library not being able to send tweets with * in them. It's not great, but I think it's the next best thing to a clean solution. IMHO a clean solution would require something like Faraday, where you can have separate instances of request handlers that can have their own rules for encoding to not interfere with other libraries. I only started looking at this repository yesterday, so I don't know why exactly the switch away from Faraday was made, but unless Twitter decides to change something about their API, using Faraday (or some other request library) is probably the only clean solution. |
I’m an experienced developer, but I don’t speak Ruby. However, I went along with @Gordin in a long Twitter conversation (German though) while he dug into the issue and can confirm his conclusions. Let me try to summarize what everyone has said:
None of the libraries that this project is using is really at fault here: They all do their job correctly. However, the OAuth and the HTTP code escape the parameters according to different standards, which then causes the issue. That makes this library the correct place to fix it, because it is supposed to connect all the threads correctly, and it doesn’t. (Sorry 😉) Overriding the way in which the parameters are escaped in the HTTP request seems to be the only way to do this, and apart from switching to a different HTTP library, the snippet suggested by @Gordin seems to me to be the best solution. |
If the |
With updates from httprb/http#599 and httprb/form_data#29, the |
There is an issue with sending tweet messages as form data when they contain an asterisk. See sferik/twitter-ruby#677 for the equivalent issue in a ruby gem. This is because of a grey area between standards. We can resolve this by sending the tweet body as a URI encoded parameter instead of as form data in the body of the request. This commit also cleans up some variable names to make it a bit clearer what things are doing, and added a couple of comments. Fixes #2
Twitter-text (1.11.0) says that tweets with asterisks are valid. And I am also allowed to post them to Twitter directly. However, when posted through the Twitter gem (6.0.0) I receive the error: "Could not authenticate you." (code 32)
This forum post indicates that asterisks need to be URL encoded to be valid, so shouldn't the Twitter gem be handling this for me?
https://twittercommunity.com/t/asterisk/6343
The text was updated successfully, but these errors were encountered: