Yeah, I also feel that a nice default authentification implementation would improve onboarding big time, but I doubt it needing to be part of phoenix itself. And the difference to routing/templating is, that there are existing go to projects handling that. Plug does have a router, Eex is part of Elixir. It would be a waist to not use them.
I know this is a beaten subject, and I’ve been trying to avoid it in the hope that a “standard” package would emerge for Phoenix authentication, but I need to add authn/authz to a web application (not only an API) and I would like to know the current state of affairs.
From the last messages on this thread it seems that “coherence” is the most widely used module. Does anyone know if it provides the following features?
- Login page
- User registration page
- Password recovery method
- Decorator that redirects to login page if not authenticated, exposes user info otherwise
- Decorator to protect an API endpoint
- OAuth2 provider support (this is a stretch, maybe I’ll have to use Authable)
Coherence for me, sadly, is entirely untenable as it only supplies an internal registration. It has no support for external directories, no support for oauth (they are talking of it, but nothing yet), and its methods of injecting its views are a little different than usual phoenix’y stuff. ^.^
I currently just use ueberauth as it handles all login types fine, but it does not have any views or back-end handling (including nothing like the features you listed), however those tend not to be hard to make, just needs a library (and I’d still not opt for automatic login/registration page handling). I had been playing with an idea to wrap uberauth in a coherence-like thing that handles all styles via protocol dispatch (and a default case the user could depend on as well for a stock coherence-like style), but I’d also like to do more traditionally phoenix style view handling in it instead of using a host of generators, or not do views at all (maybe just some callback functions for form generation or so). Maybe when I get some free time again later, but for now I am too busy. ^.^;
I saw a project that started recently named curator.
It imitates devise features and adds hooks for additional features like coherence.
Any opinions on it?
Login page - yes
User registration page - yes
Password recovery method - yes
Decorator that redirects to login page if not authenticated, exposes user info otherwise - yes
Decorator to protect an API endpoint - not out of the box
Permissions - No, by design. Authorization is a separate concern from Authentication IMHO
OAuth2 provider support (this is a stretch, maybe I’ll have to use Authable) - not yet.
Let me know if you have any more questions about coherence.
@OvermindDL1 what do you mean by "its methods of injecting its view are little different that usual phoenix stuff? Would love the feedback…
Just things I spoke to you about the time that you started it, you have your reasons for that style, I just find it difficult to work with comparatively.
A few things are an enforced user schema style, id/password only, the authorization aspect is very lacking (and at least in my projects those were some of the huge parts that needed to get done ‘right’), etc… Plus the fact it injects code all around instead of being used more like a library, instead of being a part of the project you use it becomes a thing that you have to work inside of. This is probably quite normal for the Ruby crowd (which I am not), but it is very much not normal for the Functional crowd.
Hum, are you working on an OAuth provider implementation for Coherence? Cool.
Another question. I want to persist my sessions outside the current beam vm, since I will have more than one application instance running and a user can hit any one of them. From the documentation it seems I have to implement Coherence.DbStore, is there a schema for the “Session” model that is referred in the documentation?
Also, even though the protocol is called DbStore I can store them anywhere, right? I was thinking of using Phoenix’s own session store which can be cookie based for example.
@OvermindDL1 I would love to get more details on your suggestions to improve Coherence if your willing too. We could do that here, or open a new issue on the project.
Here are some of things I would like to understand more:
- “A few things are an enforced user schema style, id/password only”. Do you mean supporting authorizing on several fields like “Email or username”? I just had that requirement and had to customize the generated controller.
- “Plus the fact it injects code all around instead of being used more like a library”. Can you give me more information here? Perhaps an example on how its done now and how you would prefer it be done.
On the authorization front, I have not yet found an Elixir solution that I’m happy with. I’ve taken a stab at this a couple of time, but have not completed anything I’m happy with.
I have a pretty strong opinion that authorization is a separate concern from authentication and that is why I have not provided anything in Coherence. With that said, I do believe that authentication is very important and would really like to have a story for people that use Coherence.
Thanks for your feedback. I really appreciate it.
The DbStore is design so it only hits the database (uses the protocol) if a session cannot be found in the Agent. So it should perform pretty well…
Well for example, I’ve built up a little thing (very much not a library, I probably should put it in one sometime though…), I have an
account schema, GUID keys, this is the base of all the users information.
From that I have an
account_google as one example, it holds the information like tokens and so forth from a google OAuth request, its primary key is a foreign key to the account primary key, always a one-to-one match and the google one cannot exist without the account one. I have a variety of other ones like this for github, steam, facebook, as well as an
account_local schema. The local one exists in only one of my systems so far (I do not even have any form of a local login for the other dozen little servers I have, oauth only for them) but it contains a login id, hashed password, and a bit of other data.
Needless to say, coherence is very much not usable for the majority of authentication purposes I’ve ever experienced.
Now in my thing I’ve built up, say, a password reset thing, simple plug in the ueberauth style, it just redirects to the proper place for a given login type (say google) or handles a local one (I confirm they are who they are based on some internal information to this company so I’ve not needed email yet, but that style would not be hard either).
I can go in to a lot more information at some other time, but I’m fairly busy at the moment, in a crunch period. ^.^
Lots and lots of examples, but the biggest one for me is the *very* specific view style it uses, basically logins via websocket, other sources, or even customizing and breaking up views in unique ways (I have a lot of little subviews all over that does not fit that style well), I have more about this in a lot more detail, but I am not in the mindset right now (my mind is in oh-god-too-much-sql mode right now, I’m making SQL queries that are many many pages in length, blehg…)
It should not necessarily have a way to do authorization, but it needs a way to let you populate your own authorizations, for example in my system I use a set of allow/deny permissions with arguments (stored as json in the database currently, eh), but in addition to those populated I get information from google and LDAP and other places to give them or deny them more permissions, so I have to get that information from the authentication layer as it can change on the fly from those systems.
Coherence could become something really really useful over time, but so far it does not meet even my minimal requirements, ignoring the advanced features that I need that I’m not even sure how to shoehorn into its current design. ^.^;
@smpallen99 To use the Session Plug I would need access to Plug.Conn, which I don’t seem to have with the DbStore protocol.
Why doesn’t the Coherence Session auth make use of the already existing Phoenix sessions? There are already several backends that it can use.
I just pushed an update to the coherence phx-1.3 branch that has support for using the latest coherence with both legacy phoenix and the new phx project structures. The work is not done yet, but there should be enough functionality to get going.
This branch now supports, what I believe, is a good Gettext implementation that allows full localization of all Coherence messages using your app’s Gettext module.
Hi, I’ve read the description of the Coherence auth project and there are seems all features which I need for my project, specifically:
password bruteforce protection
I’d like to try it out. But if I get it correctly, Coherence comes with it’s own router with own views and templates. As my project is gonna be multilingual and I plan to take the approach similar to described in the article http://code.parent.co/practical-i18n-with-phoenix-and-elixir/ where each url if it is not localized (first chunk should replicate locale ie en, uk, es, fr etc…) is redirected to the localized in accordance with browser settings and configured list of allowed languages and fallback to default language if they don’t match.
As the phoenix 1.2 is currently the stable version I’m gonna be using this.
Most of the auth examples I’ve stambled upon don’t have localization in mind.
So, the question is how well will the Coherence play with multilinqual site like that. I need register, login, restore password pages to have localized pages (with gettext) as well as confirmation emails etc… Is there an example how to do it, how many and what kind of tweaks should be done?
hello, talking about authentication with Phoenix/Elixir… there was a conference “Elixir Daze 2017” and The talk by João Moura was about what we can do to manage well this subject.
He has to attract the attention to the differences between coherence, uberauth, pot, guard and keeper (library that he is developing to work as Multi Factor Authentication), and the usage of Json Web Tokens.
here is the video link: ElixirDaze 2017- Tackling Authentication with Phoenix by João Maura
and his github repo: keeper
If it can help…
@igor I can’t see anything obvious why you should not be able to use Coherence with this approach. I would create a quick spike to to try it and flush out any potential issues.
Couple things to consider:
- Make sure the Coherence plugs come after the localization plugs
- Use the phx-1.3 branch in Coherence
- Use the
mix coherence.installtask, not the mix
If you do run into trouble, push your spike project to github so I can easily reproduce your issue.
I have tested the phx-1.3 branch with phoenix-1.3.0-rc with projects made with
mix phoenix.new. I have not tested it on pre phoenix-1.3.0 projects however.
@smpallen99 I wanted to say thanks for your quick answer, it was a big help. I got the coherence v-1.3 working nicely with the localization and phoenix-1.3, which I finally have choosen for the project. To make it work there were only router settings needed to be a little customized. In case someone can find it usefull I will leave the router code here. May be there is some not necessary stuff, for example I’m not sure about this
# Add this block scope "/" do pipe_through :protected coherence_routes :protected end
part. It is never touched because of the locale plug which redirects user before the route gets called. But compiler seems won’t generate helper path functions without it.
In general, it’s important to pay attention to the order of scopes and their namespaces because coherence needs all it’s paths to be in scopes which are not namespaced and all protected paths to go after all public paths to work properly.
defmodule MyProject.Web.Router do use MyProject.Web, :router use Coherence.Router # Add this pipeline :browser do plug :accepts, ["html"] plug :fetch_session plug :fetch_flash plug :protect_from_forgery plug :put_secure_browser_headers plug MyProject.Web.Plug.Locale, "en" plug Coherence.Authentication.Session # Add this end pipeline :protected do plug :accepts, ["html"] plug :fetch_session plug :fetch_flash plug :protect_from_forgery plug :put_secure_browser_headers plug MyProject.Web.Plug.Locale, "en" plug Coherence.Authentication.Session, protected: true # Add this end pipeline :api do plug :accepts, ["json"] end # Add this block scope "/" do pipe_through :browser coherence_routes() scope "/", MyProject.Web do get "/", PageController, :index end end # Add this block scope "/:locale", as: :locale do pipe_through :browser coherence_routes() scope "/", MyProject.Web do get "/", PageController, :index end end # Add this block scope "/" do pipe_through :protected coherence_routes :protected end # Add this block scope "/:locale", as: :locale do pipe_through :protected coherence_routes :protected scope "/", MyProject.Web do # Add protected routes below end end end
For now I have another question - what is the easyest way to provide the complex form for the anonimous user to register and at the same time create some content on the site which will be published after user confirms his account. Does the coherence provide the simple api function to be used in my controller to get the user registered and the confirmation email sent?
This block provides the routes for a logged in user. You can review the source in
Coherence.Router for more specifics.
I’m not sure if you using your own controllers, or have generated the coherence controllers. You can view the coherence controllers. For example these two lines in the Session create action are responsible for logging in a user. they could be called from the Registration controller create action.
Yeah, I see. But in my router locale plug comes to work first and redirects such paths to /:locale/… paths. For localized protected paths I have
scope "/:locale", as: :locale do pipe_through :protected coherence_routes :protected scope "/", MyProject.Web do # Add protected routes below end end
As for my second question about creating complex form for registering user and at the same time adding some content to my site, I’ve looked into coherence source, as you told me, particularly into RegistrationController and found that to register new user and send him a confirmation email there are two functions used, changeset and send_confirmation, both located in Coherence.ControllerHelpers, which do exactly what I need, thank you one more time!
Since it hasn’t been mentioned yet, how would OpenID fit into an Elixir / Phoenix Framework picture ?
There’s https://github.com/mustafaturan/shield/tree/ui that can be used as an identity provider. This could act as a separate process within an umbrella app, thus segregating user management concerns from the app’s domain.
there is also an erlang implementation of OpenID relying party https://github.com/indigo-dc/oidcc, which could be used (not sure if it’d had to be ported though ; being still a newbie in Elixir) to delegate login to a third party identity provider.
I understand this post is generic without implementation detail. What are your thoughts in terms of maintainability and security ?