I'm having issues integrating the AWS iOS SDK (authentication specifically) along with download of a simple URL from a bucket.
I'm using StackMob to store my data, and files are managed through AWS in S3 storage. When querying for an object, the link to the S3 object is given.
I have implemented the Anonymous bucket token registration, and it works fine in the demo application, I can see all the buckets as well as the files in the buckets but here's the big question:
How do I authenticate with AWS using the iOS SDK, and use that authentication to download a URL to an object in my bucket that I already have the link to?
Going directly to that link brings up an access denied error. Also, some of the files are private and not distributed, so I do not want to just make the entire bucket public for people to access with the link.
Any suggestions? I think I read somewhere that you can manipulate the URL to include your access key and secret key, but that you should never include that in a binary as it could get stolen, so maybe having it on a private server and pulling that key to temporarily use it?
Any help would be great!
Thanks
I contacted Amazon support, and it turns out that what I'm looking to do is currently impossible with the SDK.
The only way to generate a URL is having the bucket name, key, and use the "getPreSignedURL" API call to get a signed link to it.
I'll leave this up, hopefully someone will learn from this and not have to pay $50/month for support for this one question.
Related
I'm writing an open-source stand-alone desktop app in Java that handles photos, and I'm adding a feature to let users upload pictures to their Google Photos account, but I'm faced with an authentication/security question.
I've registered my project to use the Google Photo API and have downloaded my credentials JSON file. I've been able to use it successfully with the samples from the java-photoslibrary Github project, so all is good.
However, the credentials file contains a "client_secret" key which, if I'm not mistaken, should not be disclosed (am I correct here ?). But those credentials have to somehow be distributed with the app and, as it is open-source, will be basically public. So my question is: How can I authenticate my app's user to his/her Google Photo account without disclosing my app's secret key ?
Note: I've integrated Dropbox upload, and their procedure for desktop apps clearly explains how to authenticate without embedding the secret key in the Desktop app using OAuth's token flow. Is there an equivalent for Google Photos ?
Thanks.
Edit: made some progress (see my own answer below), but after I finally got time to implement it, I realized that after user has authorized the app and a valid code has been returned (Yay!), step 5 (Exchanging the code for a token) again requires the client_secret ! :-(
I tried the call without it but I'm receiving a "client_secret is missing" error, so that's not a typo.
After more search (with the [google-oauth] keyword instead of [oauth-2.0], which says it all), it seems "secret" does not mean it is actually "secret" in Google world. In other terms, it's OK to embed it in your apps because, well, it's secret but it cannot be used in a malicious way (hopefully)...
See answers to these related questions:
Safely distribute OAuth 2.0 client_secret in desktop applications in Python
Why does Google provide a client secret for a Native application?
Integrate oauth2 with native (iOS/Android) mobile application
One Google page even mentions that "In this context, the client secret is obviously not treated as a secret."
Come on Google, explain me how security works :-)
OK I think I found the answer.
Similar to Dropbox, Google can use OAuth 2 with PKCE, they just use the full spelling "Proof Key for Code Exchange", that's probably why I didn't find it at first :-). The details are here:
https://developers.google.com/identity/protocols/oauth2/native-app#obtainingaccesstokens
I didn't find the equivalent process in the Google APIs, but those API are megabytes of classes so I may have missed it. Basically, all it takes is just sending a few requests and listening to the response, so I think I'll implement it from scratch (and will probably also get rid of Dropbox's client libs as the process is so similar).
Hope it helps...
Edit: that doesn't address the point because after the clean PKCE procedure, the app still has to send its private key to exchange the authorization code for a token. See edit in my question
This may be a dumb questions, but I haven't found an answer after lots of searching. I need to do two things, I need to allow my app to login to google, then save a file the users google drive.
I've found some steps on how to connect to google drive, but either its outdated or I don't have the correct libraries because it fails to compile: https://www.codenameone.com/google-login.html
Any help would be greatly appreciated.
For the login part there are good instructions in this blog post
Another sample of code to login to Google in this demo
You'll need to set the scope of the OAuth2 login to the appropriate Google Drive Scope
For saving files to drive, you should use ConnectionRequest to create the HTTP requests directly to their REST API.
Check the Integrating Google Sign-In into your web app. There's even an video guide explaining the concept.
There's a quick Save to Drive which enables your web site to allow users to save files to their Drive account from an arbitrary URL via their browser. If that's not sufficient enough, you can always check the Uploading Files where you can upload file data by creating or updating a File resource.
I'm making a global iOS App with AWS SDK.
And there is a function for users to get image files; only if the requester is a friend of the image files' uploader.
For this function, I use AWS S3 for storage service with private access.
And I want to use CloudFront for my users to get download files faster.
I should set the bucket name for downloading on AWS S3 SDK, but it seems that the CloudFront does not support for this bucket name.
Is AWS CloudFront only for public things with url?
If you want to serve private content via CloudFront, you will find this doc useful http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html. Currently the AWS SDK for iOS doesn't support CloudFront directly. You need to manually sign the request. A related question is asked on AWS forum https://forums.aws.amazon.com/thread.jspa?messageID=336955.
Have you consider making your AWS S3 bucket public, and then encrypting all of the users pictures? You could push the keys through EC2 or another service and still get the performance of CloudFront.
However, even if you can download photos from CloudFront as indicated in https://forums.aws.amazon.com/thread.jspa?messageID=336955, it is HIGHLY not recommended to do so, because you will ship your private key pem file to the public together with your app. Yosuke said this clearly.
I have an app using RestKit successfully. I am building an IAP in the app and for iOS5 I needed a place to host the app files for the IAP. I decided using Amazon S3 for that.
Now I now that I can integrate amazon API but I wish to keep my app simple, and since I am using RestKit I just want to use it to download the files.
Is there a guide or explanation on how to generate a bucket url with expiration and secrets ?
Thanks
Shani
Sure: all the information you need is in the Authenticating REST Requests documentation page.
Also, it's not entirely clear from your question, but I hope you're putting the URL generation in some web app somewhere that you control, rather than directly embedding it in the IOS app. I also hope you're using IAM to restrict that key to the appropriate permissions level regardless.
Would encrypting the S3 keys in my binary be a good idea? How?
Thanks!
I would recommend you do not include them in your app. Put them on a server with a REST based interface and limit the possibilities of the single user on the server side.
When the user gets you S3 credentials they will be able to abuse them! And they will always be able to get them when you include them in your app.