Open discussion question, not necessarily CFML rel...
# cfml-general
s
Open discussion question, not necessarily CFML related, just throwing it in here. How do you guys implement security in API's that handle confidential information? At this point we haven OAuth-based authentication (JWT tokens), but we were looking into HMAC payload security, but when using an Angular front-end, this is quite useless imho, b/c the fact that the private / public keys can be retrieved by reading the js-code... I'm open for any suggestions / other views about this subject.
t
we have a similar issue but no solution as yet, we have recently implemented webAuthn an I was hoping to be able to store a public key in the credential but that is not an option currently the most likely candidate seems to be LargeBlob https://w3c.github.io/webauthn/#sctn-large-blob-extension but sofar it has only hit chromium
p
we've used HMAC API keys from javascript apps, but with a server side workaround. we make an AJAX call to a CF page first to read the secret key from an env file, then that builds and returns the hash to the front end which calls an API elsewhere
s
@Pete Williamson can you elaborate on this approach? And also, how do you protect the AJAX call?
p
CFML based CMS serves a page, e.g. cfmlsite.com/sometool, that contains a Javascript SPA The SPA wants to make a CORS request to example.com/api, but needs to send HMAC authentication cfmlsite.com/sometool makes an ajax request to cfmlsite.com/sometool/api.cfc?method=getAPIHash&anything=else&you=need
getAPIHash
is server side, so it can read the secret key safely, create the hash, which is returned to the Vue app in cfmlsite.com/sometool The Vue app then makes the CORS request to example.com/api, sending the message body, api key and hash
it means 2 ajax requests, one to our server to deal with the secret key, then one to the API, but I can't see a way around that without either exposing the secret key via JS, or getting the AJAX call to our server to then make a cfhttp call to example.com/api And I'd rather not put that load onto our server, and have the data go straight from the API to the user's browser
s
I see, thank you for the elaboration, Pete. It's clear to me now 🙂.
p
"how do you protect the AJAX call" To the internal hash generation page? The JS tool is on a public page, so rate limiting to our sites (which I've been discussing elsewhere on slack) to stop it being over used we're only making GET requests to load product data so it's not behind a login or anything like that caching responses to minimize repeated requests if traffic spikes to the page, API calls spike, until they're capped by rate limiting or caching
👍 1
s
FWIW, we went full OAuth2 and built our own identity server stuff. We have an Auth server (for the authorize and token calls) and a Login server that does the actual username/password handling. Our main app POSTs to authorize which redirects to the Login Server, user logs in, and that redirects back to the app with a short-lived code, app POSTs that to token with client ID / secret and gets the access/refresh tokens. The access token is passed as a header in all API calls, and the app periodically exchanges the refresh token for a new access/refresh token pair (by POSTing to token).
It's pretty clean once you have it all up and running and really not that much code. You don't have to use JWTs -- in fact, some security experts warn you to use other encrypted tokens -- but having the OAuth2 workflow in place is pretty nice. In addition to our own identity system, we can easily add other identity providers and we currently use Microsoft ADS for internal accounts as well. We also allowed login via Facebook for a while (but found members weren't using it very much).