How do I get NSURLRequest to get the Twitter request token?

I am trying to get the request token from Twitter using this code:

NSMutableURLRequest *mURLRequest = [[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:@"https://api.twitter.com/oauth/request_token"]];
mURLRequest.HTTPMethod = @"POST /oauth/request_token HTTP/1.1";
[mURLRequest setValue:@"User-Agent" forHTTPHeaderField:@"Coupled HTTP"];
[mURLRequest setValue:@"OAuth oauth_callback=\"http%3A%2F%2Fbytolution.com\"" forHTTPHeaderField:@"Authorization"];
[mURLRequest setValue:@"api.twitter.com" forHTTPHeaderField:@"Host"];
[mURLRequest setValue:@"Accept" forHTTPHeaderField:@"*/*"];

NSHTTPURLResponse *urlResponse;
NSError *error;
NSError *serializationError;
NSData *responseData = [NSURLConnection sendSynchronousRequest:mURLRequest returningResponse:&urlResponse error:&error];
NSLog(@"data: %@, response:%@, error: %@", [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&serializationError], urlResponse.allHeaderFields, error);

      

But I will only return:

data: (null), response:{ Connection = close; "Content-Length" = 0; }, error: (null)

Here is the Twitter documentation for this topic.

Thank you for your help!

+1


source to share


2 answers


After two days of frustration and Twitter curse, I was finally able to do it. Here is my implementation. The class to be used for the request will be "BL_TwitterRequest". This is only done to get the Twitter request token.

BL_TwitterRequest.h:

#import <Foundation/Foundation.h>

@interface BL_Request : NSObject <NSURLConnectionDelegate>

@property (nonatomic, strong) NSMutableData *webData;

-(void) makeRequest;

      

Add the following NSString category to the top of the implementation class (BL_TwitterRequest.m). This will be used to get the URL encoded version of the NSString.

@implementation NSString (NSString_Extended)

- (NSString *)urlencode {
    NSMutableString *output = [NSMutableString string];
    const unsigned char *source = (const unsigned char *)[self UTF8String];
    int sourceLen = strlen((const char *)source);
    for (int i = 0; i < sourceLen; ++i) {
        const unsigned char thisChar = source[i];
        if (thisChar == ' '){
            [output appendString:@"+"];
        } else if (thisChar == '.' || thisChar == '-' || thisChar == '_' || thisChar == '~' ||
                   (thisChar >= 'a' && thisChar <= 'z') ||
                   (thisChar >= 'A' && thisChar <= 'Z') ||
                   (thisChar >= '0' && thisChar <= '9')) {
            [output appendFormat:@"%c", thisChar];
        } else {
            [output appendFormat:@"%%%02X", thisChar];
        }
    }
    return output;
}

@end

      

Add the function below to "BL_TwitterRequest.m". It will be used to generate the oAuth nonce. The function basically generates a random string with a given length.

-(NSString*) generateRandomStringOfLength:(int)length {

    NSString *letters = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    NSMutableString *randomString = [NSMutableString stringWithCapacity: length];
    for (int i = 0; i < length; i++) {
        [randomString appendFormat: @"%C", [letters characterAtIndex: arc4random() % [letters length]]];
    }

    return randomString;
}

      

Include the Base64 library from here . All you have to do is drag and drop the Base64.h and Base64.m files into your project. Add the following imports:

#include <CommonCrypto/CommonDigest.h>
#include <CommonCrypto/CommonHMAC.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#import "Base64.h"

      

Add one more function as below. This will be used to get the HMAC-SHA1 value.



- (NSString *)hmacsha1:(NSString *)data secret:(NSString *)key {

    const char *cKey  = [key cStringUsingEncoding:NSASCIIStringEncoding];
    const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];

    unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH];

    CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC);

    NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];

    NSString *hash = [HMAC base64EncodedString];

    return hash;
}

      

Now for the main function that will make the request.

