Reputation: 1365
I have the following problem: I am making requests to a server, which uses HTTP basic auth and gives me
When receiving the 401s, my NSURLSession is friendly enough to call out to its delegate via
URLSession(
session: NSURLSession,
task: NSURLSessionTask, didReceiveChallenge
challenge: NSURLAuthenticationChallenge,
completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void)
where I can then modify the credentials being sent to the server.
When receiving a 403, however, I run into a problem. From there I cannot get the session to use any other credentials than what it used to get the 403. On a 403, the delegate is not asked (which is ok, it is not a 401), so how do I control which credentials are sent in the future for that protection space? Even manually emptying the shared NSURLCredentialStorage and/or setting the correct credentials there directly does not help:
let credential = NSURLCredential(user: username, password: password, persistence: .ForSession)
let protectionSpace = NSURLProtectionSpace(
host: self.host,
port: self.apiRootURL.port!.integerValue,
protocol: self.apiRootURL.scheme!,
realm: "MyRealm",
authenticationMethod: NSURLAuthenticationMethodHTTPBasic)
NSURLCredentialStorage.sharedCredentialStorage().setDefaultCredential(credential, forProtectionSpace: protectionSpace)
After this call, the correct credentials are the only ones listed in the NSURLCredentialStorage - but the next call to the server will still include the old credentials, which will inevitably lead to another 403.
Even resetting the session using its reset(completionHandler: @escaping () -> Void)
method does not help.
TLDR; how do I change the credentials that NSURLSession continues to use once it has had success with them for a given protection domain?
Upvotes: 3
Views: 938
Reputation: 10417
You catch the 403 response message, then either
I recommend the second or third approach, depending on which results in fewer requests on average. To avoid persistence, pass NSURLCredentialPersistenceNone or the Swift equivalent instead of telling it to persist for the duration of the session. To remove a credential, call removeCredential:forProtectionSpace:options:
.
There are a couple of other possibilities that might work, depending on your app design and the server design:
Upvotes: 0