-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Most recently, this is to support APIs like DOMO, but will be applicable to many other APIs in the future.
In APIs like DOMO, long-lived client credentials must be used to complete an authentication flow for a short-lived credential. This short-lived credential can then be sent with requests to protected endpoints, though it may need to be periodically renewed or replaced.
Part of Granfalloon's value is how agnostic it is in its approach. Granfalloon is compatible with any API, as long as that API:
- Meaningfully separates semantic purpose via HTTP verbs and paths
- Handles request authentication through the inclusion of a long-lived secret as an
Authorizationheader
With that in mind, I think it would be a messy, uphill battle for Granfalloon to start natively providing support for APIs on a case-by-case basis. As much as possible, Granfalloon should attempt to provide a generalized interface for supporting other APIs (which may demand a bit more from the user). At the moment, I have a few nascent ideas:
-
Adding a command-line option for pulling the
GRANFALLOON_TOKENfrom a file path, rather than an environment variable. Specifically, the secret would be pulled from the file on each request, likely with some very short-lived caching. This would allow having some external application/sidecar that runs and manages the authentication process:- The advantage is that the logic of each and every authentication API doesn't need to be managed by Granfalloon, directly or indirectly. Further, while I don't love the idea of making a secret available on the filesystem, by definition they should be short-lived. The filesystem just happens to be the most simple, platform-agnostic method for this small-scale multi-application data sharing. Long-lived credentials should continue to prefer an environment variable
- The disadvantage is that it is a bit leaky by design. Because Granfalloon has no "connection" to the process providing/renewing the token, failures won't naturally propagate.
-
Attempting to provide a "generalized" authentication flow for APIs of this nature; one that would accept a copious number of configuration parameters. Taking the DOMO API as an example, a flow looks something like this:
$ curl \ --user {CLIENT_ID}:{CLIENT_SECRET} \ "https://api.domo.com/oauth/token?grant_type=client_credentials&scope={SCOPE}" \ | jq .access_token "GhX52tNtsnyQQybNBtjrc9KbH4..."Note: The
--userparameter just base64-encodes theusername:passwordpair and adds it to theAuthorizationheader using theBasicscheme.Generalizing this a bit, it looks like this:
$ curl -H 'Authorization: {{LONG_LIVED_SECRET}}' '{{URL}}' | jq '{{JSON_PATH_TO_SHORT_LIVED_SECRET}}'
So, in summary, if we offered a generalized flow that allowed configuring the three aforementioned fields (perhaps in addition to a renewal frequency), Granfalloon could support a wider range of APIs.
- The advantage of this approach is that the authentication flow is owned by Granfalloon (though it doesn't introduce much complexity), meaning errors and the like could be handled and signaled naturally.
- The disadvantage is that it is easy to imagine APIs with slightly different flows that don't work this way. Setting this precedent means the logical next step would be to offer another semi-specialized flow. If our foresight is poor, this could happen frequently. This is further complicated by APIs that allow periodic renewals, and encourage renewal over creating new sessions when possible
-
The final option is perhaps the most ambitious, and could be seen a something of a mix of the previous two. Specifically, it involves providing a pseduo-plugin interface. This entails adding a new
--authentication-hookcommand-line option that allows providing the path to a JavaScript/TypeScript file not originally included in the Granfalloon bundle. With the interface documentation in tow, a user could provide their own implementation of an authentication/renewal process that would be loaded by Granfalloon directly and executed at the appropriate times to provide the short-lived token. This hook would be provided on startup by Granfalloon instance administrators, so it shouldn't pose any potent security risks usually associated with plugin systems.- The advantage is that, like option 0, this would allow supporting any API (as long as the user is willing to supply the custom implementation) while also being more integrated into Granfalloon as a whole, like option 1
- The disadvantage is that of complexity. Adding support and documentation for even a small plugin interface will be quite a bit of work. For users of Granfalloon, while option 0 also involves providing some "custom" infrastructure to renew secrets, it is extremely simple in scope and technology agnostic. By comparison, using this approach, users would need to write and maintain some new JS/TS code that adheres to a custom interface
I am soliciting feedback on these approaches or others