OAuthConsumer and Twitpic

3.4k Views Asked by At

I'm trying to post images to TwitPic using OAuthConsumer. I keep receiving a 401 "Could not authenticate you (header rejected by twitter)." error.

I am also making use of the Twitter+OAuth library to handle the login and posting regular tweets, and then saving the token and token secret for using with TwitPic.

This is the code I am using the construct the request:

NSURL *twitpicUrl = [NSURL URLWithString:@"http://api.twitpic.com/2/upload.json"];
NSString* realm = @"http://api.twitter.com/";
OAToken* oaToken = [[OAToken alloc] initWithKey:savedToken secret:savedTokenSecret];
OAConsumer* oaConsumer = [[OAConsumer alloc] initWithKey:kOAuthConsumerKey secret:kOAuthConsumerSecret];

OAMutableURLRequest *request = [[[OAMutableURLRequest alloc] initWithURL:twitpicUrl consumer:oaConsumer
                                    token:oaToken realm:realm signatureProvider:nil] autorelease];
[request prepare];
[request setHTTPMethod:@"POST"];
[request setValue:@"https://api.twitter.com/1/account/verify_credentials.json" forHTTPHeaderField:@"X-Auth-Service-Provider"];

NSString* authorizeHeader = [request valueForHTTPHeaderField:@"Authorization"];
[request setValue:authorizeHeader forHTTPHeaderField:@"X-Verify-Credentials-Authorization"];

And if I print out my headers, this is what I get (excluding the unused Authorization header):

    "X-Auth-Service-Provider" = "https://api.twitter.com/1/account/verify_credentials.json";
    "X-Verify-Credentials-Authorization" = "OAuth realm=\"http%3A%2F%2Fapi.twitter.com%2F\", oauth_consumer_key=\"JOvwW7mtZUjRXZRInkQI7w\", oauth_token=\"293217559-pD0HL0oE6TZSkU35mPnc7kia325oPDgMfQMTVArK\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"ctmCK35JFwx8qs8lQj0AYB6sUr4%3D\", oauth_timestamp=\"1304580843\", oauth_nonce=\"7EBE3EB0-641A-40EA-A57C-8D071B5E647F\", oauth_version=\"1.0\"";

The error I receive is:

Error: The operation couldn’t be completed. (NSURLErrorDomain error -1012.)
{"errors":[{"code":401,"message":"Could not authenticate you (header rejected by twitter)."}]}

I have excluded some detail here, specifically appending the post data, mainly because I don't think it's relevant to the error. If you think otherwise let me know and I'll update the question.

Can anyone help?

Update: Here is the code that I am now using successfully

In header:

#define kVerifyCredentialsUrl @"https://api.twitter.com/1/account/verify_credentials.json"
#define kTwitPicUrl @"http://api.twitpic.com/2/upload.json"

Implementation:

//prepare the verify credentials header
NSURL* serviceUrl = [NSURL URLWithString:kVerifyCredentialsUrl];
NSString* realm = @"http://api.twitter.com/";
OAToken* token = [[OAToken alloc] initWithKey:tokenKey secret:tokenSecret];
OAConsumer* consumer = [[OAConsumer alloc] initWithKey:kOAuthConsumerKey secret:kOAuthConsumerSecret];
OAMutableURLRequest *request = [[OAMutableURLRequest alloc] initWithURL:serviceUrl consumer:consumer token:token realm:realm signatureProvider:nil];
[request setHTTPMethod:@"GET"];
[request prepare];
NSDictionary* headerDictionary = [request allHTTPHeaderFields];
NSString* oAuthHeader = [NSString stringWithString:[headerDictionary valueForKey:@"Authorization"]];
[request release];
request = nil;

//prepare the full request
serviceUrl = [NSURL URLWithString:kTwitPicUrl];
request = [[OAMutableURLRequest alloc] initWithURL:serviceUrl consumer:consumer token:token realm:realm signatureProvider:nil];
[request setHTTPMethod:@"POST"];
[request setValue:kVerifyCredentialsUrl forHTTPHeaderField:@"X-Auth-Service-Provider"];
[request setValue:oAuthHeader forHTTPHeaderField:@"X-Verify-Credentials-Authorization"];

