AuthPipe -> an experiment in authentication

I just pushed the start of a little experiment in authentication: AuthPipe

Up until now, I’ve used Ueberauth in projects, and made a toy with Coherence to try it out … but nothing really “clicked” with me, to be honest. Ueberauth is amazingly capable, but when I just want to do local authentication using Ecto it is a little “messy”. It also doesn’t provide a built-in path that I could see to do things like 2FA/MFA, etc.

I have done auth over websockets with Ueberauth, but found I wasn’t really using Ueberauth much in those cases other than for a couple of convenience methods.

Also, I have this personal itch to scratch: I’d like to have MFA on my mail (and other) servers that don’t natively provide anything of the sort because they are from the digital stone age. :wink:

Finally, I wanted something as easy as Plug. Specifically I want to be able to do something like:

defmodule AuthDef do
  use AuthPipe

  auth_stage :session_token, required: false
  auth_stage :captcha
  auth_stage :password, implicit: true
end

… and be done! I want to be able those definitions to be usable over raw TCP, websockets or HTTP; I want to change up those pipelines at will; and I want to be able to re-use the code behind the stages as much as possible.

On the other hand, while I don’t want to write mechanics to active accounts via email (i.e.), I also don’t want a framework that injects HTML forms or other UI into my projects. I want something purely data-centric, leaving the front-ends to each aplpication. It won’t always be HTML, after all … I have mobile and desktop apps to worry about as well, and I do use different HTML/JS frameworks between projects. There is no one-sized fits all there, even if the data being passed around is identical.

On that note, I also wanted something where the client could negotiate with the server as to what challenges it can accept and which not, and for the authentication pipeline to accept that negotiation or not. This will allow me to hook up my stupid IMAP server to it, as well as offer different features between web/mobile/desktop apps.

But still simple. Yes, I want it all! The moon and the stars!

Therefore AuthPipe … I have gotten the core sketch of the infrastructure more or less completed, as you can see in the tests. It’s an amazingly small amount of code, really. Next I will begin implementing some actual authentication stages, starting with a passwords-via-Ecto one.

Things will certainly change between now and the weeks to come, that’s how it goes, but I’m relatively happy with the general design sketch. So, in the spirit of release-early/release-often, I thought I’d put this out there now, despite being still firmly in experimental stages, for your feedback and thoughts should you have any. Code is also more than welcome, though at this stage be prepared for an infinite number of paper cuts :slight_smile:

16 Likes

Sounds similar to what I’ve wanted for authentication but not got around to messing with yet (I’ve been using Ueberauth and noticed the same things about it as you). I’ll be keeping an eye on this. :slight_smile:

1 Like

This sounds really good. For me this is the missing “core” 3rd party library for Phoenix.
On top of your ideas, I would suggest a focus on always having it updated with a special attention to new issues; please don’t let that list grow too much, otherwise it wouldn’t be seen a a bullet proof authentication system, which is key.
Hope you succeed!

1 Like

100% agreed. I’ll be using it and relying on it as well, and have maintained large and security-sensitive open source code bases before, so will do my best. Though as they say: many eyes makes bugs shallow … which is rubbish … it’s many fingers :wink:

3 Likes

This sounds great Aaron :023:

I’d actually love to see a good solid foundation for auth built-in to Phoenix, even if you have to specify you want it included on project creation.

Having a built-in system makes it easier for library authors to make use of it and help create a more unified ecosystem. When the Volt framework first announced it was including auth as standard lots of people thought it was a great move…

2 Likes

I agree; the challenge is making That Thing Which Can Be Universal™. I don’t know if AuthPipe will ever mature into something that could challenge for such a position, but something that can would be great. At least for my own “itch”, I just want something that is flexible, can be shaped differently for different applications, and which feels like it is part of the “family” of Phoenix, Plug, Ecto, etc. rather than a port of some popular project written in another language / for a different framework.

We’ll see how far I get … :slight_smile:

2 Likes

Had some time in between other things today to see how much work it would be to get the SQL-backed stage. Including a migration to setup the database and a mix task to make that happen for you, it cloc’s in at 99 lines all together. In addition to authentication, it supports setting up an account for password auth, updating passwords, lock/unlock, and removal … and it’s completely reusable, just needs an Ecto repo passed to it:

defmodule AuthDef do
  use AuthPipe
  auth_stage :ecto_password, implicit: true, repo: Authlab.Repo
end

