NSURLConnection
Basic Authentication
iOS Development
HTTP
iOS Networking

NSURLConnection and Basic HTTP Authentication in iOS

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

NSURLConnection was the old Foundation API for HTTP networking on iOS, and it could handle HTTP Basic Authentication through delegate challenge methods. Today it is legacy technology, and new code should use URLSession. Still, if you are maintaining older Objective-C code, the important part is understanding the authentication challenge flow and how to provide a NSURLCredential safely.

What Basic Authentication Is

HTTP Basic Authentication sends a username and password with the request, usually after the server challenges the client with a 401 Unauthorized response. The credentials are only base64-encoded, not encrypted, so Basic Auth should be used over HTTPS, not plain HTTP.

That rule matters more than the API details. If the connection is not protected by TLS, Basic Auth is not an acceptable design.

Legacy NSURLConnection Flow

With NSURLConnection, authentication is typically handled through delegate callbacks. The connection receives a challenge, and your delegate either responds with credentials or cancels the challenge.

A typical Objective-C example looks like this:

objective-c
1#import <Foundation/Foundation.h>
2
3@interface AuthClient : NSObject <NSURLConnectionDataDelegate>
4@property (nonatomic, strong) NSMutableData *receivedData;
5@end
6
7@implementation AuthClient
8
9- (void)start {
10    NSURL *url = [NSURL URLWithString:@"https://example.com/protected"];
11    NSURLRequest *request = [NSURLRequest requestWithURL:url];
12    self.receivedData = [NSMutableData data];
13
14    [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
15}
16
17- (void)connection:(NSURLConnection *)connection
18didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
19    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic]) {
20        NSURLCredential *credential = [NSURLCredential credentialWithUser:@"alice"
21                                                                 password:@"secret"
22                                                              persistence:NSURLCredentialPersistenceForSession];
23        [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
24    } else {
25        [[challenge sender] cancelAuthenticationChallenge:challenge];
26    }
27}
28
29- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
30    [self.receivedData appendData:data];
31}
32
33- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
34    NSString *body = [[NSString alloc] initWithData:self.receivedData encoding:NSUTF8StringEncoding];
35    NSLog(@"%@", body);
36}
37
38@end

This is the legacy pattern many older projects still use.

Why This Is Legacy Code Now

Apple has long recommended URLSession for modern networking. NSURLConnection remains relevant mostly for maintenance work, debugging old code, or understanding older tutorials.

The core networking concept did not change:

  • make a request
  • receive an authentication challenge
  • respond with credentials
  • continue or cancel

Only the API surface changed.

Modern Equivalent With URLSession

If you are writing new code, use URLSession and its challenge delegate methods.

swift
1import Foundation
2
3final class AuthDelegate: NSObject, URLSessionDelegate {
4    func urlSession(
5        _ session: URLSession,
6        didReceive challenge: URLAuthenticationChallenge,
7        completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
8    ) {
9        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic {
10            let credential = URLCredential(user: "alice", password: "secret", persistence: .forSession)
11            completionHandler(.useCredential, credential)
12        } else {
13            completionHandler(.cancelAuthenticationChallenge, nil)
14        }
15    }
16}
17
18let delegate = AuthDelegate()
19let session = URLSession(configuration: .default, delegate: delegate, delegateQueue: nil)
20let url = URL(string: "https://example.com/protected")!
21
22session.dataTask(with: url) { data, response, error in
23    if let error = error {
24        print(error)
25        return
26    }
27    print(String(data: data ?? Data(), encoding: .utf8) ?? "")
28}.resume()

That is the API direction you should prefer unless the codebase is stuck on legacy patterns.

Alternative: Put The Header On The Request

For some controlled internal systems, you may see code that prebuilds the Authorization header.

swift
1import Foundation
2
3let username = "alice"
4let password = "secret"
5let raw = "\(username):\(password)"
6let encoded = Data(raw.utf8).base64EncodedString()
7
8var request = URLRequest(url: URL(string: "https://example.com/protected")!)
9request.setValue("Basic \(encoded)", forHTTPHeaderField: "Authorization")

This works, but it is less flexible than challenge handling and still requires HTTPS. It also pushes credential construction closer to application logic, which may not be what you want.

Common Pitfalls

  • Using Basic Auth over plain HTTP instead of HTTPS.
  • Continuing to add new NSURLConnection code instead of using URLSession.
  • Responding to every challenge the same way without checking the authentication method.
  • Hardcoding credentials in source code for production systems.
  • Confusing base64 encoding with encryption.

Summary

  • 'NSURLConnection can handle Basic Auth through authentication challenge delegates.'
  • The legacy solution is to provide a NSURLCredential when the server issues an HTTP Basic challenge.
  • Modern iOS networking should use URLSession instead.
  • Basic Authentication should be sent only over HTTPS.
  • When maintaining legacy code, focus on the challenge flow and migrate to URLSession when possible.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.