On API keys...

Tom Glod tom at makeshyft.com
Fri Jun 24 13:40:22 EDT 2022


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 at 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 ~ mark at livecode.com ~ http://www.livecode.com/
> LiveCode: Everyone can create apps
>
> _______________________________________________
> use-livecode mailing list
> use-livecode at lists.runrev.com
> Please visit this url to subscribe, unsubscribe and manage your
> subscription preferences:
> http://lists.runrev.com/mailman/listinfo/use-livecode
>


More information about the use-livecode mailing list