Search code examples
iosswiftauthenticationalamofirensurlcredential

Basic Authentication with Alamofire


Experiencing an issue when authenticating with Basic Auth. I am using a standard enum that conforms to URLRequestConvertible protocol to construct my requests. The issue is that when I manually set the authorization headers in the enum like so:

    let user = ***
    let password = ***

    let credentialData = "\(user):\(password)".dataUsingEncoding(NSUTF8StringEncoding)!
    let base64Credentials = credentialData.base64EncodedStringWithOptions([])

    mutableURLRequest.setValue("Basic \(base64Credentials)", forHTTPHeaderField: "Authorization")

I always get a 401 unauthorized response. However if I set the password using the authenticate callback like so:

    Alamofire.request(request)
        .authenticate(user: "USERNAME_HERE", password: "PASSWORD_HERE")
        .responseJSON { (response) -> Void in
            print("JSON response \(response)")
            completion(success: true, error: nil)
    }

It authenticates properly. I would like to be able to set it manually in the enum conforming to URLRequestConvertible instead of passing in the credentials in authenticate.

I know it's using a NSURLCredential under the hood for auth challenges but I would like to be able to set it manually.

Here is my URLRequestConvertible implementation :

enum CheckedUpAPI: URLRequestConvertible {
    static let baseURLString = "https://***"
    static let APIKey = "***"
    static let APIClientName  = "iPad"


    case UpdatePatient(String, [String: AnyObject])


    var method: Alamofire.Method {
        switch self {
        case .UpdatePatient:
            return .PATCH
        }
    }

    var path: String {
        switch self {
        case .UpdatePatient(let patientID, _):
            return "patients/\(patientID)"
        }
    }

    // MARK: URLRequestConvertible

    var URLRequest: NSMutableURLRequest {
        let URL = NSURL(string: CheckedUpAPI.baseURLString)!
        let mutableURLRequest = NSMutableURLRequest(URL: URL.URLByAppendingPathComponent(path))
        mutableURLRequest.HTTPMethod = method.rawValue


/**
        We are not setting any authorization headers since they requests return 401
        the `authenticate` function on Alamofire.request does the trick

        let user = "[email protected]"
        let password = "test"

        let credentialData = "\(user):\(password)".dataUsingEncoding(NSUTF8StringEncoding)!
        let base64Credentials = credentialData.base64EncodedStringWithOptions([])

        mutableURLRequest.setValue("Basic \(base64Credentials)", forHTTPHeaderField: "Authorization")
*/
        mutableURLRequest.setValue(CheckedUpAPI.APIKey, forHTTPHeaderField: "API-Key")

        switch self {
        case .UpdatePatient(_, let parameters):
            return Alamofire.ParameterEncoding.JSON.encode(mutableURLRequest, parameters: parameters).0
        }
    }
}

Solution

  • Ultimately figured out what the issue was. It ended up being a missing trailing forward slash in the URL. It seems Alamofire does not handle it the same way AFNetworking does. I was able to figure it out logging the requests and seeing that we were losing some bytes in the actual request.