Search code examples
iosswiftjwtalamofireexpress-jwt

JWT Authentication with Alamofire download function


I'm trying to download a zip file and save it from server using JWT token authentication thanks to Alamofire. The download works well without token authentication, the file is saved with success. When I activate the server-side authentication (using Passport.js with NodeJS), I always received 401. I attach the token to the header with the sessionManager adapter function. Others request (post, get using sessionManager.request(..) ) works well with this authentication mechanism.

Question is : Can we modify the header of Alamofire download function ? If yes how ?

Any advices appreciated

func getZip(){

    let sessionManager = Alamofire.SessionManager.default
    let authHandler = JWTAccessTokenAdapter(accessToken: Auth.getAccessToken())

    sessionManager.retrier = authHandler
    sessionManager.adapter = authHandler


    let downloadUrl: String = Auth.getApiEndpoint() + "get_zip"
    let destinationPath: DownloadRequest.DownloadFileDestination = { _, _ in
        let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0];
        let fileURL = documentsURL.appendingPathComponent("myZip.zip")
        return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
    }


    sessionManager.download(downloadUrl, method: .get,  encoding: URLEncoding.httpBody, to: destinationPath)
        .downloadProgress { progress in
            print(">> Zip Download Progress: \(progress.fractionCompleted)")
        }
        .responseData { response in
            switch response.result{
            case .success:
                if response.destinationURL != nil, let filePath = response.destinationURL?.absoluteString {
                    print("success & filepath : \(filePath)")
                    completionHandler(filePath, true)
                }
                break
            case .failure:
                print("faillure")
                completionHandler("", false)
                break
            }

        }
    } 
}

JWT Adapter :

class JWTAccessTokenAdapter: RequestAdapter {

     typealias JWT = String
     private var accessToken: JWT

     func adapt(_ urlRequest: URLRequest) throws -> URLRequest {
        var urlRequest = urlRequest

        if let urlString = urlRequest.url?.absoluteString, urlString.hasPrefix(Auth.getApiEndpoint()) {
        /// Set the Authorization header value using the access token.
           urlRequest.setValue(accessToken, forHTTPHeaderField: "Authorization")
        }

    return urlRequest

   }
}

Output :

response: SUCCESS: 12 bytes // (Unauthorized) -> Corrupted zip file

Solution

  • Without a validation step in your request chain, all responses will be considered successful. So check your response code (or just add .validate() before responseData) and see if your request is actually successful. Also, you may want to double check your parameter encoding, though you don't seem to be sending any parameters.