Guest User

Alexandr

a guest
Aug 9th, 2012
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  
  2. #import "OAuth.h"
  3.  
  4.  
  5. // private
  6. @interface OAuth()
  7.  
  8. //@property (nonatomic, retain) OAuthState *oauthState;
  9. @property (nonatomic, retain) NSOperationQueue *queue;
  10.  
  11. -(void) processTemporaryCredentials:(ASIHTTPRequest *)request;
  12. -(void) processTokenCredentials:(ASIHTTPRequest *)request;
  13.  
  14.  
  15. - (id) init;
  16.  
  17. -(void) handleHttpError:(ASIHTTPRequest *)request;
  18. -(BOOL) isHttpSuccess:(int) status;
  19.  
  20. @end
  21.  
  22.  
  23.  
  24.  
  25. @implementation OAuth
  26.  
  27. @synthesize temporaryCredentialsUrl, ownerAuthorizationUrl, tokenCredentialsUrl;
  28. @synthesize consumerSecret, oauth_callback, oauth_consumer_key, realm;
  29. @synthesize oauthState;
  30. @synthesize queue;
  31.  
  32.  
  33. #pragma mark -
  34. #pragma mark init/dealloc
  35.  
  36.  
  37. - (id) init {
  38.     self = [super init];
  39.     if (self != nil){
  40.        
  41.         self.oauthState = [OAuthState new];
  42.        
  43.         // server URLs
  44.         self.temporaryCredentialsUrl = REQUEST_TEMPORARY_CREDENTIALS_URL;
  45.         self.ownerAuthorizationUrl = REQUEST_OWNER_AUTHORIZATION_URL;
  46.         self.tokenCredentialsUrl = REQUEST_TOKEN_CREDENTIALS_URL;
  47.         // normalize URLs. See http://tools.ietf.org/html/rfc5849#section-3.4.1.2
  48.         self.tokenCredentialsUrl = [OAuthUtils normalizeUrl:self.tokenCredentialsUrl];
  49.         self.ownerAuthorizationUrl = [OAuthUtils normalizeUrl:self.ownerAuthorizationUrl];
  50.         self.temporaryCredentialsUrl = [OAuthUtils normalizeUrl:self.temporaryCredentialsUrl];
  51.        
  52.         // client credentials
  53.         self.oauth_consumer_key = CONSUMER_KEY;
  54.         self.consumerSecret = CONSUMER_SECRET;
  55.        
  56.         self.oauth_callback = APPLICATION_CALLBACK_URL;
  57.        
  58.         // realm is *usually* fine empty. See http://tools.ietf.org/html/rfc2617#section-1.2
  59.         self.realm = @"";
  60.     }
  61.     return self;
  62. }
  63.  
  64.  
  65. -(void) dealloc {
  66.     [temporaryCredentialsUrl release], [ownerAuthorizationUrl release], [tokenCredentialsUrl release];
  67.     [consumerSecret release], [oauth_callback release], [oauth_consumer_key release], [realm release];
  68.     [oauthState release], [queue release];
  69.     [super dealloc];
  70. }
  71.  
  72.  
  73. #pragma mark -
  74. #pragma mark OAuth authentication steps
  75.  
  76.  
  77. /**
  78.  * Step ONE of the OAuth flow: Request temporary credentials.
  79.  *
  80.  * This method is described here:
  81.  *   - [http://tools.ietf.org/html/rfc5849#section-2.1 2.1. Temporary Credentials]
  82.  *   - [http://tools.ietf.org/html/rfc5849#section-3.1 3.1. Making Requests]
  83.  */
  84. -(BOOL) requestTemporaryCredentials {
  85.    
  86.     // reset the state of any previous OAuth flow
  87.     [self.oauthState reset];
  88.    
  89.     // nonce and timestamp: http://tools.ietf.org/html/rfc5849#section-3.3
  90.     NSString *encodedNonce = [OAuthUtils urlEncode:[OAuthUtils nonce]];
  91.     NSString *timestamp = [NSString stringWithFormat:@"%ld",time(NULL)];
  92.    
  93.     NSString *encodedConsumerKey = [OAuthUtils urlEncode:self.oauth_consumer_key];
  94.     NSString *encodedCallbackUrl = [OAuthUtils urlEncode:self.oauth_callback];
  95.    
  96.     // parameters = join(sort(urlEncode( parameter=value )), '&');
  97.     // http://tools.ietf.org/html/rfc5849#section-3.4.1.3.2
  98.     NSMutableString *parameterString;
  99.     {
  100.         // DON'T ALTER THE LINE ORDER in this block
  101.         // this could be done with KVC and sorting but unlike that, this is readable
  102.         parameterString = [NSMutableString string];
  103.         [parameterString appendFormat:@"%@=%@",   koauth_callback,         encodedCallbackUrl];
  104.         [parameterString appendFormat:@"&%@=%@",  koauth_consumer_key,     encodedConsumerKey];
  105.         [parameterString appendFormat:@"&%@=%@",  koauth_nonce,            encodedNonce];
  106.         [parameterString appendFormat:@"&%@=%@",  koauth_signature_method, koauth_signature_methodValue];
  107.         [parameterString appendFormat:@"&%@=%@",  koauth_timestamp,        timestamp];
  108.         [parameterString appendFormat:@"&%@=%@",  koauth_version,          koauth_versionValue];
  109.     }
  110.    
  111.     // baseString = HTTP_METHOD '&' urlEncode(normalized_url) '&' urlEncode(parameters)
  112.     // http://tools.ietf.org/html/rfc5849#section-3.4.1.1
  113.     NSString *baseString;
  114.     {
  115.         // note: all URLs were already normalized in the init method
  116.         NSString *encodedUrl = [OAuthUtils urlEncode:self.temporaryCredentialsUrl];
  117.         NSString *encodedParameters = [OAuthUtils urlEncode:parameterString];
  118.         baseString = [NSString stringWithFormat:@"POST&%@&%@", encodedUrl, encodedParameters];
  119.     }
  120.    
  121.     // signature = base64 ( hmac-sha1(baseString, signatureKey) )
  122.     NSString *signature = [OAuthUtils signBaseString:baseString
  123.                             withConsumerSecret:self.consumerSecret
  124.                                 andTokenSecret:@""]; // no secret token exists during this step
  125.    
  126.     // header: http://tools.ietf.org/html/rfc5849#section-3.5.1
  127.     NSMutableString *header = [NSMutableString string];
  128.     [header appendFormat:@"%@=\"\"", krealm];
  129.     [header appendFormat:@", %@=\"%@\"",  koauth_callback,         encodedCallbackUrl];
  130.     [header appendFormat:@", %@=\"%@\"",  koauth_consumer_key,     encodedConsumerKey];
  131.     [header appendFormat:@", %@=\"%@\"",  koauth_nonce,            encodedNonce];
  132.     [header appendFormat:@", %@=\"%@\"",  koauth_signature,        [OAuthUtils urlEncode:signature]];
  133.     [header appendFormat:@", %@=\"%@\"",  koauth_signature_method, koauth_signature_methodValue];
  134.     [header appendFormat:@", %@=\"%@\"",  koauth_timestamp,        timestamp];
  135.     [header appendFormat:@", %@=\"%@\"",  koauth_version,          koauth_versionValue];
  136.    
  137.    
  138. //    debug(@"\n\nREQUEST TEMPORARY CREDENTIALS\n  GET %@ \n  Authorization: \n    %@\n\n", self.temporaryCredentialsUrl,
  139. //          [header stringByReplacingOccurrencesOfString:@", " withString:@", \n    "]);
  140.    
  141.     // make the request
  142.     NSURL *url = [NSURL URLWithString:self.temporaryCredentialsUrl];
  143.     ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
  144.     request.requestMethod = @"POST";
  145.     [request addRequestHeader:@"Authorization" value:header];
  146.     [request setDelegate:self];
  147.     [request setDidFinishSelector:@selector(processTemporaryCredentials:)];
  148.     [request setDidFailSelector:@selector(handleHttpError:)];
  149.     //[[self queue] addOperation:request];
  150.     [request startSynchronous];
  151.  
  152.     debug(@"    OAuth state: %@", [self.oauthState describe]);    
  153.     return [self isHttpSuccess:request.responseStatusCode];
  154. }
  155.  
  156.  
  157. /**
  158.  * Process response of step one (request temporary credentials).
  159.  */
  160. -(void) processTemporaryCredentials:(ASIHTTPRequest *)request {
  161.    
  162.     // parse response: oauth_token=xxx &oauth_token_secret=xxx &oauth_callback_confirmed=true
  163.     NSMutableDictionary *dic = [NSMutableDictionary dictionary];
  164.     for (NSString *parts in [[request responseString] componentsSeparatedByString:@"&"]) {
  165.         NSArray *keyValues = [parts componentsSeparatedByString:@"="];
  166.         [dic setObject:[keyValues objectAtIndex:1] forKey:[keyValues objectAtIndex:0]];
  167.     }
  168.     // save state
  169.     self.oauthState.oauth_token = [dic objectForKey:koauth_token];
  170.     self.oauthState.oauth_token_secret = [dic objectForKey:koauth_token_secret];
  171.     //debug(@"oauthToken=%@ oauthTokenSecret=%@", self.oauthState.oauth_token, self.oauthState.oauth_token_secret);
  172. }
  173.  
  174.  
  175. /**
  176.  * Step TWO of the OAuth flow: request owner authorization.
  177.  */
  178. -(void) requestOwnerAuthorization {
  179.     NSString *url = [NSString stringWithFormat:@"%@?oauth_token=%@&oauth_callback=%@", self.ownerAuthorizationUrl, self.oauthState.oauth_token, self.oauth_callback];
  180.    
  181.     debug(@"    Launching browser for the owner authorization step");
  182.     [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
  183.     // execution continues in method application:handleOpenURL: of the delegate class
  184. }
  185.  
  186. /**
  187.  * Step THREE of the OAuth flow: Request an access token.
  188.  * See http://tools.ietf.org/html/rfc5849#section-2.3
  189.  *
  190.  * @param token temporary credentials identifier (aka oauth_token)
  191.  * @param verifier verification code (aka oauth_verifier)
  192.  */
  193. -(BOOL) requestTokenCredentials {
  194.    
  195.     NSString *encodedNonce = [OAuthUtils urlEncode:[OAuthUtils nonce]];
  196.     NSString *timestamp = [NSString stringWithFormat:@"%ld",time(NULL)];
  197.     NSString *encodedConsumerKey = [OAuthUtils urlEncode:self.oauth_consumer_key];
  198.    
  199.     // parameters = join(sort(urlEncode( parameter=value )), '&');
  200.     // http://tools.ietf.org/html/rfc5849#section-3.4.1.3.2
  201.     NSMutableString *parameterString;
  202.     {
  203.         // DON'T ALTER THE LINE ORDER in this block
  204.         parameterString = [NSMutableString string];
  205.         [parameterString appendFormat:@"%@=%@",   koauth_consumer_key,     encodedConsumerKey];
  206.         [parameterString appendFormat:@"&%@=%@",  koauth_nonce,            encodedNonce];
  207.         [parameterString appendFormat:@"&%@=%@",  koauth_signature_method, koauth_signature_methodValue];
  208.         [parameterString appendFormat:@"&%@=%@",  koauth_timestamp,        timestamp];
  209.         [parameterString appendFormat:@"&%@=%@",  koauth_token,            self.oauthState.oauth_token];
  210. //        [parameterString appendFormat:@"&%@=%@",  koauth_verifier,         self.oauthState.oauth_verifier];
  211.         [parameterString appendFormat:@"&%@=%@",  koauth_version,          koauth_versionValue];
  212.     }
  213.    
  214.     // baseString = HTTP_METHOD '&' urlEncode(normalized_url) '&' urlEncode(parameters)
  215.     // http://tools.ietf.org/html/rfc5849#section-3.4.1.1
  216.     NSString *baseString;
  217.     {
  218.         // note: all URLs were already normalized in the init method
  219.         NSString *encodedUrl = [OAuthUtils urlEncode:self.tokenCredentialsUrl];
  220.         NSString *encodedParameters = [OAuthUtils urlEncode:parameterString];
  221.         baseString = [NSString stringWithFormat:@"GET&%@&%@", encodedUrl, encodedParameters];
  222.     }
  223.    
  224.     //debug(@"base string: %@", [baseString stringByReplacingOccurrencesOfString:@"%26" withString:@"\n%26"]);
  225.    
  226.     // signature = base64 ( hmac-sha1(baseString, signatureKey) )
  227.     NSString *signature = [OAuthUtils signBaseString:baseString
  228.                             withConsumerSecret:self.consumerSecret
  229.                                 andTokenSecret:self.oauthState.oauth_token_secret];
  230.    
  231.      NSLog(@"signature -- %@", signature);
  232.    
  233.     NSMutableString *header = [NSMutableString string];
  234.     [header appendFormat:@"%@=\"\"",      krealm];
  235.     [header appendFormat:@", %@=\"%@\"",  koauth_consumer_key,     encodedConsumerKey];
  236.     [header appendFormat:@", %@=\"%@\"",  koauth_nonce,            encodedNonce];
  237.     [header appendFormat:@", %@=\"%@\"",  koauth_signature,        [OAuthUtils urlEncode:signature]];
  238.     [header appendFormat:@", %@=\"%@\"",  koauth_signature_method, koauth_signature_methodValue];
  239.     [header appendFormat:@", %@=\"%@\"",  koauth_timestamp,        timestamp];
  240.     // this call adds token and verifier
  241.     [header appendFormat:@", %@=\"%@\"",  koauth_token,            [OAuthUtils urlEncode:self.oauthState.oauth_token]];
  242. //    NSLog(@"token - %@   verifier - %@", self.oauthState.oauth_token, self.oauthState.oauth_verifier);
  243. //    [header appendFormat:@", %@=\"%@\"",  koauth_verifier,         [OAuthUtils urlEncode:self.oauthState.oauth_verifier]];
  244.     [header appendFormat:@", %@=\"%@\"",  koauth_version,          koauth_versionValue];
  245.     //debug(@"Authorization:\n%@", [header stringByReplacingOccurrencesOfString:@", " withString:@", \n"]);
  246.    
  247.     // POST
  248.     // make the request
  249.     NSURL *url = [NSURL URLWithString:self.tokenCredentialsUrl];
  250.     ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
  251.     request.requestMethod = @"GET";
  252.     [request addRequestHeader:@"Authorization" value:header];
  253.     [request setDelegate:self];
  254.     [request setDidFinishSelector:@selector(processTokenCredentials:)];
  255.     [request setDidFailSelector:@selector(handleHttpError:)];
  256.     //[[self queue] addOperation:request];
  257.     [request startSynchronous];
  258.    
  259.     debug(@"    OAuth state: %@", [self.oauthState describe]);
  260.     return [self isHttpSuccess:request.responseStatusCode];
  261. }
  262.  
  263.  
  264.  
  265. /** Second part of step one (request an unauthorized token). */
  266. -(void) processTokenCredentials:(ASIHTTPRequest *)request {
  267.    
  268.     // parse response: oauth_token=xxx &oauth_token_secret=xxx
  269.     NSMutableDictionary *dic = [NSMutableDictionary dictionary];
  270.     for (NSString *parts in [[request responseString] componentsSeparatedByString:@"&"]) {
  271.         NSArray *keyValues = [parts componentsSeparatedByString:@"="];
  272.         [dic setObject:[keyValues objectAtIndex:1] forKey:[keyValues objectAtIndex:0]];
  273.     }
  274.     [[NSNotificationCenter defaultCenter] postNotificationName:@"tripit_success" object:self userInfo:dic];
  275.     NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
  276.     self.oauthState.oauth_token = [dic objectForKey:koauth_token];
  277.     [defaults setObject:self.oauthState.oauth_token forKey:@"oauth_saved_token"];
  278.    
  279.     debug(@"Setting self.oauthState.oauth_token = %@", self.oauthState.oauth_token);
  280.    
  281.     self.oauthState.oauth_token_secret = [dic objectForKey:koauth_token_secret];
  282.     [defaults setObject:self.oauthState.oauth_token forKey:@"oauth_saved_token_secret"];
  283.     self.oauthState.authenticated = TRUE;
  284. }
  285.  
  286.  
  287.  
  288. -(ASIHTTPRequest*) accessProtectedResourceWithUrl:(NSString *)url {
  289.                          //andParameters:(NSDictionary*) parameters {
  290.     debug(@"    Authorized request %@", url);
  291.    
  292.     NSLog(@"%@", self.oauthState.oauth_token_secret);
  293.    
  294. //    NSUserDefaults* def = [NSUserDefaults standardUserDefaults];
  295.    
  296.     NSString *encodedNonce = [OAuthUtils urlEncode:[OAuthUtils nonce]];
  297.     NSString *timestamp = [NSString stringWithFormat:@"%ld",time(NULL)];//[def objectForKey:@"saved_timestamp"];
  298.     NSString *encodedConsumerKey = [OAuthUtils urlEncode:self.oauth_consumer_key];
  299.    
  300.     // parameters = join(sort(urlEncode( parameter=value )), '&');
  301.     // http://tools.ietf.org/html/rfc5849#section-3.4.1.3.2
  302.     NSMutableString *parameterString;
  303.     {
  304.         // DON'T ALTER THE LINE ORDER in this block
  305.         parameterString = [NSMutableString string];
  306.         [parameterString appendFormat:@"%@=%@",  koauth_consumer_key,     encodedConsumerKey];
  307.         [parameterString appendFormat:@"&%@=%@", koauth_nonce,            encodedNonce];
  308.         [parameterString appendFormat:@"&%@=%@", koauth_signature_method, koauth_signature_methodValue];
  309.         [parameterString appendFormat:@"&%@=%@", koauth_timestamp,        timestamp];
  310.         [parameterString appendFormat:@"&%@=%@", koauth_token,            self.oauthState.oauth_token];
  311.         [parameterString appendFormat:@"&%@=%@", koauth_version,          koauth_versionValue];
  312.     }
  313.    
  314.     // baseString = HTTP_METHOD '&' urlEncode(normalized_url) '&' urlEncode(parameters)
  315.     // http://tools.ietf.org/html/rfc5849#section-3.4.1.1
  316.     NSString *baseString;
  317.     {
  318.         // note: all URLs were already normalized in the init method
  319.         NSString *encodedUrl = [OAuthUtils urlEncode:url];
  320.         NSString *encodedParameters = [OAuthUtils urlEncode:parameterString];
  321.         baseString = [NSString stringWithFormat:@"GET&%@&%@", encodedUrl, encodedParameters];
  322.     }
  323.    
  324.     //debug(@"base string: %@", [baseString stringByReplacingOccurrencesOfString:@"%26" withString:@"\n%26"]);
  325.    
  326.     // signature = base64 ( hmac-sha1(baseString, signatureKey) )
  327.     NSString *signature = [OAuthUtils signBaseString:baseString
  328.                             withConsumerSecret:self.consumerSecret
  329.                                 andTokenSecret:self.oauthState.oauth_token_secret];
  330.     NSLog(@"signature -- %@", signature);
  331.    
  332.     NSMutableString *header = [NSMutableString string];
  333.     [header appendFormat:@"%@=\"\"", krealm];
  334.     [header appendFormat:@", %@=\"%@\"", koauth_consumer_key,     encodedConsumerKey];
  335.     [header appendFormat:@", %@=\"%@\"", koauth_nonce,            encodedNonce];
  336.     [header appendFormat:@", %@=\"%@\"", koauth_signature,        [OAuthUtils urlEncode:signature]];
  337.     [header appendFormat:@", %@=\"%@\"", koauth_signature_method, koauth_signature_methodValue];
  338.     [header appendFormat:@", %@=\"%@\"", koauth_timestamp,        timestamp];
  339.     [header appendFormat:@", %@=\"%@\"", koauth_version,          koauth_versionValue];
  340.     // new parmeter
  341.     [header appendFormat:@", %@=\"%@\"", koauth_token,            [OAuthUtils urlEncode:self.oauthState.oauth_token]];
  342.    
  343.     /*
  344.     for (NSString* key in parameters) {
  345.         NSString* obj = [parameters objectForKey:key];
  346.         [header appendString:[NSString stringWithFormat:@", %@=\"%@\"", key, [self urlEncode:obj] ] ];
  347.     }
  348.     */
  349.    
  350.     // TODO: any other parameter that goes in the request
  351.     // debug(@"Authorization:\n%@", [header stringByReplacingOccurrencesOfString:@", " withString:@", \n"]);
  352.    
  353.     // POST
  354.     // make the request
  355.     NSURL *theUrl = [NSURL URLWithString:url];
  356.     ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:theUrl];
  357.     request.requestMethod = @"GET";
  358.     [request addRequestHeader:@"Authorization" value:header];
  359.     [request setDelegate:self];
  360.     //[request setDidFinishSelector:@selector(processProtectedResource:)];
  361.     [request setDidFailSelector:@selector(handleHttpError:)];
  362.     //[[self queue] addOperation:request];
  363.     [request startSynchronous];
  364. //    req = [[[NSURLRequest alloc]initWithURL:[NSURL URLWithString:url]]autorelease];
  365.    
  366. //    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES];
  367.    
  368.     return [self isHttpSuccess:request.responseStatusCode] ? request : nil;
  369. }
  370.  
  371.  
  372. /**
  373.  * Return TRUE if the HTTP operation is in the 2xx range.
  374.  *
  375.  * According to http://tools.ietf.org/html/rfc5849#section-2.3
  376.  * OAuth operations should return 200, but 11870 returns 201.
  377.  */
  378. -(BOOL) isHttpSuccess:(int) status {
  379.     return status>199 && status <207;
  380. }
  381.  
  382.  
  383. #pragma mark -
  384. #pragma mark utility methods
  385.  
  386.  
  387. -(void) handleHttpError:(ASIHTTPRequest *)request {
  388.     // this should be a 200
  389.     // http://tools.ietf.org/html/rfc5849#section-2.3
  390.     int status = request.responseStatusCode;
  391.     BOOL success = [self isHttpSuccess:status];
  392.     debug(@"11870 returned %d for the access token phase", status);
  393.     if (!success) { // 11870 may return 201 (not sure), it should be 200
  394.         // request failed
  395.         NSString *error = [[request error] localizedDescription];
  396.         debug(@"error=%@, status=%d, response=%@", error, status, request.responseString);
  397.         // hmm reset state or retry?
  398.         return;
  399.     }
  400. }
  401.  
  402.  
  403. #pragma mark -
  404. #pragma mark oauth state
  405.  
  406. /** @return TRUE if we are ready to access protected resources. */
  407. -(BOOL) isAuthenticated {
  408.     return self.oauthState.authenticated;
  409. }
  410.  
  411. -(void) resetState {
  412.     [self.oauthState reset];
  413. //    debug(@"    State resetted to: %@", [oauthState describe]);
  414. }
  415.  
  416. -(NSString*) describeState {
  417.     return [self.oauthState describe];
  418. }
  419.  
  420.  
  421. @end
Add Comment
Please, Sign In to add comment