No Code challenge: create file named after user in OCI Bucket through OCI API Gateway 1vLd09EWkSWs29xIwcfFGoQ

No Code challenge: create file named after user in OCI Bucket through OCI API Gateway

In this article I will share what I could not find (exactly) in the documentation and what my AI assistants wildly hallucinated about (too little documentation, too little code samples?). It is a fairly simple mechanism that I am planning on using a lot: save data from a static web application in a secure way without having to run a database or writing a lot of code.

This is what I want to achieve in some detail:

No Code challenge: create file named after user in OCI Bucket through OCI API Gateway
From the static web application (loaded from GitHub Pages) the authenticated user can save their personal changes. Through a PUT request to OCI API Gateway, a file with the name of the user should be created on OCI Object Storage. Without any code — only from declarations.

My static web application is started from GitHub Pages. It then has the user authenticate (against my company’s EntraId tenant); using the acquired JWT token, OCI API Gateway is called to retrieve the (confidential) data for the application that only my colleagues can see. The data is in a JSON file, stored on OCI Object Storage and accessible over a Pre Authenticated Request URL included in the Deployment definition on API Gateway. This is described in an earlier article.

Then, the user can make changes to their own data in the application, and save those changes. This happens by making another call to the API Gateway. This PUT call is also checked for the authentication token (as well as CORS policies). Then, URL for the backend to be invoked is constructed from another Pre Authenticated Request URL (one that allows Listing and Writing objects) and that includes “deltas/” as a prefix in its definition, so only objects in the “deltas folder” can be seen and written) and the user claim in the JWT token. The API Gateway makes sure that the name of the file corresponds with the name of the user in the token — even if the user has tried to manipulate the data submitted and make it about some other user. When we process the user specific files on the backend, any file where name of the file does not correspond to the contents of the file will be discarded.

This flow in more detail is illustrated by this image:

No Code challenge: create file named after user in OCI Bucket through OCI API Gateway
Internals of the setup required to have API Gateway create file on OCI Object Storage with the proper name — derived from the user claim in the IdToken

Implementation Steps

Create the Pre Authenticated Request (URL) for the bucket — with prefix set (to restrict access to “folder” conclusion-assets/deltas/) and Read, Write and Listing enabled for all objects.

No Code challenge: create file named after user in OCI Bucket through OCI API Gateway 1dJWSEBX i0VKTNO3UeML3A

Assuming a Deployment on API Gateway with Authentication and CORS configured (as described in this article), make sure that the CORS settings include the OPTIONS and PUT methods in the Allowed methods and the Content-Type in addition to Authentication in the Allowed headers:

No Code challenge: create file named after user in OCI Bucket through OCI API Gateway 1m6EHEGTyHQnYBjGTB3c9wg
CORS settings to allow PUT (which will be preceded by an OPTONS call) as methods and Content-Type as header

Define a Route that associates the public endpoint with the dynamic URL that leverages the Pre Authenticated Request and defines the file name using the user claim from the JWT Token.

No Code challenge: create file named after user in OCI Bucket through OCI API Gateway 17MU1WDTH wglhKFeDbq5Pw
The Route definition with a backend URL that contains the expression ${request.auth[user]}

The URL is defined from the combination of the PAR, the prefix and the expression ${request.auth[user]} that evaluates to the value of the user claim in [the IdToken in] the JWT Token.

When I save my own data from the web application, the resulting JSON file is created as “conclusion-assets/deltas/Lucas Jellema”. Nothing I can do from the web application to prevent that — because the name is derived from the authentication token that I cannot tamper with. And nor can my colleagues.

No Code challenge: create file named after user in OCI Bucket through OCI API Gateway 1UFkOrW2wgrDksLmWGCIF9w
When I save my own data from the web application, the resulting JSON file is created as “conclusion-assets/deltas/Lucas Jellema”

The logging produced by API Gateway explains what happened:

No Code challenge: create file named after user in OCI Bucket through OCI API Gateway 1s3O9gPzw2aAgrWD 80kjgQ

