ios didReceiveAuthenticationChallenge status - ios

I'm trying to authenticate users through webserver and calling the following method in my login view button touch to do so.
- (void)connection:(NSURLConnection *)connection
didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
NSLog(#"challenge failure %d", [challenge previousFailureCount]);
// Access has failed two times...
if ([challenge previousFailureCount] == 0)
{
//NSLog(#"desc %#",[connection description]);
NSURLCredential *cred = [[[NSURLCredential alloc] initWithUser:userName.text password:passWord.text
persistence:NSURLCredentialPersistenceForSession] autorelease];
[[challenge sender] useCredential:cred forAuthenticationChallenge:challenge];
// need to call new view on correct authentication
[connection release];
}
else {// Answer the challenge
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Authentication error"
message:#"Invalid Credentials" delegate:self
cancelButtonTitle:#"Retry"
otherButtonTitles:nil];
[alert show];
[alert release];
}
}
Is there any status returned after successful authentication so that i may use that status and pass on to next view else display the error.

Jsut Call connectionDidFinishLoading: Method.

Ok, as said in my comment:
Actually the connectionDidFinishLoading: method tells you that you can proceed to the next step.

Related

Successive NSURLConnection Requests Fail Authentication

This seems to be an iOS8 only issue.
I have an app that uses the NSURLConnection delegate. Everything works exactly as it should, except in iOS8 when multiple connections are created and ran successively, an arbitrary number of connections fail to authenticate.
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if (challenge.previousFailureCount == 0)
{
KeychainItemWrapper *itemWrapper = [[KeychainItemWrapper alloc] initWithIdentifier:#"login" accessGroup:nil];
[[challenge sender] useCredential:[NSURLCredential credentialWithUser:[itemWrapper objectForKey:(__bridge id)(kSecAttrAccount)] password:[itemWrapper objectForKey:(__bridge id)(kSecValueData)] persistence:NSURLCredentialPersistenceNone] forAuthenticationChallenge:challenge];
_authenticationChallenged = YES;
}
else
{
[self cancel];
KeychainItemWrapper *itemWrapper = [[KeychainItemWrapper alloc] initWithIdentifier:#"login" accessGroup:nil];
if ([[itemWrapper objectForKey:(__bridge id)(kSecAttrAccount)] isEqualToString:#""]) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Please Log In" message:#"To use this app, please log in" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Log In", nil];
[alertView setTag:2];
[alertView setAlertViewStyle:UIAlertViewStyleLoginAndPasswordInput];
[alertView show];
} else {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Invalid Credentials" message:nil delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Log In", nil];
[alertView setTag:2];
[alertView setAlertViewStyle:UIAlertViewStyleLoginAndPasswordInput];
[alertView show];
}
}
}
In above code is where the issue lies. The else statement is getting called, even though the credentials are correct and work correctly on every other request. This only happens when I create multiple (separate) NSURLConnections at the same time and run them.
Any ideas?
Thanks!

retrying a request after it failed

I am using the default classes provided by app to do my networking tasks in my app.
At some point, some of my requests time out (regardless of the reason for the timeout)
I would like to retry some of these requests
I have subclassed the NSURLConnection class and added some parameters to it.
However, in the method "connection:didFailWithError:"
con.retries seems to always be 1, never incremented. Why ?
- (void)connection:(NSURLConnection*) connection didFailWithError:(NSError *)error
{
[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:NO];
NSLog(#"%#",[NSString stringWithFormat:#"Did recieve error: %#", [error description]]);
NSLog(#"%#",[NSString stringWithFormat:#"%#", [[error userInfo]description]]);
WBURLConnection *con = (WBURLConnection *)connection;
if([con shouldRetryRequest:error]){
con.retries ++;
[con start];
}else{
[con cancel];
[con.data setLength:0];
if(!self.alert){
self.alert = [[UIAlertView alloc]initWithTitle:#"Alert" message:[error localizedDescription] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[self.alert show];
}else {
if(![self.alert isVisible]){
[self.alert show];
}
}
}
}
-(BOOL)shouldRetryRequest:(NSError *)error{
[self.retryCount appendString:[NSString stringWithFormat:#"%#:%ld",error,(long)self.retries]];
LogInfo(#"retries:%#",self.retryCount);
if([error code] == -1004){
return NO;
}
return self.retries<3;
}

Is there a way to let the user chose whether or not trust the site when we try to use NSURLConnection to connect with SSL for an untrusted cert?

There is a similar question on stack overflow.
Here is my code which will accept the untrusted server certificate anyway.
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)space
{
//We can always attempt to authenticate...
return YES;
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodServerTrust) {
[[challenge sender] useCredential:[NSURLCredential credentialForTrust:[[challenge protectionSpace] serverTrust]] forAuthenticationChallenge:challenge];
} else {
// Other situation
}
}
However, I want to present an alter view to let the user chose whether or not trust the site.
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:
[[challenge protectionSpace]host] message:#"Do you trust this site?"
delegate:self cancelButtonTitle:#"No"
otherButtonTitles:#"Yes", #"Just once", nil];
[alert show];
How can I do that?
As an example you can save the challenge object to a property and then implement the alertView:clickedButtonAtIndex: delegate method like this (this is for the "trust just once"):
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(buttonIndex == alertView.cancelButtonIndex)
{
[[self.challenge sender] cancelAuthenticationChallenge:self.challenge];
}
else
{
[self.challenge.sender useCredential:[NSURLCredential credentialForTrust:self.challenge.protectionSpace.serverTrust] forAuthenticationChallenge:self.challenge];
self.challenge = nil;
}
}
If you want to trust always you will need to do some more complex things to save and compare the server certificate data. Or make it simple and unsafe by saving that the server url should always be trusted, which makes you vulnerable to man in the middle attacks.

NSURLConnection Authentication Challenge even if it is not supposed to

I can do authentication with NSURL and user can assign username and password. However, I got another problem. If I open this, http://html5test.com/ , it also pop up and ask username and password. I got authentication even if it is not supposed to get. I would like to know how to do.
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if(!_auth)
{
connection_for_auto = [[NSURLConnection alloc] initWithRequest:request delegate:self];
firsttimeonly=TRUE;
[connection_for_auto start];
NSLog(#"Request >> %# and !firsttimeonly",request);
return NO;
}
self.lbl_error.hidden = YES; //hide error message label
return YES;
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
checkTochangeUIalert=TRUE;
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Login"
message:nil
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK",#"Auto", nil];
alertView.transform=CGAffineTransformMakeScale(1.0, 0.75);
alertView.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
[alertView show];
}
I think I have found a way to do. I need to check what kind of authentication method I use.
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic] || [challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodNTLM])
{
.............
}

Login and Password Input with NSURLConnection

I am a newbie in the development of iOS applications.
I need to reach different url loaded from a remote XML file,
some of these url require a http basic authentication.
Authentication with NSURLCredential, it works correctly.
Now, I want to require the user to enter their credentials.
When the connection fails I visualize the interface
login UIAlertView with setAlertViewStyle:UIAlertViewStyleLoginAndPasswordInput.
At this point I verify the correspondence
username and password entered by the user with textFieldAtIndex: 0 and 1
but I can and use them for a new connection attempt with NSURLConnection.
Can someone help me?
This is my code:
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
if ([challenge previousFailureCount] == 0)
{
NSLog(#"received authentication challenge");
NSURLCredential *newCredential;
newCredential=[NSURLCredential credentialWithUser:#""
password:#""
persistence:NSURLCredentialPersistenceForSession];
NSLog(#"credential created");
[[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
NSLog(#"responded to authentication challenge");
}
else
{
NSLog(#"previous authentication failure");
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Login"
message:#"Enter your username & password"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Login", nil];
[message setAlertViewStyle:UIAlertViewStyleLoginAndPasswordInput];
[message show];
}
}
- (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView
{
NSString *inputText = [[alertView textFieldAtIndex:0] text];
if( [inputText length] >= 1 )
{
return YES;
}
else
{
return NO;
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:#"Login"])
{
UITextField *username = [alertView textFieldAtIndex:0];
UITextField *password = [alertView textFieldAtIndex:1];
NSLog(#"Username: %#\npassword: %#", username.text, password.text);
if ([username.text isEqualToString:#"myname"] && [password.text isEqualToString:#"1234"])
NSLog(#"Success");
}
[xmlDataBuffer setLength:0];
}

Resources