Using JSON Web Tokens For Userless Mobile Authentication
For my travel vocabulary app Pidging (created with Flutter/Dart), I'm using an API (written in Python) that manages requests to actual translation service (Microsoft Azure Translator), cache results in memory and DB and also manage a built-in vocabulary. There's no concept of user though, as all user-generated content remains on user device, and server-side only caches translations.
But even though the API is simple and no user info or content is exposed, I still want to protect it from being abused, be able to control any unwanted user behavior and potentially store user data on server to remedy the situation where app is removed and then reinstalled, or migrated to a new device.
I thought about introducing user authentication, but I really don't want to impede the access or introduce any extra steps to the app usage. So I decided to go with an identifier-based approach - but not with device id, because I don't control its creation/change, and it also is considered a PII.
So I decided to generate app ID (UUID v4) when app id launched for the first time, and store it in the keychain - as keychain content is the most persists content storage on the phone, and I'm not abusing it much (as I'll mention further on, there's also access and refresh tokens, but it's still a negligible amount of data). I'm using https://pub.dev/packages/flutter_keychain to manage the process.
The next consideration was to how to use it in the App-API communication. I first thought of doing something sophisticated like generating cryptographic key pair on the app, register public key on the server and then pass encrypted tokens with the API calls to ensure authentication. That would work (even though I'd still need to maintain some token expiration mechanism), but it was unnecessary complex and would involve bringing A LOT of dependencies. So I decided to keep the encryption to server and just use a tried JWT (JSON Web Token) approach, which has established libraries in many languages (I'm using Flask-JWT-Extended).
Currently, the logic sequence diagram looks like this (thx https://sequencediagram.org/):
The next steps would be to utilize this mechanism not only for a stricter access control, but also to save/restore user data at the server side.