(Authlab is a small phoenix app I’m using to see how it integrates in practice …)

That result has encouraged me to keep motoring along, as I think the design is, at least in the broad strokes, probably ok. I’m about to move on to proper Plug integration and injection of application specifics (e.g. email templates and sending, web endpoints …)

Don’t worry -> I won’t be updating this thread with every day’s progress, as fun as that might be for me :stuck_out_tongue: … but just wanted to share that things have moved into the realm of almost actually useful, and that I have a clearer idea of what lays ahead now. Which is to say my kanban board has become full(er). Huzzah!

See you at the first release …

6 Likes

One of the best readings one can have in a library to understand why we have what we have today is the Changelog.
Better only periodic relevant Posts entries with the insights behind it…:slight_smile:

Can this be integrated with Coherence? The boring part of authentication for a web app is not setting a token in the request, it’s handling user registration, confirmation, password reset, forgotten password, etc. That’s veeery boring and having Coherence do that for me is something I wouldn’t want to give up.

I don’t plan on adding UI (I think that is up to the application to provide), but the business logic of all of these things will be available in AuthPipe. Then you can “just” lay your UI on top of that.

Well, with the exception of user registration. It can already handle new user registration, but only the authentication surface. AuthPipe does not, and will not, try and tell you what information should be in your user accounts. Though … I suppose … one could write an AuthPipe.Stage that does that. I just don’t plan on writing that myself, as “what is a user account?” is, IME, a bit too application-specific to belong in a generic framework.

Happy to be convinced otherwise, though! :slight_smile:

2 Likes

As soon as I get to a 0.01-suitable candidate (e.g. first unstable release for publishing on hex.pm), a CHANGELOG will certainly be added to the repo.

Yes, I don’t think UI should be there. For example, if one’s use AJAX for authentication, having server rendered pages don’t work and it would only pollute the library.
This is not to say that UI is not an important part of authentication.
But that should be handled with a few good blog posts with examples of using it. One example with a traditional server-rendered page, another with AJAX, other with two-factor authentication and even other with OAuth.
That’s why, I think the library itself should be very solid, clean, intuitive, but then, the other half are good blog posts, more than just code examples that newbies can copy but don’t understand 100%.
When the time is right I’m willing to contribute with a post about AJAX UI.

Good, you don’t want it to become a bloated monster like Devise in Ruby (sorry José & Plataformatec!).

Completely agree with you, and:

I’ll definitely be posting again to the forums when the library reaches that point, and it would be awesome to work with you on that AJAX UI post!

For user facing apps that have some common needs like the ones I’ve outlined above, a bloated monster is very convenient.

Yes, but I tend to define some components that I can reuse in my projects, meaning that I create them only once in my templates (you can use pre-defined code form a blog that you can customise to your needs) and then render them where I want, as simple as:

<%= render MyApp.Web.ModuleView, "login.html",
      option1: ""/nil, option2: ""/nil, option3: ""/nil
%>

This code is what I need instead of using generators (off course after creating first my component).
I use this pattern very effectively with Phoenix and I’m enjoying a lot to customise my own UI components and modules, because that way I can create a catalog of reusable modules/components and instantiate them very, very fast, and it’s my code, that I understand and when I have to change it latter, it’s a breeze.
I can illustrate this latter if it’s useful.

I can see the desire for a “batteries included” UI layer; perhaps the best way to get there will be to create a separate library that can be added to a project’s mix deps which provides those UI parts (generators, templates, etc).

This will allow those who need/want just the business logic not to be weighed down by those UI parts, and those who want those UI parts to easily get at them. This would further allow different sets of UI components to be created.

Personally, I’m using vue.js a fair amount these days, and I will probably adapt some vue.js modules I have for account sign in, creation and password reset to use AuthPipe, and that could easily become a library on its own with some generators to allow for customization. (Or maybe not and it becomes an npm module?) But then other libraries using .eex templates, elm, react, or whatever else could also be made available by those who are interested in those techniques.

This of course implies that the public API of AuthPipe remains stable, otherwise chaos will ensue, but seeing as that is really just one module’s set of public functions, that should be quite easy to accomplish.

That should give everyone a path to what they want, and no more. What do you think?

9 Likes

That would be … what the Phoenix ecosystem is waiting :slight_smile:
Everyone would be served.

Hear hear, definitely never include UI parts, that is the job for other things, this should just be pipes. ^.^

2 Likes