8

I am creating an application for iOS and I am using this OAuth library. GET requests seem to work fine but as soon as I try to make POST requests I get the following error :

[code 32] Could not authenticate you.

Now I am not quite sure what is happening, as POST requests are generated pretty similarly to the GET requests. Any ideas what is causing this error ?

Here is the code generating the request:

+ (NSURLRequest *)preparedRequestForPath:(NSString *)path
                              parameters:(NSDictionary *)queryParameters
                              HTTPmethod:(NSString *)HTTPmethod
                              oauthToken:(NSString *)oauth_token
                             oauthSecret:(NSString *)oauth_token_secret
{
    if (!HTTPmethod
        || !oauth_token) return nil;



    NSMutableDictionary *allParameters = [self standardOauthParameters];
    allParameters[@"oauth_token"] = oauth_token;
    if (queryParameters) [allParameters addEntriesFromDictionary:queryParameters];

    NSString *parametersString = CHQueryStringFromParametersWithEncoding(allParameters, NSUTF8StringEncoding);

    NSString *request_url = API_URL;
    if (path) request_url = [request_url stringByAppendingString:path];
    NSString *oauth_consumer_secret = CONSUMER_SECRET;
    NSString *baseString = [HTTPmethod stringByAppendingFormat:@"&%@&%@", request_url.utf8AndURLEncode, parametersString.utf8AndURLEncode];
    NSString *secretString = [oauth_consumer_secret.utf8AndURLEncode stringByAppendingFormat:@"&%@", oauth_token_secret.utf8AndURLEncode];
    NSString *oauth_signature = [self.class signClearText:baseString withSecret:secretString];
    allParameters[@"oauth_signature"] = oauth_signature;

    NSString *queryString;
    if (queryParameters) queryString = CHQueryStringFromParametersWithEncoding(queryParameters, NSUTF8StringEncoding);
    if (queryString) request_url = [request_url stringByAppendingFormat:@"?%@", queryString];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:request_url]];
    request.HTTPMethod = HTTPmethod;

    NSMutableArray *parameterPairs = [NSMutableArray array];
    [allParameters removeObjectsForKeys:queryParameters.allKeys];
    for (NSString *name in allParameters) {
        NSString *aPair = [name stringByAppendingFormat:@"=\"%@\"", [allParameters[name] utf8AndURLEncode]];
        [parameterPairs addObject:aPair];
    }
    NSString *oAuthHeader = [@"OAuth " stringByAppendingFormat:@"%@", [parameterPairs componentsJoinedByString:@", "]];
    [request setValue:oAuthHeader forHTTPHeaderField:@"Authorization"];

    if ([HTTPmethod isEqualToString:@"POST"]
        && queryParameters != nil) {
        NSData *body = [queryString dataUsingEncoding:NSUTF8StringEncoding];
        [request setHTTPBody:body];
    }

    return request;
}

EDIT

The very last lines of the code where I set the HTTP body seem to cause the problem. When I remove the lines

 NSData *body = [queryString dataUsingEncoding:NSUTF8StringEncoding];
 [request setHTTPBody:body];

everything works fine, except when the parameters are exceptionally bigger like sending a base64 encoded image, where it obviously fails... What could I possibly do to fix this ?

the_critic
  • 12,720
  • 19
  • 67
  • 115

2 Answers2

1

Well...

I don't know what is cause it exactly. Can't send private message to non-follower.

How about API Console? It can be test Twitter APIs. maybe good to you.

First you test Direct Message API right way. and then compare results between API Console and your codes.

Sung-Pil Lim
  • 423
  • 3
  • 12
  • I am able to send messages, I just say that the culprit cannot be the permission because if I have access to direct messages then I surely would have to be able to make POST requests... But I am going to check out the console, that could potentially help me, I'll try it out and come back later. – the_critic May 22 '13 at 09:11
  • Could you print 'queryString' and 'request_url' when return 'request'? And I have Question! 'queryString' encoded UTF8 twice when method type 'POST' to setBody. – Sung-Pil Lim May 23 '13 at 01:20
  • Why don't use [Twitter API Libraries](https://dev.twitter.com/docs/twitter-libraries). Already exists Objective-C libraries. Have a any reason? – Sung-Pil Lim May 23 '13 at 01:33
  • I am using a library and this code is from the library. If I log the body of the returned request `NSLog(@"body = %@", [[NSString alloc]initWithData:preparedRequest.HTTPBody encoding:NSUTF8StringEncoding]);` I get back an example value of "body = id=336959346300829698" – the_critic May 23 '13 at 10:10
  • [401 error when trying to POST, no problems with GET](https://dev.twitter.com/discussions/1464) from twitter. Developer Twitter → Home → My application and then your Application's 'Settings' → 'Application Type' → checked 'Read, Write and Access direct messages' right? – Sung-Pil Lim May 24 '13 at 02:00
  • Ok look at my question again I edited it and came to the conclusion that the HTTP body was the problem. However I have to send my query parameters with the HTTP body because if the parameters are to large, the request will not go through... So a little problem still remains – the_critic May 24 '13 at 17:44
0

I solved the problem by adding the following HTTP header fields:

[request setValue:@"api.twitter.com" forHTTPHeaderField:@"X-HostCommonName"];
[request setValue:@"api.twitter.com" forHTTPHeaderField:@"Host"];
[request setValue:@"https://api.twitter.com" forHTTPHeaderField:@"X-Target-URI"];
[request setValue:@"Keep-Alive" forHTTPHeaderField:@"Connection"];
the_critic
  • 12,720
  • 19
  • 67
  • 115