Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to upload a file to S3 using alamofire 4.8 using multipartFormData with access key?

I am attempting to upload directly to s3 using alamofire (my app has to run on the apple watch and the aws-ios-sdk does not work on the apple watch). I know I have to sign the url but am at a loss of how to directly form the request given a url. However, my current approach seems to do nothing of the sort. I have found several similar questions that don't seem to address upload with alamofire directly to s3, end to end, including signing a url with access keys and secrets.

code

class UploadUtil 
    public func upload(file: URL, key: String, success: @escaping ()->()) {
        let access_key = "AKIA123453435242"
        let secret = "abcdefghijklmnopqrstuvwxyz"
        Alamofire.upload(
            multipartFormData: { multipartFormData in
                multipartFormData.append(unicornImageURL, withName: "unicorn")
                multipartFormData.append(rainbowImageURL, withName: "rainbow")
            },
            to: "https://mybucket.s3.amazonaws.com",
            encodingCompletion: { encodingResult in
                switch encodingResult {
                    case .success(let upload, _, _):
                        upload.responseJSON { response in
                            debugPrint(response)
                        }
                    case .failure(let encodingError):
                        print(encodingError)
                }
            }
        )
    }
}
like image 364
Victor 'Chris' Cabral Avatar asked Dec 05 '18 01:12

Victor 'Chris' Cabral


1 Answers

You'll need to use your AWS creds to sign the request. Details on the signature scheme are here: https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html

That said, you might not want to be embedding AWS creds into your watch app. They'll be hard to rotate/manage without pushing out an app update.

Are your users signing into any kind of web service that you control? If so, you could have them upload blobs to that (using an authenticated POST), and then shovel the data into S3. Or, you could have your web service vend a presigned url to users that they use to upload data. Or you could have the watch app auth to a service using something like API Gateway, and then have a lambda handler put data into S3.

If you are doing any kind of "social login" (sign in with facebook, sign in with google, etc), you can OAuth to IAM and get unique creds per user. thats another way to go if you want to do it straight from the app without maintaining a service.

If you're ok with embedding the same set of IAM creds into every watch app, then look at SigV4, but I'd suggest seeing if theres a way you can authenticate based on individual users.

like image 140
Alex Avatar answered Nov 12 '22 04:11

Alex