In words:

"Dynamic request url formed: 
[https://hanz.objectstorage.us-ashburn-1.oci.customer-oci.com/p/1EJ9/n/hanz/b/laptop-extension-drive/o/conclusion-assets/deltas/Lucas Jellema]
from configured url:
[https://hanz.objectstorage.us-ashburn-1.oci.customer-oci.com/p/1EJ9/n/hanz/b/laptop-extension-drive/o/conclusion-assets/deltas/${request.auth[name]}]"

I will now create a script or function that will periodically process all files in the deltas folder. Any file where the data in the file (the name property first and foremost) corresponds with the name of the file will be processed (and the data added to main data file that all users can make use of).

The code that makes the call from my web application:

    const deltaEndpoint = "https://odzn.apigateway.eu-amsterdam-1.oci.customer-oci.com/conclusion-proxy/speakerpool-delta"; 

try {
const response = await fetch(deltaEndpoint, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(updatedProfileData)
});

if (!response.ok) {
...
}

and the logging in Console and Network pane:

No Code challenge: create file named after user in OCI Bucket through OCI API Gateway 1*WBkphkZ85214UvL87d1FyA
Feedback from saving the user data by sending PUT request to OCI API Gateway

Lessons learned along the way

Some of the things I learned along the way:

  • prefix $ in Terraform configuration files with another $ — to prevent untimely evaluation a Terraform variable (so $${request.auth[user]})
  • the JSON document you get by exporting an API Gateway Deployment using OCI CLI is not correct! (properties are named with xxx-yyy instead of xxxYyy , you need to convert all hyphenated keys to camelCase keys). Here is the command.
oci api-gateway deployment get \
--deployment-id ocid1.apigatewaydeployment.oc1..xxxx \
--query "data.specification" \
--raw-output > deployment-spec.json
  • expressions such as ${request.auth[user]} cannot be followed by “.json”. This is not correct syntax: “${request.auth[user]}.json”, to be used in the URL. The feedback about this is somewhat unclear from both Terraform apply and the console (Invalid specification.routes[1].backend.url: contains invalid path segment for HttpBackend). The documentation does not mention this at all.
    Note: multiple expressions can be strung together. It is perfectly fine to have this definition for URL:
    https://hanz.objectstorage.us-ashburn-1.oci.customer-oci.com/p/1EJ9/n/2hanz/b/laptop-extension-drive/o/conclusion-assets/deltas/${request.auth[oid]}${request.auth[preferred_username]}${request.auth[name]}
No Code challenge: create file named after user in OCI Bucket through OCI API Gateway
This unclear error message took me hours to fix; I focused on ${request.auth[name]} — but that part was correct it turned out (much later)
  • beware the hallucinations from AI tools. I got all kinds of recommendations, including syntax that does not exist at all. All kinds of rabbit holes to fall into and chase wild and meaningless options.
No Code challenge: create file named after user in OCI Bucket through OCI API Gateway 1iPog2kD7 iD6kKINZnsndQ
Invented by ChatGPT: a new type of request transformation; it is so plausible, I am still almost believing it. But it does not exist! It is a fabulation. Only took 45 minutes to unmask for what it was

Of course I should have figured out much sooner that this was nonsense:

No Code challenge: create file named after user in OCI Bucket through OCI API Gateway 1oOVvDo qecIhK2InowMfLA
There are ways to dispel the magic

Conclusion

The solution I have created is satisfactory. With only configuration and no special moving parts I can have users save data in a proper, authenticated way.

I would have preferred to add the .json extension to the filename, but I do not know how to do it (other than by creating a request header with the value of json and adding it to the URL definition.

The documentation on using the ${request.auth[claim]} is somewhat underwhelming; no complete examples. And the community seems to have produced little of value in this area either. Which leads to poor AI tool assistance. I have said it before: technology that does not have a lot of resources (StackOverflow, documentation, code samples, tutorials, community articles) and therefore does not get great AI support is under threat. Why use stuff that my tools cannot properly help me with?

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.