A few weeks ago I wrote a couple of Medium articles. One about Dart Isolates and the fact that they really are threads and the other was about generating Apple’s client_secret for signin with Apple. What I was really working on was this end-to-end OAuth2 demonstrator and the code for the Dart server part of the demo is now available here. The companion Flutter client is available here.
One of the first things you do when you write most apps is authenticate your users. When I started looking into the details of how to do this on Flutter, I ran into a number of interesting things:
- All of the plugins were specific to mobile platforms and I wanted support for the desktop as well.
- Some of the plugins encouraged storing secret keys in the client code which you should really never do.
- When I tried to find tutorials on how to do this myself, I either found videos on using those mobile-only plugins, or videos that used the Firebase authentication back-end. What Google did with the Firebase authentication back-end is great stuff, but if you don’t use Firebase, it just adds another dependency.
- Each plugin is different (by necessity) which means the integration of each ‘signin with <pick your provider>’ would be different in the app.
Given that I’m retired and I have nothing but time (pandemic too), I decided to embark on a little project to implement a complete OAuth2 flow that would work on both mobile and desktop, would support multiple providers (Google, Github, Facebook and Apple), and have no plug-in or back-end dependencies. I also wanted as much of a single-code base as possible to handle all the providers. These companion Dart/Flutter projects are the culmination of my little retirement/pandemic hobby.
I like to learn and the server part of the project (where most of the code and logic flow resides) got me to figure out how to write an https server from the ground up (no frameworks). I added support for Isolates (the subject of that other medium article) just because I could. There were also a number of Dart features that I learned along the way. I also went through the process of understanding JSON web tokens (ID Tokens), how to generate them, sign them and validate those signatures.
The Flutter project doesn’t do a whole lot other than initiate the authentication flow, verify and use tokens during API calls, request refresh tokens, and manage the local storage of tokens. The task management parts are really more of a hello world thing rather than a useful task manager.
By going through this, I had to learn all of the idiosyncrasies of each OAuth2 provider. While OAuth2 is a standard, you quickly find out that each provider implements it differently. It took me a couple of months to learn and understand all of the various differences and how they’re implemented. As I was going through this, I figured that others might benefit by seeing the underlying details of how OAuth2 really works and how each provider does things.
If you’re not really a Flutter/Dart developer, but really want to see a full implementation of OAuth2, this demonstrator will give you all that detail. The combination of the readme files, and the comments in the (server) code base should make it relatively easy for any developer to follow the flow even if you’re not a Dart developer.
In the end, I got the OAuth2 flow to work across four providers and I tested it to run on iOS, Android, Mac, Windows and Linux. I met my objective. I’d love to hear from OAuth2 experts out there to tell me the things I did wrong (or I could have done better). Also, if anyone wants to implement yet another provider (Twitter’s OAuth2 is also a little quirky), I’d love the see what you do to make it work. With the pandemic coming to an end (we hope), I hope to travel more and code less. But, maybe I’ll come up with something else to work on during some of the plane rides.
I really hope this demonstrator helps a few people out there either learn how to implement a few interesting Dart features, or a bit more about the underpinnings of OAuth2. If you get something out of this, I’d love to hear from you.