NSURLCredentialStorage not work in iOS 7 - ios7

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

Related

eBay API objective-c

I am working on a Mac app in objective-c which will use the eBay API to access the eBay functionality, including trading. I have successfully retrieved items and categories, but for trading, I need the session ID and token, which I have not been able to do.
I have made many changes after reading various posts and the documentation, but always get this error after responding to the challenge:
error: Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={NSUnderlyingError=0x6080000585a0 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={_kCFStreamErrorCodeKey=-4, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=https://api.sandbox.ebay.com/ws/api.dll, NSErrorFailingURLKey=https://api.sandbox.ebay.com/ws/api.dll, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-4, NSLocalizedDescription=The network connection was lost.}
After making the call, I get the challenge callback and handle it here:
- (void)URLSession:(NSURLSession *)session
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition,
NSURLCredential *credential))completionHandler{
NSLog(#"didReceiveChallenge: %#", challenge);
NSURLCredential* credential = [NSURLCredential credentialWithUser:sandBoxUserID password:sandBoxPassword persistence:NSURLCredentialPersistenceForSession];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
}
The call for the session ID is here:
-(void) retrieveSessionID{
// retrieve a session ID for this user for this app
// headers for auth
NSURLSessionConfiguration* configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
NSMutableString* urlString = [[NSMutableString alloc]initWithCapacity:200];
[urlString appendString:sandBoxEndPoint];
NSString* callname = #"GetSessionID";
NSString* version = #"768";
NSString* contentType = #"text/xml";
NSString* siteID = #"0";
NSMutableDictionary* headersDictionary = [[NSMutableDictionary alloc]initWithCapacity:10];
[headersDictionary setObject:contentType forKey:#"Content-Type"];
[headersDictionary setObject:sandBoxAppID forKey:#"X-EBAY-API-APP-NAME"];
[headersDictionary setObject:devID forKey:#"X-EBAY-API-DEV-NAME"];
[headersDictionary setObject:sandBoxCertID forKey:#"X-EBAY-API-CERT-NAME"];
[headersDictionary setObject:callname forKey:#"X-EBAY-API-CALL-NAME"];
[headersDictionary setObject:version forKey:#"X-EBAY-API-COMPATIBILITY-LEVEL"];
[headersDictionary setObject:siteID forKey:#"X-EBAY-API-SITEID"];
configuration.HTTPAdditionalHeaders = headersDictionary;
NSLog(#"configuration.HTTPAdditionalHeaders: %#", configuration.HTTPAdditionalHeaders);
NSLog(#"urlString: %#", urlString);
NSURL *eBayUrl = [NSURL URLWithString:urlString];
NSLog(#"eBayUrl: %#", eBayUrl);
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:eBayUrl];
request.HTTPMethod = #"GET";
NSXMLElement *root = [[NSXMLElement alloc] initWithName:#"GetSessionIDRequest"];
[root addAttribute:[NSXMLNode attributeWithName:#"xmnls" stringValue:#"urn:ebay:apis:eBLBaseComponents"]];
NSXMLElement *childElement1 = [[NSXMLElement alloc] initWithName:#"RuName"];
childElement1.stringValue = sandBoxRuName;
[root addChild:childElement1];
NSXMLDocument *xmlRequest = [NSXMLDocument documentWithRootElement:root];
NSData* xmlRequestAsData = [xmlRequest XMLData];
request.HTTPBody = xmlRequestAsData;
NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
NSLog(#"error: %#", error);
NSLog(#"response: %#", response);
self.sessionIDRequestXMLstring = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"self.sessionIDRequestXMLstring: %#", self.sessionIDRequestXMLstring);
[self.delegate receivedSessionIDRequestXMLstring:self.sessionIDRequestXMLstring];
}
];
[dataTask resume];
}
I apologize for the formatting here, but I haven't quite figured out how to use it correctly.

NSURLRequest for JSON w/ credentials

NSString *login = #"Web Guest";
NSString *password = #"xxxxx";
NSError *myError = nil;
NSLog(#"CONNECTION: Adding credentials");
NSURLCredential *credential = [NSURLCredential credentialWithUser:login
password:password
persistence:NSURLCredentialPersistenceForSession];
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
initWithHost:#"54.225.xxx.xxx"
port:80
protocol:#"http"
realm:#"54.225.xxx.xxx"
authenticationMethod:NSURLAuthenticationMethodDefault];
//Not sure if set up correctly
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:protectionSpace];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"xx.xxx.xxx.xxx/blah"]
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:12];
NSLog(#"CONNECTION: Running request");
//Perform the request
NSURLResponse *response;
NSData *data = [NSURLConnection
sendSynchronousRequest:request
returningResponse:&response
error:&myError];
At this point, I get an error "Terminating app due to uncaught
exception 'NSInvalidArgumentException', reason: ' +[NSString
stringWithCString:encoding:]: NULL cString'"
NSString *result = [NSString stringWithCString:[data bytes] encoding:NSUTF8StringEncoding];
NSLog(#"Webserver response: %#", result);
I'm attempting to return some JSON from the web server which requires authorization using basic authentication, but seem to be having some trouble with getting it set up. I'm new to objective-c programming and ios development, but would really appreciate any help! Thanks.
You're not using a scheme in your request URL string: #"xx.xxx.xxx.xxx/blah". You'll need something like #"https://xx.xxx.xxx.xxx/blah", otherwise [NSURL URLWithString:] returns nil.

Get web service response data

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.

How to access secured url from ios

I'm trying to access a secure url from ios. Basically url will prompt the user with Username and Password. How can I send username and Password from ios?
My Code
Here is the Methods that I'm using to access JSON Parser
- (NSString *)stringWithUrl:(NSURL *)url{
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReturnCacheDataElseLoad
timeoutInterval:30];
// Fetch the JSON response
NSData *urlData;
NSURLResponse *response;
NSError *error;
// Make synchronous request
urlData = [NSURLConnection sendSynchronousRequest:urlRequest
returningResponse:&response
error:&error];
// Construct a String around the Data from the response
return [[[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding] autorelease];}
- (id) objectWithUrl:(NSURL *)url{
SBJsonParser *jsonParser = [[[SBJsonParser alloc]init] autorelease];
NSString *jsonString = [self stringWithUrl:url];
// Parse the JSON into an Object
return [jsonParser objectWithString:jsonString error:nil]; }
Here is the piece of code that I'm retrieving json keys to my dictionary.
- (NSDictionary *) downloadFeed {
id response = [self objectWithUrl:[NSURL URLWithString:#"http://mysite.com/Services/Secure.svc/GetList?id=2127"]];
NSDictionary *feed = (NSDictionary *)response;
return feed; }
Can someone let me know where can I pass the Username and Password to this url?
Either switch to ASIHTTPRequest, which handles Basic authentication simply, or use a NSMutableRequest and set the Authorization header correctly, with a base64 encoded user:password pair.

Yet another Cocoa OAuth (for Twitter) issue [duplicate]

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.