Mark, thanks for taking the time to give this in-depth answer. This will come in handy for others as well I am sure.
Have a great weekend. Tom On Fri, Jun 24, 2022 at 1:04 PM Mark Waddingham via use-livecode < use-livecode@lists.runrev.com> wrote: > So this is mainly aimed at Tom Glod due to a question he asked in this > afternoon's Feature Focus session which I perhaps did not answer > particularly well (and given that it is security related, I figured I > should expand on what I said). > > The question was whether putting an API Key as a LiveCode 'constant', > rather than anything else, made it 'more secure' - the answer is 'no > more than putting it anywhere else in a password protected script'. > > However, what I should have probably expanded on is what my > understanding on the best practice for API keys in general is... > > I have come across three kinds of API key in practice: > > 1) API keys intended to be used from web pages (in client-side code) > > 2) API keys intended to be used in deployed apps > > 3) API keys intended to be used for doing secure things > > How I would advise using them (based on my current understanding, at > least) is: > > TYPE 1 > > In (1) above you have things like Google Analytics 'product ids' (which > aren't strictly API keys I guess, but are similar enough to warrant > inclusion) and Google Maps JS keys. > > As these are intended to be used in client side JavaScript - there is > very little, if anything, you can do to protect them directly. > > For Analytics, since the worse that can happen is that someone can > generate fake analytics it doesn't really matter - and the data can be > relatively easily filtered and processed to eliminate any dodgy looking > submissions. > > For Maps, it can cost you money if someone else tries to use yours - > however, you can restrict the key by the referring website and IP > addresses, as well as what the key can do. > > TYPE 2 > > In (2) you have things like Google Maps App keys (for Android/iOS) - and > all manner of other 'cloud type' services which have (native) app > bindings for mobile (and desktop). > > Many services offer restrictions for these keys too - for example Google > Services API keys can be restricted by Android app signing hashes and > ids, and iOS app bundle ids. > > However, in general, these services generally suggest that you ensure > that the API key is not extractable directly from the app bundle (after > decompressing in general) - i.e. that the key be obfuscated in some > fashion and does not appear in plaintext. > > It is important to note that they do not require any more than this > because, at the end of the day, any API key has to be in memory at some > point, and indeed has to be transmitted 'over the wire'. If someone has > enough access to access memory, then they have enough access to > intercept the HTTP requests (even if encrypted - if they really know > what they are doing) so obfuscating in the on-disk files of the app is > as good as you can get. > > If these keys are compromised then it is a pain - it might cost you > money (as all these services which have them tend to charge by use) - > and, if embedded in an app, will require an app update to replace. > > TYPE 3 > > Certain services require (sometimes in the TOS!) that their API keys > *never* leave a secure bubble which you control - this means they must > never appear in deployed apps or in files transmitted to the browser. > Payment gateway API keys will pretty much always fall into this category > - Stripe is a good example. > > The only way to use these keys is from server scripts running on a > server which you do your best to maintain the security of. Ideally these > keys should be stored in files which are only readable by specific users > - usually the web-server user which is running the backend scripts which > needs to make the requests. > > Indeed, services which require this tend to design their APIs for the > intention of being used on a server. > > WHAT TO DO IN LIVECODE > > If you are dealing with a type 1 key then you really don't have to worry > - they are designed to be used in a context which offers zero ability to > protect them, so including them in a deployed app (in particular) is > more secure out of the gate than in their intended use in a webpage. > > [ Of course, whether you are actually *allowed* to use their services > from anything other than websites is another matter - and entirely > defined by their TOS - but I digress! ] > > If you are dealing with a type 2 key then the requirements put on their > use in deployed (native) apps is more than catered for by having the key > in script, in a password protected stack - for example, as a constant > return value of a function, or indeed as a constant defined in the > script which is talking to the API. With this, the key will not appear > in plaintext in any of the files included in the built app (even after > the container is unzipped). > > [ I should note here that custom properties values also do not appear in > plaintext in any of the files of a built app - however, having them in a > password protected script offers an extra level of protection ]. > > If you are dealing with a type 3 key then you must only use that key via > a server - this means you need to set up server side scripts which your > app then talks to via a suitable protocol (e.g. HTTP / REST) to perform > the operations which use it. The key must never be sent over the wire > between your app and the server as this could be intercepted by someone > who is using your app locally. > > BEST PRACTICE FOR APPS WHICH REQUIRE USER LOGIN > > Of course, the most secure way to use API keys of all types is to have > them only ever on a server - however, this is only really suitable if > your app is 'always online' and you can do all operations on the server > - many services this doesn't work, e.g. Google Maps. However, there is a > reasonable middle ground which offers a little more security (and > convenience, in the case of compromise!). > > If your app can only be used by a user *after* they login locally then > the best practice for type 1 and type 2 keys (as mentioned previously > type 3 keys must NEVER leave your server!) is to not store the keys in > the deployed app at all. > > Instead, once the user has successfully authenticated have the server > send the API keys the app needs to use. You can either do this once per > session, or if your app allows 'offline' use as long as they have signed > in before (on mobile) you can use something like the 'secureKey' library > to store them in the mobile devices 'trusted' store. > > This approach has two main benefits: > > 1) The API keys are never actually in a file someone can sit and > dissect at will (even obfuscated, there are some very persistent bad > actors out there!) > > 2) If your API key is compromised (or you do need to change it, for > whatever reason) you can do so without having to have everyone install > an app update with the new one in. > > Anyway, that's probably more than Tom probably needed to know (or > perhaps knew already), but hopefully it is helpful (at least for those > who have to deal with API keys and such things!). > > Warmest Regards, > > Mark. > > -- > Mark Waddingham ~ m...@livecode.com ~ http://www.livecode.com/ > LiveCode: Everyone can create apps > > _______________________________________________ > use-livecode mailing list > use-livecode@lists.runrev.com > Please visit this url to subscribe, unsubscribe and manage your > subscription preferences: > http://lists.runrev.com/mailman/listinfo/use-livecode > _______________________________________________ use-livecode mailing list use-livecode@lists.runrev.com Please visit this url to subscribe, unsubscribe and manage your subscription preferences: http://lists.runrev.com/mailman/listinfo/use-livecode