1

I am trying to access a web page to retrieve JSON data. When I access the page through the browser it shows me a small box said authentication required A username and password are being requested by The site says: " API""

I am trying to get these data to pass then to NSdictionary object. What I found is that my response for the HTTP request is "401 - Unauthorized: Access is denied due to invalid credentials.You do not have permission to view this directory or page using the credentials that you supplied"

FYI, I passed the username and password in the authorization header for the request.

but what I found in the browser that it will ask for WWW-Authenticate: Basic realm="API" before the getting or showing the data

I looked up for a solution, I red about NSURLCredential So I implemented the NSURLsession delegate to trigger its function (

- (void)URLSession:(NSURLSession *)session
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition,
                             NSURLCredential *credential))completionHandler

) but it was never called I don't know why

What should I do?

This is my code:

+(void)getUsername:(NSString*)username andPassword:(NSString*)password completionBlock:(void(^)(NSDictionary* response))completion
{

    NSString *authStr = [NSString stringWithFormat:@"%@:%@", username, password];
    NSData *authData = [authStr dataUsingEncoding:NSUTF8StringEncoding];

    NSString *base64String = [authData base64EncodedStringWithOptions:0];

    NSString *authValue = [NSString stringWithFormat:@"Basic %@", base64String];

    __block NSDictionary *currentUserdictionarytest = nil;
    NSDictionary *headers = @{ @"authorization": authValue,
                               @"accept": @"application/json",
                               @"accept": @"text/html",
                               @"cache-control": @"no-cache",
                               @"postman-token": @"0a47efb3-c559-c0f9-8276-87cbdbe76c9d" };

    NSString *url = @"http://demo.redmine.org/";
stringByAppendingString:@"users/current.json"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
                                                           cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                       timeoutInterval:10.0];
    [request setHTTPMethod:@"GET"];
    [request setAllHTTPHeaderFields:headers];

    NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];

    NSURLSession *session = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue:nil]; //[NSOperationQueue mainQueue]]; //[NSURLSession sharedSession];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
                                                completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                    if (error) {
                                                        NSLog(@"%@", error);

                                                    } else {
                                                        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
                                                        NSLog(@"%@", httpResponse);
                                                        NSError *JSONError = nil;
                                                        currentUserdictionarytest = [NSJSONSerialization JSONObjectWithData:data
                                                                                                                options:0
                                                                                                                  error:&JSONError];
                                                        NSLog(@"Printing current user data: %@", data);
                                                        NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                                                         NSLog(@"Printing current user data string: %@", str);


                                                        if (JSONError)
                                                        {
                                                            NSLog(@"Serialization error: %@", JSONError.localizedDescription);
                                                        }
                                                        else
                                                        {
                                                            NSLog(@"Response: %@", currentUserdictionarytest);
                                                        }
                                                    }

                                                }];
    [dataTask resume];
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
    NSLog(@"did receive challenge method called with task");
    NSString* username = @"username";
    NSString* password = @"password";
    if ([challenge previousFailureCount] == 0) {

        NSURLCredential *newCredential;
        newCredential = [NSURLCredential credentialWithUser:username
                                                   password:password
                                                persistence:NSURLCredentialPersistenceNone];
        [[challenge sender] useCredential:newCredential
               forAuthenticationChallenge:challenge];

    } else {
        [[challenge sender] cancelAuthenticationChallenge:challenge];
    }
}
miss h
  • 133
  • 1
  • 2
  • 15
  • You need to pass your actual username & password which is authorised to access this page, except there is no problem with your code. – Dipen Panchasara May 04 '16 at 05:52
  • I know that my code is working just fine when the admin user request this data, but when a normal user asked for the data it gave a "401" error. I have read about using NSURLProtectionSpace but I don't know where to pass this object or where to use it. – miss h May 04 '16 at 05:59
  • You can check this post [Can I use NSURLCredentialStorage for HTTP Basic Authentication?](http://stackoverflow.com/questions/501231/can-i-use-nsurlcredentialstorage-for-http-basic-authentication). it may be helpful. – Dipen Panchasara May 04 '16 at 06:11
  • I did the exact thing, I assign the values for initWithHost:@"example.com" port:80 protocol:@"http" realm:@"API" authenticationMethod:NSURLAuthenticationMethodHTTPBasic]; but it's still giving me same error! – miss h May 04 '16 at 16:21

1 Answers1

0

That's the wrong delegate method. The session delegate handles only connection-level authentication, e.g. verifying server TLS certificates or providing client certificates, not request-level authentication (e.g. passwords). You want URLSession:task:didReceiveChallenge:completionHandler:.

dgatwood
  • 10,129
  • 1
  • 28
  • 49