-(void) makeRequest {

    _webData = [[NSMutableData alloc]init]; // WILL BE USED BY NSURLConnection

    NSString *httpMethod = @"POST";
    NSString *baseURL = @"https://api.twitter.com/oauth/request_token";
    NSString *oauthConsumerKey = @"YOUR_CONSUMER_KEY";
    NSString *oauthConsumerSecret = @"YOUR_CONSUMER_SECRET";
    NSString *oauth_timestamp = [NSString stringWithFormat:@"%.f", [[NSDate date]timeIntervalSince1970]];
    NSString *oauthNonce = [self generateRandomStringOfLength:42];
    NSString *oauthSignatureMethod = @"HMAC-SHA1";
    NSString *oauthVersion = @"1.0";
    NSString *oauthCallback = @"YOUR_TWITTER_CALLBACK_URL"; 

    //1. PERCENT CODE EVERY KEY AND VALUE THAT WILL BE SIGNED AND
    //   APPEND KEY AND VALUE WITH = AND &

    NSMutableString *parameterString = [[NSMutableString alloc]initWithFormat:@""];

    [parameterString appendFormat:@"oauth_callback=%@", [oauthCallback urlencode]];
    [parameterString appendFormat:@"&oauth_consumer_key=%@", [oauthConsumerKey urlencode]];
    [parameterString appendFormat:@"&oauth_nonce=%@", [oauthNonce urlencode]];
    [parameterString appendFormat:@"&oauth_signature_method=%@", [oauthSignatureMethod urlencode]];
    [parameterString appendFormat:@"&oauth_timestamp=%@", [oauth_timestamp urlencode]];
    [parameterString appendFormat:@"&oauth_version=%@", [oauthVersion urlencode]];

    //2. CREATE SIGNATURE STRING WITH HTTP METHOD AND ENCODED BASE URL AND PARAMETER STRING

    NSString *signatureBaseString = [NSString stringWithFormat:@"%@&%@&%@", httpMethod, [baseURL urlencode], [parameterString urlencode]];

    //3. GET THE SIGNING KEY NOW FROM CONSUMER SECRET

    NSString *signingKey = [NSString stringWithFormat:@"%@&", [oauthConsumerSecret urlencode]];

    //4. GET THE OUTPUT OF THE HMAC ALOGRITHM

    NSString *oauthSignature = [self hmacsha1:signatureBaseString secret:signingKey];

    // TIME TO MAKE THE CALL NOW

    NSMutableString *urlString = [[NSMutableString alloc]initWithFormat:@""];

    [urlString appendFormat:@"%@", baseURL];

    // INITIALIZE AUTHORIZATION HEADER

    NSMutableString *authHeader = [[NSMutableString alloc]initWithFormat:@""];

    [authHeader appendFormat:@"OAuth "]; // MIND THE SPACE AFTER 'OAuth'

    [authHeader appendFormat:@"oauth_nonce=\"%@\",", [oauthNonce urlencode]];
    [authHeader appendFormat:@"oauth_callback=\"%@\",", [oauthCallback urlencode]];
    [authHeader appendFormat:@"oauth_signature_method=\"%@\",", [oauthSignatureMethod urlencode]];
    [authHeader appendFormat:@"oauth_timestamp=\"%@\",", [oauth_timestamp urlencode]];
    [authHeader appendFormat:@"oauth_consumer_key=\"%@\",", [oauthConsumerKey urlencode]];
    [authHeader appendFormat:@"oauth_signature=\"%@\",", [oauthSignature urlencode]];
    [authHeader appendFormat:@"oauth_version=\"%@\"", [oauthVersion urlencode]];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:urlString]] ;

    [request setHTTPMethod:httpMethod];

    [request setValue:authHeader forHTTPHeaderField:@"Authorization"];

    NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];

    [connection start];

}

      

Now, just implement the NSURLConnection delegate methods to get the answer.

#pragma mark - Connection Delegate

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {

    [_webData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {

    NSString *resultString = [[NSString alloc]initWithData:_webData encoding:NSUTF8StringEncoding];

    NSLog(@"RESULT STRING : %@", resultString);  
}

      

If all goes well, "resultString" will have an oauth_token and an oauth_token_secret.

To make a call, follow these steps:

 BL_TwitterRequest *twitterRequest = [[BL_TwitterRequest alloc]init];
 [twitterRequest makeRequest];

      

Be aware that missing spaces or commas can lead to an error.

+2


source


Several errors (not sure if the list is complete, this is what I found at first glance):



  • The HTTP method should be simple @"POST"

    , not @"POST foo"

    , @"POST or I will kill you"

    or anything else;
  • Similarly, it @"OAuth oauth_callback=\""

    should be @"oauth_callback=\""

    ;
  • You do not include all the required header fields, such as oauth_consumer_key

    , oauth_signature

    , oauth_signature_method

    , oauth_nonce

    and oauth_timestamp

    ;
  • This doesn't return JSON. It returns a URL encoded response, something like the example in the official documentation .
+1


source







All Articles