//add the content and start the request
UIImage* imageToUpload = [UIImage imageNamed:@"test.png"];
NSData *data = UIImagePNGRepresentation(imageToUpload);
ASIFormDataRequest *asiRequest = [[[ASIFormDataRequest alloc] initWithURL:[NSURL URLWithString:kTwitPicUrl]] autorelease];
[asiRequest addRequestHeader:@"X-Auth-Service-Provider" value:kVerifyCredentialsUrl];
[asiRequest addRequestHeader:@"X-Verify-Credentials-Authorization" value:oAuthHeader];
[asiRequest setPostValue:@"Message here" forKey:@"message"];
[asiRequest setPostValue:kTwitPicAPIKey forKey:@"key"];
[asiRequest setData:data forKey:@"media"];
[asiRequest setDidFinishSelector:@selector(requestDone:)];
[asiRequest setDidFailSelector:@selector(requestWentWrong:)];
[asiRequest setDelegate:self];
[asiRequest startAsynchronous];
2

There are 2 best solutions below

1
On BEST ANSWER

Try this :

NSURL *serviceURL = [NSURL URLWithString:@"https://api.twitter.com/1/account/verify_credentials.json"];
OAMutableURLRequest *oRequest = [[OAMutableURLRequest alloc] initWithURL:serviceURL
                                                                consumer:consumer_
                                                                   token:accessToken_
                                                                   realm:@"http://api.twitter.com/"
                                                       signatureProvider:nil];
[oRequest setHTTPMethod:@"GET"];
[oRequest prepare];
NSDictionary * headerDict = [oRequest allHTTPHeaderFields];
NSString * oauthHeader = [NSString stringWithString:[headerDict valueForKey:@"Authorization"]];
[oRequest release];

//  Prepare the POST request
oRequest = nil;
serviceURL = nil;
serviceURL = [NSURL URLWithString:@"http://api.twitpic.com/2/upload.json"];
oRequest = [[OAMutableURLRequest alloc] initWithURL:serviceURL
                                               consumer:consumer_
                                                  token:accessToken_
                                                  realm:@"http://api.twitter.com/"
                                      signatureProvider:nil];
[oRequest setHTTPMethod:@"POST"];
[oRequest setValue:@"https://api.twitter.com/1/account/verify_credentials.json" forHTTPHeaderField:@"X-Auth-Service-Provider"];
[oRequest setValue:oauthHeader forHTTPHeaderField:@"X-Verify-Credentials-Authorization"];

You should also make this change in OAMutableURLRequest.m at the end of the method - (void)prepare:

 NSString *oauthHeader = [NSString stringWithFormat:@"OAuth realm=\"%@\", oauth_consumer_key=\"%@\", %@oauth_signature_method=\"%@\", oauth_signature=\"%@\", oauth_timestamp=\"%@\", oauth_nonce=\"%@\", oauth_version=\"1.0\"%@",
                         [realm URLEncodedString],
                         [consumer.key URLEncodedString],
                         oauthToken,
                         [[signatureProvider name] URLEncodedString],
                         [signature URLEncodedString],
                         timestamp,
                         nonce,
                         extraParameters];
if(![self valueForHTTPHeaderField:@"X-Verify-Credentials-Authorization"])
    [self setValue:oauthHeader forHTTPHeaderField:@"Authorization"];
0
On

It may also be a problem with twitter right now. My code using OAMutableURLRequest like yours, has been working fine for ages, and today I keep getting the 401 error code. Searching twitter you will find more people having this problem recently.

This is what you can read now in the api status page:

We are currently experiencing elevated error rates. There may be intermittent issues loading twitter.com and Twitter clients. We are aware of the problem and taking action. Thanks for your patience!

Twitter API Status