This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
Can't get Twitter OAuth callback authentication to work in Cocoa application
I have an application that sends Twitter updates (tweets). The current version does OAuth authentication using the OOB process:
(1) Send request token request:
consumer = [[OAConsumer alloc] initWithKey: kOAuthConsumerKey secret:kOAuthConsumerSecret];
OAMutableURLRequest *request = [[[OAMutableURLRequest alloc]
initWithURL: [NSURL URLWithString:kOAuthTwitterRequestTokenURL]
consumer: self.consumer
token: nil realm: nil signatureProvider: nil] autorelease];
[request setHTTPMethod:#"POST"];
OADataFetcher *fetcher = [[[OADataFetcher alloc] init] autorelease];
[fetcher fetchDataWithRequest:request delegate:self didFinishSelector:#selector(setRequestToken:withData:) didFailSelector:#selector(failRequestToken:data:)];
(2) Then assemble the authentication URL and open a browser window:
NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
self.requestToken = [[[OAToken alloc] initWithHTTPResponseBody:dataString] autorelease];
NSString *urlString = [NSString stringWithFormat: #"%#?oauth_token=%#", kOAuthTwitterAuthorizeURL, self.requestToken.key];
NSURL *requestURL = [NSURL URLWithString: urlString];
[[NSWorkspace sharedWorkspace] openURL: requestURL];
(3) Pop up an Alert Window with a text field, and get the PIN number from the user, then:
self.requestToken.secret = [input stringValue];
OAMutableURLRequest *request = [[OAMutableURLRequest alloc] initWithURL:[NSURL URLWithString:kOAuthTwitterAccessTokenURL] consumer: self.consumer token: self.requestToken realm: nil signatureProvider: nil];
[request setHTTPMethod:#"POST"];
OADataFetcher *fetcher = [[[OADataFetcher alloc] init] autorelease];
[fetcher fetchDataWithRequest:request delegate:self didFinishSelector:#selector(setAccessToken:withData:) didFailSelector:#selector(failAccessToken:data:)];
(4) Save the return credentials:
NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
accessToken = [[OAToken alloc] initWithHTTPResponseBody:dataString];
[accessToken storeInUserDefaultsWithServiceProviderName: kOAuthTwitterDefaultsDomain prefix: kOAuthTwitterDefaultsPrefix];
(Memory Management and error checking removed for brevity)
This all works fine, but I really hate the process of redirecting to a browser and then making the user copy and paste the PIN number. I wanted to stop using the OOB method and go to the callback method. That takes some finagling for a Desktop application. So I switched to using a WebView, and I do steps 1 and 2 the same, except 2 does this instead:
NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
self.requestToken = [[[OAToken alloc] initWithHTTPResponseBody:dataString] autorelease];
OAMutableURLRequest* requestURL = [[[OAMutableURLRequest alloc] initWithURL:[NSURL URLWithString:kOAuthTwitterAuthorizeURL] consumer:nil token:self.requestToken realm:nil signatureProvider:nil] autorelease];
[requestURL setParameters:[NSArray arrayWithObject:[[[OARequestParameter alloc] initWithName:#"oauth_token" value: self.requestToken.key] autorelease]]];
[[webview mainFrame] loadRequest: requestURL];
[NSApp beginSheet: webSheet modalForWindow: [NSApp mainWindow] modalDelegate:self didEndSelector: #selector(webSheetDidEnd:returnCode:contextInfo:) contextInfo:nil];
I use the WebView PolicyDelegate to look for the redirect (to my callback URL) after the user has authorized using the Twitter webpage:
- (void)webView: (WebView *)webView decidePolicyForNavigationAction: (NSDictionary *)actionInformation request: (NSURLRequest *)request frame: (WebFrame *)frame
decisionListener: (id<WebPolicyDecisionListener>)listener
{
NSString *urlString = [[actionInformation objectForKey:#"WebActionOriginalURLKey"] absoluteString];
if ([urlString rangeOfString:#"oauth_verifier"].location != NSNotFound)
{
// parse out oauth_token and oauth_verifier from the URL
}
self.requestToken.secret = oauthVerifier;
[listener ignore];
[NSApp endSheet:webSheet returnCode: 0];
OAMutableURLRequest *request = [[[OAMutableURLRequest alloc] initWithURL:[NSURL URLWithString:kOAuthTwitterAccessTokenURL] consumer: self.consumer token: self.requestToken realm: nil signatureProvider: nil] autorelease];
[request setHTTPMethod:#"POST"];
OADataFetcher *fetcher = [[[OADataFetcher alloc] init] autorelease];
[fetcher fetchDataWithRequest:request delegate:self didFinishSelector:#selector(setAccessToken:withData:) didFailSelector:#selector(failAccessToken:data:)];
}
As far as I can tell, this should authenticate exactly the same. The only difference, as far as Twitter is concerned, is that I'm using the oauth_verifier from the callback URL instead of the one presented to the user (and provided back to my application). But if this was a true server-to-server implementation, that's the value I'd be using anyway.
What actually happens is that this last step (getting the access token) fails with:
failAccessToken: 'Error Domain=NSURLErrorDomain Code=-1012 "The operation couldn’t be completed. (NSURLErrorDomain error -1012.)" UserInfo=0x101b3e780 {NSErrorFailingURLStringKey=http://api.twitter.com/oauth/access_token, NSUnderlyingError=0x101bacf40 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error -1012.)", NSErrorFailingURLKey=http://api.twitter.com/oauth/access_token}'
Any ideas on what's causing this authentication to fail?
joe
I finally gave up on the OAuthConsumer framework and switched to the Google GTMOAuth framework. That works fine.
Related
Currently I'm working on translate application , I referred from read text file returned by URL to get the translated text file
https://translate.google.com.tw/translate_a/t?client=t&hl=en&sl=" +
sl + "&tl=" + tl + "&ie=UTF-8&oe=UTF-8&multires=1&oc=1&otf=2&ssel=0&tsel=0&sc=1&q="
.This is works fine in android while translate, but in iOS it returns text as
The below code I used to get the file
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://translate.google.com.tw/translate_a/t?client=t&hl=en&sl=en&tl=ta&ie=UTF-8&oe=UTF-8&multires=1&oc=1&otf=2&ssel=0&tsel=0&sc=1&q=summer"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
connectionRequest=[[NSURLConnection alloc]initWithRequest:request delegate:self];
NSString* newStr = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"newStr%#",newStr);
What I'm doing?please anybody help me to get out of this..Thanks
I recommend using web service rest of google. Can read the official guide.
enter link description here
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSMutableURLRequest* request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:#"http://translate.google.com.tw/translate_a/t?client=t&hl=en&sl=en&tl=ta&ie=UTF-8&oe=UTF-8&multires=1&oc=1&otf=2&ssel=0&tsel=0&sc=1&q=summer"]];
[request setHTTPMethod:#"GET"];
[self addHeaders:request];
[NSURLConnection connectionWithRequest:request delegate:self];
[pool release];
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response {
NSString* newStr = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
}
hope i'm not unique iOS 7 victim :)
I have an application that synchronize its database with my web service, in my synchronization flow there is 14 call to web services, using Windows Authentication. All this call are inside a separate thread. I created a custom class that return NSData by URL. Till iOS7 all worked fine, but with new iOS version user credential saved in sharedCredentialStorage (NSURLCredentialStorage) no longer work. Here is my code:
- (BOOL)isValidURL:(NSString *) stringUrl forUsername:(NSString*) username andPassword:
(NSString*) password andDomain:(NSString*) _domain
{
username = [_domain stringByAppendingFormat:#"\\%#",username];
NSURLCredential *credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistenceForSession ];
//------------search host, port for credential storege......
NSArray *dati = [self getHostAndPortFromUrl:stringUrl];
if(dati==nil)
return FALSE;
//this info are correct
NSString *host = [dati objectAtIndex:0];
NSNumber *port = [dati objectAtIndex:1];
//-----------------------------------------------------------
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc] initWithHost:host port:port.intValue protocol:#"http" realm:host authenticationMethod:NSURLAuthenticationMethodNTLM];
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:protectionSpace];
//creadentials are saved
NSLog(#"%#",[[NSURLCredentialStorage sharedCredentialStorage] allCredentials]);
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#",stringUrl]];
NSURLRequest *req = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:25.0];
NSHTTPURLResponse *res = nil;
NSError *err = nil;
[NSURLConnection sendSynchronousRequest:req returningResponse:&res error:&err ];
//here i receive error: Error Domain=NSURLErrorDomain Code=-1012 "The operation couldn’t be completed. (NSURLErrorDomain error -1012.)"
//show alert view if error
[self showMsgBasedOnError:err andResponce:res];
//NSLog(#"url valid = %#\n", ((err==nil && [res statusCode]!=404) ? #"YES" : #"NO"));
return (err==nil && [res statusCode]!=404);
}
How I can implement an synchronous request using NTLM credentials in iOS7 :( ?
Thank you in advance,
Max
I have a piece of code in the .m file as below:
- (IBAction)btnLogin:(UIButton *)sender
{
NSString *strURL = [NSString stringWithFormat:#"http://www.myworkingdomain.com/fn_checkLogin2.php?name=%#&pass=%#", self.email.text, self.password.text];
// to execute php code
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]];
// to receive the returend value
NSString *strResult = [[[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding]autorelease];
if ([strResult isEqualToString:#"0"]) {
UIStoryboard *loginFailStoryBoard = [UIStoryboard storyboardWithName:#"loginFailStoryboard" bundle:nil];
UIViewController *initialFailLogin = [loginFailStoryBoard instantiateInitialViewController];
initialFailLogin.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:initialFailLogin animated:YES];
//NSLog(#"%#", strResult);
} else {
UIStoryboard *memberMenuBoard = [UIStoryboard storyboardWithName:#"memberMenuStoryboard" bundle:nil];
UIViewController *initialMemberMenu = [memberMenuBoard instantiateInitialViewController];
initialMemberMenu.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:initialMemberMenu animated:YES];
//NSLog(#"%#", strResult);
}
NSLog(#"%#", strResult);
}
#end
I am trying to determine if a person entered the right email and password and then to move on to the next view. I have the 'strResult' in my log and it shows that the php script it working correctly. It is now seems that the if..else statement that is not working due to the part [strResult isEqualToString:#"0"]
Can someone please advice where should I change to correct this so that when a member logins with the right password, he can go to the member view?
Thanks
#dan
The main thread is where all your UI elements are displayed. If you launch a connection on the main thread, your UI will become unresponsive until the connection is resolved (Unable to press buttons, unable to scroll etc...) In order to avoid that you should use another thread. There are other ways of doing it but the following code should do the trick without blocking your UI.
NSString *loginString =[NSString stringWithFormat:#"fn_checkLogin2.php?name=%#&pass=%#", self.email.text, self.password.text];
NSURL *url = [NSURL URLWithString:#"http://www.myworkingdomain.com/"];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url ];
[urlRequest setTimeoutInterval:30.0f];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setHTTPBody:[loginString dataUsingEncoding:NSUTF8StringEncoding]];
NSOperationQueue *queue= [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
if ([data length]>0 && error==nil) {
NSString *html = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"HTML = %#",html);
}
}
];
So if data is returned you can do stuff, if connection fails you can do other stuff without blocking your UI.
I have made this so far. It's code that will make a json String request with an http Header. When i run this code i get no errors. But i get a Expression result unused warning. I should get a response from the web service after sending this http header.
code:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *nid = #"";
NSString *vocab = #"";
NSString *inturl = #"testoverview";
NSString *mail = #"chh#fbr.dk";
NSString *md5pw = #"4d57e7ef1b7c3f431aca424764e9d786";
NSDictionary *jsonDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
nid, #"nid",
vocab, #"vocab",
inturl, #"inturl",
mail, #"mail",
md5pw, #"md5pw",nil];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
if (!jsonData) {
NSLog(#"Got an error; %#", error);
} else if(jsonData) {
NSString *url = #"http://www.taenk.dk/services/mobile";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLCacheStorageAllowed timeoutInterval:30.0];
[request setValue:jsonString forHTTPHeaderField:#"X-FBR-App"];
[[NSURLConnection alloc] initWithRequest:request delegate:self]; <-- this line triggers the warning: "Expression result unused"
NSLog(#"jsonString %#", jsonString);
}
Can anybody clarify 2 things for me:
Does this trigger a response as soon as the request to the web service?
If yes, how do i print this result out?
You need to assign the result to a variable like
NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:...
for later use (e.g. [con cancel];)
Then you should at least implement the delegate method connection:didFailWithError:. In the class reference I don't see the connection:didFinishLoading... anymore. Can you use the sendSynchronousRequest:returningResponse:error: instead, then you'll have the result, be it positive or negative.
This is how I retrieved the data (this version is without ARC):
- (void) connection :(NSURLConnection *)conn didReceiveData :(NSData *)data {
NSString *msg = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
[self checkAutoMailReply:msg];
[msg release];
}
msg contains the pure response data, no header or such.
I am trying to access the XML http://webservices.ns.nl/ns-api-stations using ASIHTTPRequest. But what I am using now doesn't seem to work. It says the host is not reachable. So I assume it is going wrong at the ASIHTTPRequest part?
-(void)fetchStationData {
//Method for the fetching of the data
//First lets check wheater there is an internet connection and if the host is reachable
if(internetActive) {
//Internet is active
//Init the parser
parser = [[RSSParser alloc] init];
//Set he parser context
parser.context = context;
//The array to het the data from
NSURL *url = [NSURL URLWithString:#"http://webservices.ns.nl/ns-api-stations"];
ASIHTTPRequest *requestaccount = [ASIHTTPRequest requestWithURL:url];
[requestaccount setUsername:#"user"];
[requestaccount setPassword:#"password"];
//The XML elements to fetch
NSArray *elements = [[NSArray alloc] initWithObjects:#"name",nil];
//The actual fetchin
[parser fetchStationItemsForUrl:url forElements:elements];
//Save the context ?
[context save:nil];
//Clean up
[elements release];
}else{
//Internet is down :(
//Offline artikelen inladen
//Dit uitvoeren op de main que
dispatch_async(dispatch_get_main_queue(), ^ {
UIAlertView *Notpermitted = [[UIAlertView alloc] initWithTitle:#"Alert" message:#"Er is geen verbinding mogelijk met de Mezz. Offline artikelen zijn ingeladen." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[Notpermitted show];
[Notpermitted release];
});
}
}
Use ASIFormDataRequest.
NSURL *url = [NSURL URLWithString:#"http://webservices.ns.nl/ns-api-stations"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request addPostValue:#"accountname" forKey:#"username"];
[request addPostValue:#"password" forKey:#"password"];
[request setCompletionBlock:^ {
// do something when request succeeds and credentials are ok, e.g. redirect user to the home page
}];
[request setFailedBlock:^ {
// notify user that request failed
}];
[request startAsynchronous];