An NSURLRequest object often encounters an authentication challenge, or a request for credentials from the server it is connecting to. The delegates for NSURLConnection
and NSURLDownload
can be notified when their request encounters an authentication challenge, so that they can act accordingly.
If an NSURLRequest object requires authentication, the delegate of the NSURLConnection (or NSURLDownload) object associated with the request first receives a connection:canAuthenticateAgainstProtectionSpace:
(or download:canAuthenticateAgainstProtectionSpace:
) message. This allows the delegate to analyze properties of the server, including its protocol and authentication method, before attempting to authenticate against it. If your delegate is not prepared to authenticate against the server’s protection space, you can return NO
, and the system attempts to authenticate with information from the user’s keychain.
Note: If your delegate does not implement the connection:canAuthenticateAgainstProtectionSpace:
method and the protection space uses client certificate authentication or server trust authentication, the system behaves as if you returned NO
. The system behaves as if you returned YES
for all other authentication methods.
If your delegate returns YES
from connection:canAuthenticateAgainstProtectionSpace:
or doesn’t implement it, and there are no valid credentials available, either as part of the requested URL or in the shared NSURLCredentialStorage
, the delegate receives a connection:didReceiveAuthenticationChallenge:
message. In order for the connection to continue, the delegate has three options:
Provide authentication credentials
Attempt to continue without credentials
Cancel the authentication challenge
To help determine the correct course of action, the NSURLAuthenticationChallenge
instance passed to the method contains information about what triggered the authentication challenge, how many attempts were made for the challenge, any previously attempted credentials, the NSURLProtectionSpace
that requires the credentials, and the sender of the challenge.
If the authentication challenge has tried to authenticate previously and failed, you can obtain the attempted credentials by calling proposedCredential
on the authentication challenge. The delegate can then use these credentials to populate a dialog that it presents to the user.
Calling previousFailureCount
on the authentication challenge returns the total number of previous authentication attempts, including those from different authentication protocols. The delegate can provide this information to the end user, to determine whether the credentials it supplied previously are failing, or to limit the maximum number of authentication attempts.
The following are the three ways you can respond to the connection:didReceiveAuthenticationChallenge:
delegate method.
To attempt to authenticate, the application should create an NSURLCredential
object with authentication information of the form expected by the server. You can determine the server’s authentication method by calling authenticationMethod
on the protection space of the provided authentication challenge. Some authentication methods supported by NSURLCredential are:
NSURLAuthenticationMethodHTTPBasic
)The basic authentication method requires a user name and password. Prompt the user for the necessary information and create an NSURLCredential object with credentialWithUser:password:persistence:
.
NSURLAuthenticationMethodHTTPDigest
)Like basic authentication, digest authentication just requires a user name and password (the digest is generated automatically). Prompt the user for the necessary information and create an NSURLCredential object with credentialWithUser:password:persistence:
.
NSURLAuthenticationMethodClientCertificate
)Client certificate authentication requires the system identity and all certificates needed to authenticate with the server. Create an NSURLCredential object with credentialWithIdentity:certificates:persistence:
.
NSURLAuthenticationMethodServerTrust
)Server trust authentication requires a trust provided by the protection space of the authentication challenge. Create an NSURLCredential object with credentialForTrust:
.
After you’ve created the NSURLCredential object, pass it to the authentication challenge’s sender with useCredential:forAuthenticationChallenge:
.
If the delegate chooses not to provide a credential for the authentication challenge, it can attempt to continue without one by calling continueWithoutCredentialsForAuthenticationChallenge:
on [challenge sender]
. Depending on the protocol implementation, continuing without credentials may either cause the connection to fail, resulting in a connectionDidFailWithError:
message, or return alternate URL contents that don’t require authentication.
The delegate may also choose to cancel the authentication challenge by calling cancelAuthenticationChallenge:
on [challenge sender]
. The delegate receives a connection:didCancelAuthenticationChallenge:
message, providing the opportunity to give the user feedback.
The implementation shown in Listing 1 attempts to authenticate the challenge by creating an NSURLCredential
instance with a user name and password supplied by the application’s preferences. If the authentication has failed previously, it cancels the authentication challenge and informs the user.
Listing 1 An example of using the connection:didReceiveAuthenticationChallenge:
delegate method
-(void)connection:(NSURLConnection *)connection |
didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge |
{ |
if ([challenge previousFailureCount] == 0) { |
NSURLCredential *newCredential; |
newCredential = [NSURLCredential credentialWithUser:[self preferencesName] |
password:[self preferencesPassword] |
persistence:NSURLCredentialPersistenceNone]; |
[[challenge sender] useCredential:newCredential |
forAuthenticationChallenge:challenge]; |
} else { |
[[challenge sender] cancelAuthenticationChallenge:challenge]; |
// inform the user that the user name and password |
// in the preferences are incorrect |
[self showPreferencesCredentialsAreIncorrectPanel:self]; |
} |
} |
If the delegate doesn’t implement connection:didReceiveAuthenticationChallenge:
and the request requires authentication, valid credentials must already be available in the URL credential storage or must be provided as part of the requested URL. If the credentials are not available or if they fail to authenticate, a continueWithoutCredentialForAuthenticationChallenge:
message is sent by the underlying implementation.
Last updated: 2010-03-24