I'm trying to setup Kahuna for my iOS app, and haven't been able to find a clear answer - the docs says that the secret key is meant to be used with the API Key for authenticating requests, but I can't find anything that states clearly if either of these should be kept secret/out of source code. Are these safe to put in my code, or should they be kept on the server side?
Thanks
Are these safe to put in my code, or should they be kept on the server side?
Short Answer is no for keeping them on the mobile app code and yes to keep them on the server side.
Why?
Because they will be static secrets in your mobile app code, thus they are easily extracted by using any reverse engineer tool, like using the Mobile Security Framewrok(MSF) to decompile the app binary.
Alternatives?
Well you can try code obfuscation, to generate the secrets dynamical in the mobile app or to store the secrets in the iOS keychain, but once more they can be reverse engineered at run-time, once more by using the MSF tool.
Possible Solution?
The best approach is to use a Mobile App Attestation service to protect the connection between the mobile app and the API server, that will guarantee at run-time that your App is not being man in the middle attacked, being tampered with, that is not running in a rooted or jail broken device and that is the same original one uploaded into the app store. This is done in the background without impacting the user experience by using an SDK integrated in your App and a service running in the cloud.
With this guarantees in place we don't need any-more to store secrets in the mobile app for Authentication, Authenticity and Integrity purposes, thus any access to third part services within the App can now be delegated to the API server that will be able to do a better job of protecting all the necessary secrets to access the third part services, like storing them in a vault.
You can find a Mobile App Attestation service in Approov(I work here) that provides SDKs for several platforms, including iOS. The integration will also need a small check in the API server code to verify the JWT token. This check is necessary for the API server to be able to decide what requests to serve and what ones to deny.
I started a few weeks ago to develop my first IOS app and it requires Twitter and Facebook Login.
I am very surprised about the different approaches that both platforms take in terms of security/authentication.
Facebook uses the IOS Bundle ID approach, which seems great, since every Bundle ID is unique and you cannot publish an app Bundle ID in behalf of another user, so is pretty easy for Facebook to figure out if your are who you say you are.
Twitter uses his traditional Key/Secret pair that uses in Web/REST applications in IOS as well, while it works for the Web because you don't need to expose those keys to the Client, that is not the case for IOS applications.
According with the official documentation
"To initialize the Twitter Kit with your app’s credentials, pass them
to startWithConsumerKey:consumerSecret:"
"Calling startWithConsumerKey:consumerSecret: will override any keys
which were automatically configured. Automatically configured keys
live in your app’s Info.plist under the key"
My understanding is that even if I use my keys, or I use the keys generated by Fabric, those will be exposed on the plist which is a non-secure method to store private keys.
I am sure I am missing something here, please clarify me how it works.
I'm trying to make an Autocomplete field which should fetch cities as the user types, by using the Google Places API as described in this tutorial:
https://developers.google.com/places/training/autocomplete-android
You've probably found this question around many times before as I did, but none of the answers helped me. Here are the things you should know:
The URL is
https://maps.googleapis.com/maps/api/place/autocomplete/json?sensor=false&key=myKey&components=country:ro&input=whatTheUserTypes
Please don't reply by saying you replaced the API key with your own and it worked - the API key which goes there must be Android specific and won't work from a browser.
So did I make the Android API key using the SHA1 fingerprint obtained from the keystore I signed the app with.
I turned on Maps and Places APIs from the console.
The quota isn't exceeded.
All those and it still gives me REQUEST_DENIED
What I didn't mention is that I have O2Auth activated - does that change anything? Shouldn't it be as simple as putting the API key in the app?
Thanks!
Although this has been answered, I think the community could do better.
I was tearing my hair out about this, it just didn't make sense to me.. I was making an iOS/Android App, so I made an iOS/Android Key...
Wrong.
With Google's Places API, your bundle identifier isn't even considered.
What you really want to do is this:
(I'm using the new User Interface)
1. Log into https://cloud.google.com/console#/project
Select your Project Name, then go into API's & Auth > APIs
Make sure you have Places API Turned on. This is the only thing that needs to be turned on for Places-API to work.
2. Go into Credentials
Click CREATE NEW KEY under Public API Access
3. Select BROWSER KEY
4. Click Create, Nothing Else
Leave the HTTP Refer box empty.
5. Use the Key Generated here
This key will allow ANY user from any device access to the API via your Developer login.
You can try it out here: (Be sure to replace YOUR_KEY_HERE with your generated Key)
https://maps.googleapis.com/maps/api/place/autocomplete/json?input=Food%20Sh&sensor=false&radius=500&location=0,0&key=YOUR_KEY_HERE
6. Enjoy
Now you can use that URL above in your Android/iOS device.
The Google Places API does not currently support Android or iOS keys generated from the Google APIs Console. Only Server and Browser keys are currently supported.
If you would like to request this support, please file a Places API - Feature Request.
https://developers.google.com/places/training/autocomplete-android
Storing your API key
Although the above code demonstrates how to communicate directly
between an Android app and the Places Autocomplete service, you should
not store your Places API key with your app.
You should therefore build a web application that stores your API key
and proxies the Places API services. In order to secure communication
between your Android app and the proxy web service, you should require
user authentication to your proxy web service. Your Android app can
securely store user credentials and pass them to your web service, or
the user can log into your web app via an Android WebView.
For the latter approach, your web app should create and return a user
authentication token to your Android app, and your Android app should
subsequently pass this token to your proxy web service.
Go to google cloud platform console>Credentials click on edit by selected your YOUR_API_KEY>Application restrictions > select none option>save thats it.
If you select the android apps option from Application restrictions then google deny the place API with exception REQUEST_DENIED.
In Google dev console, you should be able to find both "Places API" and "Places API for Android"
Make sure to use "Places API for Android"
For some reason, "Places API for Android" is hidden in the API list, but can be accessed using search.
I had the same issue , I fix it by leaving
Accept requests from these HTTP referrers (web sites) (Optional)
in browser key Empty
I am still new, so I cannot comment, but to shed some light on Moe's answer, I resolved some similar Google Maps API issues regarding URL queries (for directions, using Volley) with the following steps:
Get Android API Key (including Google Maps Directions API in my case).
Get "Server" API Key (which seems to be created by using a key restriction of "HTTP referrers" these days - really, it's just used to issue URL queries through HTTP).
Store the Android API key as a meta-data tag in the application tag in AndroidManifest.xml with android:name="com.google.android.maps.v2.API_KEY" and android:value as your key. This is used for direct interaction with the Maps API (minus URL queries).
Use the server API key whenever issuing URL queries.
I am not sure if this also applies to URL queries for the Places API, if you only need the server API key, or if there is a better solution, but this worked for me.
I imagine that it works with just the first key - the one not restricted to Android.
Inside Google Cloud Console type Places and Activate it. Create an API Key and insert it onto your Android Studio App as you would do normally. That`s it.
I had the same problem. For me the key was to enable billing on project. I am still using "Applications for Android" restrictions. After setting up the payment method, Places Api started working.
Prior to using the Places SDK for Android, do the following:
Follow the Get an API Key guide to get, add, and restrict an API key.
Enable billing on each of your projects.
Enable the Places API for each of your projects.
See it there.
Be sure also to check out the billing plans for the Google Places API as it is not free!
I have to call payment gateway API from iOS code. Problem is it needs merchant credentials and I feel insecure embedding the merchant credentials in code. If someone somehow reverse engineer the code and get the credentials then the client is dead. Any advice?
I found this post Does Apple modify iOS application executables on apps submitted to the App Store? which says that app binaries are encrypted by Apple be default. Does it mean I can safely embed the credentials in code?
NO! Instead of adding the credentials to iOS app you should think about setting up a server which handles the interaction with the API, you are talking about, and let the app only interact with your server. So you can store the API key on your server and can limit whats possible by the user on server side (which will be much harder to abuse).
In the Facebook App Settings ☞ Advanced ☞ Authentication I can pick "Web" or "Native/Desktop" as App Type. The info bubble says:
Only select Native/Desktop if you are a Native iOS or Android app,
device, or Desktop app
Actually I am none of those but my app is a Native iOS App as well as a Facebook Page Tab.
Question: Which App Type should I pick?
I did some research and found the following in the Facebook Android Tutorial (under Troubleshoot):
App type Web vs Native/Desktop. Does it matter?: No, it does not
matter. However it's recommended to use the type 'Native/Desktop' for
your app.
What does it mean it does not matter? That does not make sense to me. Why should I have a choice then?
I did some more research on SO and found this statement by #Igy (dev support engineer at Facebook):
If the app's type is set to 'Native / Desktop' it's assumed you
distributed the app's secret key with the binary, and thus the app
access token isn't trusted (and 'getAccessToken' in the PHP SDK will
only work when real users log in, it can't fall back to the app token)
Finally I found this in the Facebook documentation:
Note: Applications that are configured as Native/Desktop apps will not
be able to make API calls that require an application access_token.
I do need to make API calls which require an access token from my page tab app, hence my conclusion is to pick "Web" as the App Type, although I'm having a native iOS app using the same app ID as the page tab app. But will that have any drawbacks on the iOS app?
TL;DR: use 'web' unless you're putting the app secret into the iOS / Android binary
The primary difference (and also the reason that it says 'it doesn't matter' while also giving a recommendation) is that if you choose 'native/desktop' mode, it's assumed that you distribute the app binary with the application secret embedded and the app secret is considered untrusted.
In this configuration, API calls which use the app secret (e.g. creating test users, making API calls on behalf of the app itself like changing app settings, posting achievements, etc) will not work.
If your app doesn't need to use the app secret / app access token, setting it to native/desktop increases the security somewhat as there's one less attack vector for your app.
If you're distributing the app secret with your code you MUST use that option or users could easily determine the app secret and hijack the app itself.