How to create a NTLM authentication header to use with Alamofire?

6.6k views Asked by At

These are request headers:

let userName = "someUserName"
let password = "aPasswordForSomeUserName"

var headers: HTTPHeaders = [
    "Accept": "application/json",
]

if let authorizationHeader = Request.authorizationHeader(user: userName, password: password) {
    headers[authorizationHeader.key] = authorizationHeader.value
}

So this is generating Authorization like this.

Basic aC5paHFoOkulbXKhNpk43A== (I have modified it for security).

But when I make the same request in Advance Rest Client (a chrome extension). I am seeing this:

Accept: application/json
Authorization: NTLM TlMMTVNTUAADAAAAGAAYAG4AAAAYABgAhgAAAAYABgBAAAAADAAMAEYAAAAcABwAUgPPPAAAAACeAAAAAYIAAEUARwBBAGgALgBzAGgAYQBoAUIOVABHAC4AUSDFGC4ARQBHAEEALgBMAEEAToD38IenExnddmNhyXz+u0cmIHEl/p8P9OWe2rePPsiRkZO1Ne6ZrWxnIxHK1CZcyTU=

Notice, NTLM and Basic in both the generated authorization key for my username and password.

How to do this in iOS (and possibly with Alamofire)?

This also leads to this question I asked previously.

How to make a NTML request with Alamofire 4.0?

1

There are 1 answers

0
Saeed On

I enhanced the correct answer in this link, and make work of any request sent using Alamofire instead of adding the login for each ViewController:

private var manager : SessionManager?
var username: String? = nil
var password: String? = nil

func doesHaveCredentials() -> Bool {
    self.username = Defaults[.username]
    self.password = Defaults[.password]

    guard let _ = self.username else { return false }
    guard let _ = self.password else { return false }
    return true
}

func apiManager() -> SessionManager{
    if let m = self.manager{
        return m
    }else{
        let configuration = URLSessionConfiguration.default
        configuration.timeoutIntervalForRequest = 25
        configuration.timeoutIntervalForResource = 25
        self.manager = Alamofire.SessionManager(configuration: configuration)

        let delegate: Alamofire.SessionDelegate = self.manager!.delegate
        delegate.taskDidReceiveChallengeWithCompletion = { session, task, challenge,  completionHandler in
            print("Got challenge")
            guard challenge.previousFailureCount == 0 else {
                print("too many failures")
                challenge.sender?.cancel(challenge)
                completionHandler(.cancelAuthenticationChallenge, nil)
                return
            }

            guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM else {
                print("unknown authentication method \(challenge.protectionSpace.authenticationMethod)")
                challenge.sender?.cancel(challenge)
                completionHandler(.cancelAuthenticationChallenge, nil)
                return
            }

            guard self.doesHaveCredentials() else {
                challenge.sender?.cancel(challenge)
                completionHandler(.cancelAuthenticationChallenge, nil)
                DispatchQueue.main.async {
                    print("Userdata not set")
                };
                return
            }

            let credentials = URLCredential(user: self.username!, password: self.password!, persistence: .forSession)
            challenge.sender?.use(credentials, for: challenge)
            completionHandler(.useCredential, credentials)
        }

        return self.manager!
    }
}