Debug and reverse engineer a UI5 application – Part1
The other day I ran into an issue with the SAP web app https://go.support.sap.com/minisap/ to generate a new license keys for my netweaver developer version. The app did show just an empty shell and no content. Really needing the license right then, I decided to have a look at what the issue was with that app. In addition to my license, some exercise in dealing with UI5 seemed also worthwhile. I ended up debugging through the app, tapping the associated OData service and reconstructing the app in my WebIDE und brought it up and running, finally getting my license. Even though I spent some time on this, in the end I was quite pleased with UI5 from a developer point of view, the tooling that SAP provides and the accessibility to these web applications. Having a background in ABAP development, I am used to have full access to application sources, frontend and backend alike on the ABAP stack.. It is nice to see, that UI5 apps can be quite accessible as well. So I want to share that experience.
Opening the developer tools in chrome, first thing that I noticed were a bunch of error messages in the console.
Nothing too unusual seeing error messages there, but TypeError: sap.ui.require.preload is not a function sounds like an compatibility issue with the deployed UI5 library version. Nothing I can do anything about on that server.
Now, the source panel lists some files that are loaded for the app:
The ServiceClient.js in the helpers folder seems to be some facade for the access to an OData service. Even thoug it is somewhat minified, it is easy to read with the Chrome pretty print. There in line 23, 24 it sets a path, depending on the location ( containing “go”, which is there in the public URL for the app ). That string reads like an OData service address. And as such it is used in line 30 to create an OData model instance.
Now peeking at the OData Service at https://go.support.sap.com/minisap/odata/bkey/minisap
Hit! The service description contains two entity types: LicenseKey and Types. The ServiceClient.js contains two functions that do something with the OData service: createLicenseKey and read. Both functions expect some not so clear input in the form of objects passed in and then either do a create or read on the OData model instance. Both use the entity property of the import object to create a path. Let’s try just for both and read LicenseKey and Types. Just dropping https://go.support.sap.com/minisap/odata/bkey/minisap/LicenseKey in the browser…
The LicenseKey entity does not support reading i.e. get a list of the entities, the entity set. Seems to be just used to create entities then.
Better luck with the Types entity at https://go.support.sap.com/minisap/odata/bkey/minisap/Types. There is a list coming up and listing some license types.
Let’s give it a try, if I can get a license from the OData service. Assuming, and somewhat remembering from last using that, that a record is sent and a license received. That is then probably happening with the LicenseKey entity and using some data from the types and user input?. Looking at the LicenseKey metadata at https://go.support.sap.com/minisap/odata/bkey/minisap/$metadata:
Sparing you some try’n’error, this is the recipe to talk to the OData service. I am using Postman to do the REST stuff.
First, get yourself a xsrf token. Send a GET to the service base address https://go.support.sap.com/minisap/odata/bkey/minisap with header x-csrf-token: Fetch
The server hopefully sends a response header x-csrf-token that contains the token string. Copy that.
Next, send a POST to the LicenseKey entity at https://go.support.sap.com/minisap/odata/bkey/minisap/LicenseKey. Set header x-csrf-token to the one from before and Content-Type to application/json:
Then set the request body in the raw to a json containing your request data:
The server could give you a response with your new license:
You could grab it from the Licensekey property save it to a file and be done.
Or keep reading part 2 about how to reverse engineer and rebuild that UI5 application.