It’s almost 2am and I’m sleepy, but I wanted to write this down while it’s relatively fresh in my mind.

I’ve been playing around with user authentication in Go.

While actual user interaction is not the primary part of the simulation and will not be the focus in the Go rewrite as I said in my previous post, there will need to be a few basic actions that a user will take before leaving the rest of the simulation to do its thing. This is why I mentioned implementing a very basic CLI to interact with the simulation earlier. The user will basically just need to sign up, log in, set some basic options for their snail stable (like the stable name and location), capture a snail or two, and leave them to do their thing from there. It is kind of like norn Wolfling runs in Creatures 3 - you have to hatch some norns before you let nature take its course.

Design differences from the PHP version

The main difference from the way the concept of users is currently implemented in the PHP version of SnailLife is this: users will no longer be considered synonymous with owners. In the PHP version of SnailLife, users and owners are just one table - account details, moderator/BrainHub management access fields, and stable information are all stored in one location. In my opinion this isn’t the best approach. A user of the snail simulation will not neccessarily need to be an owner of a stable or of any snails. This is especially true considering I’m building this thing with multiple possible applications in mind.

Approach

I haven’t worked much with authentication systems before - the PHP version of the app made use of the authentication features that came with Laravel. So this is largely going to be a matter of trial and error. The commit with the rough first stage of this can be found here. Here are the highlights:

  • For the Go rewrite I am thinking of using Auth0.
  • I suspect I may need different auth approaches for web and cli authentication, and my first thought is to separate these into plugins. I have added a client type enum to the Application struct that is populated on app init. If the application is of type CLI, the CLI authentication plugin will be loaded. If it is of type Web, the web authentication plugin will be loaded (but I am only implementing the CLI version for now).
  • The CLI plugin is built like this: go build -buildmode=plugin -o cli.so, and the authorizer then imports cli.so (or web.so, which is currently not built)
  • The plugin could potentially have multiple possible providers, but right now I am only implementing Auth0 - each provider is to implement the Provider interface defined outside of the plugin in the auth package.
  • I have added an auth.json to the conf directory (in gitignore of course), and also added a separate credentials generator for auth0 testing (also gitignored).
  • So far I have a registration and login test implemented - the test generates a random username (email) and password each run to test registration and login.
  • Authentication package structure is currently as follows:
auth
├── authenticator.go
├── auth.go
├── cli
│   ├── auth0
│   │   ├── auth0.go
│   │   └── tests
│   │       ├── auth0_test.go
│   │       └── config_test.go
│   ├── cli.go
│   └── cli.so
├── provider.go
└── web