Webhooks is an amazing API, it allows our application to react to events that happen on other systems, which is close to magic sometimes. This sample is quite interesting, it sends an SMS, email notification and Slack message for new files. Learn more at this previous blog post. In this case we use a trick: store the phone number, email address and slack channel into the hook attribute, that way the app don't store anything, just perform the action.
There are a few challenges moving forward, especially regarding Authentication. I started discussing this topic before, see this blog post, in summary, the access token is required to read/write data, and in the context of BIM 360 and Data Management, it needs to be a 3-legged token. Quick reminder: this involves the end-user (owner of the data) authorizing access to it and our app can use the refresh token to extend this access. On apps with user-interface this can be simplified by storing that information on a secure cookie or session, so when the user comes back we use it to refresh the token. But what about back-end interface for webhook?
As the webhook will callback our app in a random time in the future, the app will need to use the refresh token to regain access to the data. The only way to keep that record if by using a database. Here we have another important point: only the last refresh token issued is valid, learn more here. So we also need to make sure every new sign in or refresh token action is properly tracked and the new refresh token stored.
For this sample let's use a modified version of the 3-legged tutorial code. The main change is that, on first sign-in, the credentials, access and refresh token, are stored in a database with the expiration date. If the credentials are refreshed the new values are updated on the database. The only way to truly identify a user is by his/her Autodesk ID, and that's what we use as our Primary Key (or Document ID for NoSQL database). When the webhook calls back it includes the Autodesk ID, which is used to obtain the access token (refresh if needed) and read/write data.
Time for the sample: based on yesterday's blog post, this new sample register for dm.version.added event, when it triggers, let's call manifest endpoint to read the newly uploaded file information. Here is the workflow:
For this I'm using .NET Core 2, which runs fine on Windows, MacOS and Linux. Is also compatible with Heroku via build-pack. Interested? Learn more here. The database is a MongoDB hosted on mLab, free up to 0.5GB development environment. I'm also using Hangfire to queue jobs, which is far better than starting additional threads in ASP.NET and allow retry on failure (e.g. exceptions). Finally, for local testing, you'll need a tool like ngrok.
Let's see it in action, here is a video demonstrating all the moving parts: