riverrun / openmaize Goto Github PK
View Code? Open in Web Editor NEWNo longer maintained - was an Authentication library for Plug-based applications in Elixir
License: Other
No longer maintained - was an Authentication library for Plug-based applications in Elixir
License: Other
This issue is to discuss adding an option to use sessions for authentication instead of JWTs.
At the moment, Openmaize uses JSON Web Tokens for authentication. An alternative method of authenticating users is to use a more traditional cookie-based approach. Many users coming from Ruby / Rails will probably be used to using sessions and might therefore prefer this approach.
I have no strong opinion on this issue - there are advantages and disadvantages to both approaches. What concerns me more is that whatever method is used is implemented correctly.
I want to implement the "remember me" option so, if a user logs in and marks a checkbox, a cookie will be written so the user does not need to log in again on new sessions for the following days.
Are there currently plans for this feature?
In general, as of 2016 it is and has been for quite some time now considered an bad practice to use usernames for authentication since they require the user to remember them for each account and sometimes the username might not even be unique. Email on the other hand have to be remembered by users anyway. not just for your particular applications, it is still needed for either account confirmation or password reset, and they are unique in the sense theoretically only one user can use one email.
Most libraries and tutorials I've seen have taken notice of this fact and don't require usernames at all, also most modern sites/apps don't requie usernames, just emails( facebool, google etc, github is just an exception that confirms the rull)
So I believe Openmaize should either default to using email instead of usernames or it's documentation should provide a easy set of steps to configure it to do so.
Building under Ubuntu 14.04 with build-essentials and elixir-dev installed.
Error log:
Running dependency resolution
All dependencies up to date
==> openmaize
Compiled lib/openmaize.ex
Compiled lib/openmaize/config.ex
Compiled lib/openmaize/signup.ex
Compiled lib/openmaize/plugs/loginout_check.ex
Compiled lib/openmaize/report.ex
Compiled lib/openmaize/plugs/id_check.ex
Compiled lib/openmaize/token_config.ex
== Compilation error on file lib/openmaize/plugs/authorize.ex ==
** (CompileError) lib/openmaize/plugs/authorize.ex:75: function full_path/1 undefined
(stdlib) lists.erl:1337: :lists.foreach/2
(stdlib) erl_eval.erl:669: :erl_eval.do_apply/6
could not compile dependency openmaize, mix compile failed. You can recompile this dependency with `mix deps.compile openmaize` or update it with `mix deps.update openmaize`
Deps:
defp deps do
[{:phoenix, "~> 0.15"},
{:phoenix_ecto, "~> 0.8"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "~> 1.4"},
{:phoenix_live_reload, "~> 0.5", only: :dev},
{:cowboy, "~> 1.0"},
{:openmaize, git: "https://github.com/elixircnx/openmaize.git"}]
end
Is it possible to use email instead of name?
Hey Riverrun,
First off, awesome package. The structure is easy to understand and integrate. I appreciate the good work. I am looking for some help. I am using RethinkDB with Phoenix and trying to use Openmaize. I got the signup working using RethinkDB-elixir and RethinkDB-ecto from hamiltonp which are some awesome packages as well. But, I am having trouble getting the login to work. The issue happens whenever the process hits the check_user function. I need to change out the SQL query for RethinkDB and change the other pipes to reflect this. I think there are some issues when it hits |> Config.repo.one
In the config, I have the repo set as: Appname.RethinkDB
I have a module called Appname.RethinDB using RethinkDB.Ecto.Connection that handles the dirty work. Not all Ecto operations are supported, so I have to import RethinkDB.Query and use it for any queries instead of Ecto. So, I have to track down any areas of Openmaize that use Ecto queries (not insert, delete, or other basic CRUD actions as those are supported by the Ecto shim). I know this may not be enough, but is there any advice you can give me to swap out Postgres Ecto queries for RethinkDB? Thanks!!
At https://github.com/elixircnx/openmaize/blob/master/lib/openmaize/token/create.ex#L33, there's:
`user` is a map containing the user information, which needs to contain
values for `id`, `name`, `role`, `nbf_delay`, which is the number of minutes <<<<====
in the future after which the token can be used, and `token_validity`, which
is the number of minutes that the token will be valid for.
"""
def generate_token(user, {nbf_delay, token_validity}) do
nbf = get_nbf(nbf_delay * 60_000)
Map.take(user, [:id, :name, :role]) <<<<<====
|> Map.merge(%{nbf: nbf, exp: get_expiry(nbf, token_validity * 60_000)})
|> encode(Config.get_token_alg)
end
Elsewhere, :name
is optional if you change the unique key with:
config :openmaize,
unique_id: "login",
...
Probably doesn't matter, given the variation in the other keys, but I thought I'd mention it.
Hi there! First, thanks for openmaize, which I'm starting to use to achieve authentication against an existing Rails/devise database (gradual rewrite of app from Rails to Phoenix).
It took me a bit of time to figure this out so I thought I'd share it here - maybe this is worth adding to the readme (e.g. "migrating from Rails & devise" section), since I suspect more people will do this in the upcoming months.
The first obvious steps to get this working were in the config:
config :openmaize,
# matches devise db convention
hash_name: :encrypted_password
and in my controller:
plug Openmaize.Login, [
db_module: MyApp.OpenmaizeEcto,
# matches devise db convention
unique_id: :email
] when action in [:login_user]
That was the easy part; the harder one was around the role
column.
The database users
table hasn't got a role
column in devise (at least not by default). Initially I just tweaked the code in web/controllers/authorize/ to fix pattern matching against
role(which didn't work), but
current_userwasn't set after that. I dig into openmaize-jwt and ended up seeing that because the
role` key was missing, I got an "incomplete token" error.
Ultimately I used a virtual field with a default value for role
, which seems to work fine:
schema "users" do
field :email, :string
# snip
field :encrypted_password, :string
timestamps inserted_at: :created_at
# this seems to work nicely
field :role, :string, virtual: true, default: "user"
end
Hope this helps others :-)
Rather surprised this is completely left up to the consumer of the library rather than providing a basic example. Greatly appreciate something quick to base off of and I'm pretty sure this would go a long way with other new users of the library.
Hi!
Thanks for this great project! This is rather a question than an issue but I didn't know where to ask it. What I would like to do is restricting editing of a user to the admin (in any case) and to the user itself (but not other users). I found plug :authorize_id for the latter but how can I express that this should only be applied if the user has the role "user" and if it's an "admin" then the check should not be in place...?
How can you combine those two anyways? I couldn't find it in the docs nor in the example project.
Marius
Hi David,
I've noticed that the priv/templates/phoenixauth/user_migration.exs
used by the generator, lacks some of the fields (:otp_required
, :otp_secret
, :role
and :remember
) used by the "advanced" openmaize version.
It is just an oversight or an intended behavior? Are we supposed to add them by hand to the project, or we may safely enhance the generator so to speedup the project setup?
It would be great if generators could be added for common features e.g. generate schemas, controllers etc and basic user CRUD. These are stuff that's pretty much needed in any web application and it is much easier to have them generated instead of copying and pasting them from the demo phoenix app.
Is it possible to invalidate tokens when a user logs out?
It would be nice if we could add the db_module
to the config once, instead of adding it to every plug etc.
config :openmaize,
db_module: Welcome.OpenmaizeEcto
Is there any reason against it?
Edit: Same for unique_id
After much thought, I've come to the conclusion that the redirects option does not really belong within Openmaize as an authentication framework. The responsibility for redirects should be handled by the web framework that the developer is using.
Work is continuing on this in the noredirects
branch.
Change "password_hash" field name in scheme through config
Currently openmaize forces you to use the "name" field in User model for Authentication, but I think by a having a additional config parameter (defaulted to name, so it maintains its' current usability) but that might add easier adoption for existing systems, that use email, or username fields as login method.
Any ability to login as any user right from controller?
Now that you're also discussing session/JWT may be a good time to propose/think about this feature that may be useful in several use cases and goes well with your package that handles user activity related stuff in an integrated and efficient way.
By user activity/cross-identity I mean:
I think this could be a good fit for Openmaize and another distinctive feature in the 360 degrees user identity/activity solution.
Thank you very much for your attention.
In the examples it says that the way to authorize the actions in a controller is:
def action(conn, _), do: authorize_action conn, ["user"], __MODULE__
But this would apply it to all the actions. How can we exclude some actions so no authorization is required? For example, if you have a REST resource and you want all actions authorized, except for :show
?
Or, if we wanted to authorize some actions for the user
role, and some for the admin
role in the same controller?
Thanks!
@riverrun To use openmaize in an existing project I needed to override the add_token/4
redirect as its currently wired to use the login_dir
configuration setting.
What do you think about adding a config parameter such as redirect_path
? The caveat is that any additional roles will probably need custom redirects too.
TL;DR: I have Phoenix controller tests that sometimes pass and sometimes fail. When they fail, an action that is supposed to be reached, because of an authentication token, instead redirects to /login
. This only happens when two controller tests are running. It might be a timing issue, but slowing one of the controller's tests with :timer.sleep
doesn't make the problem go away. (It does get less frequent, but it still happens even with a 30 second delay.)
I am an Elixir and Phoenix newbie, so it's probably something obvious. Using `:openmaize, "0.11.0" :phoenix, "1.0.4" with both Elixir 1.1.1 and 1.2.
In my Phoenix application, I'm using the tests here and in openmaize-phoenix
as a model. I have two controllers. Their tests share this setup code:
def authenticated() do
{:ok, user_token} = %{id: 2, login: "derp", role: "admin"} |> Token.generate_token({0, 86400})
conn()
|> put_req_cookie("access_token", user_token)
end
(However, it doesn't matter if each of them has its own variant (with different login
and role
).)
The tests look like this and this:
test "GET / when logged in", %{authenticated: conn} do
# :timer.sleep(30000)
conn = get conn, "/"
assert html_response(conn, 200)
end
test "GET / when logged in", %{authenticated: conn} do
conn = get conn, "/"
assert html_response(conn, 200)
end
The failures look like:
1) test GET / when logged in (Critter4us.AdminControllerTest)
test/controllers/admin_controller_test.exs:18
** (RuntimeError) expected response with status 200, got: 302
stacktrace:
(phoenix) lib/phoenix/test/conn_test.ex:327: Phoenix.ConnTest.response/2
(phoenix) lib/phoenix/test/conn_test.ex:341: Phoenix.ConnTest.html_response/2
test/controllers/admin_controller_test.exs:21
It can be either one that fails.
As I say, I expect this is a problem with my setup, but it might also be a real issue with openmaize.
Why is this called find_user_byid
? IMO it would be nicer if it was called find_user_by_id
. It might be changed in 1.1
.
I am working at a pretty decent sized application with phoenix and I wanted to add Authentication with OpenMaize. I was surprised when I noticed it was asking me if it should overwrite web/router.ex
and other files I've been already working on.
I believe OpenMaize should work just like Devise
works for Rails, you can install it whenever you want and if you've been working on certain files already, it should simply add just the lines of code you need without damaging initial file.
I'm trying to get Openmaize to work with Phoenix.Token for user authentication. I tried to modify authenticate.ex
in the library like this, but it doesn't seem to be called as I was expecting it.
Can you please tell me what is the right way to use Phoenix.Token with Openmaize?
defp set_current_user(user, conn) do
token = Phoenix.Token.sign(conn, "user socket", user.id)
IO.inspect(token)
conn
|> assign(:current_user, user)
|> assign(:user_token, token)
Hello, I have a phoenix application with Openmaize 0.19, where users are logged in and remembered via a cookie. It works fine, but when I restart the Heroku server, it fails with this, and I need to delete my cookies to access the site.
2016-06-16T10:34:22.299967+00:00 heroku[web.1]: State changed from starting to up
2016-06-16T10:34:28.716619+00:00 heroku[router]: at=info method=GET path="/" host=example.com request_id=b0703eeb-21cd-4147-ad26-98a52d8f0c2f fwd="..." dyno=web.1 connect=0ms service=249ms status=500 bytes=295
2016-06-16T10:34:28.528526+00:00 app[web.1]: 10:34:28.528 request_id=b0703eeb-21cd-4147-ad26-98a52d8f0c2f [info] GET /
2016-06-16T10:34:28.721654+00:00 app[web.1]: 10:34:28.721 request_id=b0703eeb-21cd-4147-ad26-98a52d8f0c2f [info] Sent 500 in 192ms
2016-06-16T10:34:28.770918+00:00 app[web.1]: 10:34:28.770 [error] #PID<0.439.0> running MyApp.Endpoint terminated
2016-06-16T10:34:28.770930+00:00 app[web.1]: Server: example.com:80 (http)
2016-06-16T10:34:28.770939+00:00 app[web.1]: Request: GET /
2016-06-16T10:34:28.770940+00:00 app[web.1]: ** (exit) an exception was raised:
2016-06-16T10:34:28.770940+00:00 app[web.1]: ** (ArgumentError) argument error
2016-06-16T10:34:28.770941+00:00 app[web.1]: :erlang.binary_to_existing_atom("email", :utf8)
2016-06-16T10:34:28.770942+00:00 app[web.1]: (poison) lib/poison/parser.ex:97: Poison.Parser.object_name/2
2016-06-16T10:34:28.770943+00:00 app[web.1]: (poison) lib/poison/parser.ex:82: Poison.Parser.object_pairs/3
2016-06-16T10:34:28.770943+00:00 app[web.1]: (poison) lib/poison/parser.ex:36: Poison.Parser.parse/2
2016-06-16T10:34:28.770944+00:00 app[web.1]: (poison) lib/poison/parser.ex:50: Poison.Parser.parse!/2
2016-06-16T10:34:28.770944+00:00 app[web.1]: (poison) lib/poison.ex:83: Poison.decode!/2
2016-06-16T10:34:28.770945+00:00 app[web.1]: (elixir) lib/enum.ex:1088: Enum."-map/2-lists^map/1-0-"/2
2016-06-16T10:34:28.770946+00:00 app[web.1]: (elixir) lib/enum.ex:1088: Enum."-map/2-lists^map/1-0-"/2
This already failed in 0.18, I mean, it does not seem related to the related changes about the "Remember me" feature.
I want to narrow the focus of Openmaize to authentication and the handling of JWTs. There are many variables involved in handling authorization, or access control, and I think it would be better to provide guidelines to the web developers rather than any authorization module.
Related to this, and #22, I'm going to work on a Mix generator for authorization using Openmaize in a Phoenix project.
After an action has been authorized with:
def action(conn, _), do: authorize_action conn, ["user"], __MODULE__
We get the user as a third param in the actions:
def index(conn, params, user) do
However, we only get some of its data:
IO.inspect user
# %{email: "[email protected]", exp: 1464787171584, id: 1, nbf: 1464779971584, role: "user"}
So we then need to get the whole user from the DB in order to be able to fetch all its data, associations, etc.
current_user = Repo.get(User, user.id)
Is that the supposed way to do this? Could Openmaize instead pass the whole User instead? Or maybe a %User{}
struct with this data, like, including the __struct__: User
key?
Hello! This seems to be the best authentication system for Elixir. It will be even better when they add support cookies. But it is very costly for those who are starting in the programming world. Some do not want to stop to understand and configure an authentication system, but to focus on building your application. There should be generators that let Openmaize ready for production. Or else a wiki that explains step by step how to set up.
Sorry if this is not the place to discuss this, and thank you for this excellent software.
Automatically translated.
This is an enhancement of #11.
Consider changing the user_email
confirmation function so that it is called by plug, something like:
plug :user_email, [mail_func: &Mailer.ask_confirm/1] when action in [:confirm]
Then have Openmaize handle the redirects, if redirects
is set to true.
Whether we decide to make this change or keep the function user_email
as it is, the email confirmation for resetting the password should be called in the same way (there shouldn't be any inconsistency).
As passwords are notoriously troublesome, it is advisable to add an additional layer to the initial authentication process.
Hey there!
When using the latest version of openmaize from hex - either in my own app or with the openmaize-phoenix-example, when I attempt to login I receive an error claiming that there's no function clause matching Openmaize.Login.call
.
Here's the stacktrace which includes the function call that was attempted:
[error] #PID<0.367.0> running Welcome.Endpoint terminated
Server: localhost:4000 (http)
Request: POST /sessions
** (exit) an exception was raised:
** (FunctionClauseError) no function clause matching in Openmaize.Login.call/2
(openmaize) lib/openmaize/login.ex:74: Openmaize.Login.call(%Plug.Conn{adapter: {Plug.Adapters.Cowboy.Conn, :...}, assigns: %{current_user: nil}, before_send: [#Function<0.7834419/1 in Plug.CSRFProtection.call/2>, #Function<4.13001795/1 in Phoenix.Controller.fetch_flash/2>, #Function<0.82590416/1 in Plug.Session.before_send/2>, #Function<1.32426848/1 in Plug.Logger.call/2>, #Function<0.78287744/1 in Phoenix.LiveReloader.before_send_inject_reloader/1>], body_params: %{"_csrf_token" => "bAQhOio5MQBxIC8AMjEHFmcbe1EdJgAA6+WWmlEKEdAzUSdP2u4hTg==", "_utf8" => "✓", "session" => %{"password" => "password", "username" => "johnhamelink"}}, cookies: %{"HFS_SID_" => "0.591043542139232", "_leasedv2_session" => "eVVsMXpML2kyemZYWk5Ka214OEtRRHpUZDVLOUpZeTVzSHJxT1RsMFowWkFpQ1grYys2b3NZVTZsYjRWMzIrd21tOWpZOWRwbW8wMHJLdmpGQVhvc1RJUnZLeEQzSlFpalIrY2xiaktVU1hJV2tXNTRyVWRDLzVFL3dKMnlGRXdsWlRqWkphL2pUYi9UYWl1MHRKTDhFakd2Tjd2WFVSdjRUK3ZRRHRGTHp6SzFtRG1pcUV1SCs2Ry9Td3lhcHFOV1BveEEwUE9MUldQQ2J1QXloZllKaU9rVDk0R1lVT2dieDdGNFZyd1FzSUhIRGJxS25IWDFmYVpac2hPa2lQQzZSRHZ5cHB2dVNOV0NUUUFXa0MreVZEVEJzMjc4aGJ6VDN4eWp6cm5DQVlqRFFBc0NHbHdlQnk4cDl1VkF0M0MwVk5NZU5SVzBmTWdROUtkNEZ0RkJYZzdrbDRaUHFLaStnZFdla3JPMG1FPS0taFpzZ1ZMSDlIejRNajRnYW5RWXBsdz09--a3d18892053b659ccc503c73d372d576266362ce", "_meditation_now_key" => "SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYU2xUVHVYWEpCRU5rOXA3aUQxRy9Gdz09.SWD_rANEn-KbjwNb3XQdOFUFw4KtW53LTubom80kLe8", "_welcome_key" => "SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYWi92bUdVdEs0RG56Z2JjRlVuTzlJQT09.4ZPb7-_QvUHDUHsljcJkZ_VQ1hMwShjrZQZNdKw_v-A", "expensifyAuthToken" => "AD99FD8049E7447E52B6C7B319C517837936CF5DA3C70B3F44402EB64E2EA0E35C12A2541069206ED591ADDB12D5E549411591D0D0E17455C6FC96BB0CE13C73343E2DFC0FF2D2AD0DDF04F018825FCFC9ECA09A17731F7CA77BB41CDA9FF1B35D3635AC63D9146455B160EFE23458EFE3DE90FD768194BCE218978E789E14FC", "gsScrollPos" => "", "undefined" => "1"}, halted: false, host: "localhost", method: "POST", owner: #PID<0.367.0>, params: %{"_csrf_token" => "bAQhOio5MQBxIC8AMjEHFmcbe1EdJgAA6+WWmlEKEdAzUSdP2u4hTg==", "_utf8" => "✓", "session" => %{"password" => "password", "username" => "johnhamelink"}}, path_info: ["sessions"], peer: {{127, 0, 0, 1}, 36392}, port: 4000, private: %{Welcome.Router => {[], %{}}, :phoenix_action => :create, :phoenix_controller => Welcome.SessionController, :phoenix_endpoint => Welcome.Endpoint, :phoenix_flash => %{}, :phoenix_format => "html", :phoenix_layout => {Welcome.LayoutView, :app}, :phoenix_pipelines => [:browser], :phoenix_route => #Function<10.116680344/1 in Welcome.Router.match_route/4>, :phoenix_router => Welcome.Router, :phoenix_view => Welcome.SessionView, :plug_session => %{"_csrf_token" => "Z/vmGUtK4DnzgbcFUnO9IA=="}, :plug_session_fetch => :done}, query_params: %{}, query_string: "", remote_ip: {127, 0, 0, 1}, req_cookies: %{"HFS_SID_" => "0.591043542139232", "_leasedv2_session" => "eVVsMXpML2kyemZYWk5Ka214OEtRRHpUZDVLOUpZeTVzSHJxT1RsMFowWkFpQ1grYys2b3NZVTZsYjRWMzIrd21tOWpZOWRwbW8wMHJLdmpGQVhvc1RJUnZLeEQzSlFpalIrY2xiaktVU1hJV2tXNTRyVWRDLzVFL3dKMnlGRXdsWlRqWkphL2pUYi9UYWl1MHRKTDhFakd2Tjd2WFVSdjRUK3ZRRHRGTHp6SzFtRG1pcUV1SCs2Ry9Td3lhcHFOV1BveEEwUE9MUldQQ2J1QXloZllKaU9rVDk0R1lVT2dieDdGNFZyd1FzSUhIRGJxS25IWDFmYVpac2hPa2lQQzZSRHZ5cHB2dVNOV0NUUUFXa0MreVZEVEJzMjc4aGJ6VDN4eWp6cm5DQVlqRFFBc0NHbHdlQnk4cDl1VkF0M0MwVk5NZU5SVzBmTWdROUtkNEZ0RkJYZzdrbDRaUHFLaStnZFdla3JPMG1FPS0taFpzZ1ZMSDlIejRNajRnYW5RWXBsdz09--a3d18892053b659ccc503c73d372d576266362ce", "_meditation_now_key" => "SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYU2xUVHVYWEpCRU5rOXA3aUQxRy9Gdz09.SWD_rANEn-KbjwNb3XQdOFUFw4KtW53LTubom80kLe8", "_welcome_key" => "SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYWi92bUdVdEs0RG56Z2JjRlVuTzlJQT09.4ZPb7-_QvUHDUHsljcJkZ_VQ1hMwShjrZQZNdKw_v-A", "expensifyAuthToken" => "AD99FD8049E7447E52B6C7B319C517837936CF5DA3C70B3F44402EB64E2EA0E35C12A2541069206ED591ADDB12D5E549411591D0D0E17455C6FC96BB0CE13C73343E2DFC0FF2D2AD0DDF04F018825FCFC9ECA09A17731F7CA77BB41CDA9FF1B35D3635AC63D9146455B160EFE23458EFE3DE90FD768194BCE218978E789E14FC", "gsScrollPos" => "", "undefined" => "1"}, req_headers: [{"host", "localhost:4000"}, {"connection", "keep-alive"}, {"content-length", "158"}, {"cache-control", "max-age=0"}, {"origin", "http://localhost:4000"}, {"upgrade-insecure-requests", "1"}, {"user-agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36"}, {"content-type", "application/x-www-form-urlencoded"}, {"accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"}, {"dnt", "1"}, {"referer", "http://localhost:4000/sessions/new"}, {"accept-encoding", "gzip, deflate"}, {"accept-language", "en-GB,en;q=0.8,en-US;q=0.6"}, {"cookie", "_leasedv2_session=eVVsMXpML2kyemZYWk5Ka214OEtRRHpUZDVLOUpZeTVzSHJxT1RsMFowWkFpQ1grYys2b3NZVTZsYjRWMzIrd21tOWpZOWRwbW8wMHJLdmpGQVhvc1RJUnZLeEQzSlFpalIrY2xiaktVU1hJV2tXNTRyVWRDLzVFL3dKMnlGRXdsWlRqWkphL2pUYi9UYWl1MHRKTDhFakd2Tjd2WFVSdjRUK3ZRRHRGTHp6SzFtRG1pcUV1SCs2Ry9Td3lhcHFOV1BveEEwUE9MUldQQ2J1QXloZllKaU9rVDk0R1lVT2dieDdGNFZyd1FzSUhIRGJxS25IWDFmYVpac2hPa2lQQzZSRHZ5cHB2dVNOV0NUUUFXa0MreVZEVEJzMjc4aGJ6VDN4eWp6cm5DQVlqRFFBc0NHbHdlQnk4cDl1VkF0M0MwVk5NZU5SVzBmTWdROUtkNEZ0RkJYZzdrbDRaUHFLaStnZFdla3JPMG1FPS0taFpzZ1ZMSDlIejRNajRnYW5RWXBsdz09--a3d18892053b659ccc503c73d372d576266362ce; undefined=1; HFS_SID_=0.591043542139232; expensifyAuthToken=AD99FD8049E7447E52B6C7B319C517837936CF5DA3C70B3F44402EB64E2EA0E35C12A2541069206ED591ADDB12D5E549411591D0D0E17455C6FC96BB0CE13C73343E2DFC0FF2D2AD0DDF04F018825FCFC9ECA09A17731F7CA77BB41CDA9FF1B35D3635AC63D9146455B160EFE23458EFE3DE90FD768194BCE218978E789E14FC; gsScrollPos=; _meditation_now_key=SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYU2xUVHVYWEpCRU5rOXA3aUQxRy9Gdz09.SWD_rANEn-KbjwNb3XQdOFUFw4KtW53LTubom80kLe8; _welcome_key=SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYWi92bUdVdEs0RG56Z2JjRlVuTzlJQT09.4ZPb7-_QvUHDUHsljcJkZ_VQ1hMwShjrZQZNdKw_v-A"}], request_path: "/sessions", resp_body: nil, resp_cookies: %{}, resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}, {"x-request-id", "r346e80o59o0q8lfldi5idsnckpnrihr"}, {"x-frame-options", "SAMEORIGIN"}, {"x-xss-protection", "1; mode=block"}, {"x-content-type-options", "nosniff"}], scheme: :http, script_name: [], secret_key_base: "NWubAA15egYxOBxjxQnkfHvUFus7nEanYQNWq0O+NKA1J+NcrhovPv/fUBh3RdMk", state: :unset, status: nil}, {Welcome.OpenmaizeEcto, :username})
(welcome) web/controllers/session_controller.ex:1: Welcome.SessionController.phoenix_controller_pipeline/2
(welcome) lib/welcome/endpoint.ex:1: Welcome.Endpoint.instrument/4
(welcome) lib/phoenix/router.ex:261: Welcome.Router.dispatch/2
(welcome) web/router.ex:1: Welcome.Router.do_call/2
(welcome) lib/welcome/endpoint.ex:1: Welcome.Endpoint.phoenix_pipeline/1
(welcome) lib/plug/debugger.ex:123: Welcome.Endpoint."call (overridable 3)"/2
(welcome) lib/welcome/endpoint.ex:1: Welcome.Endpoint.call/2
(plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
(cowboy) src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
At the moment, there is no OTP update function in the database behaviour or the openmaize_ecto
generated file. We need to add one for the following reasons:
otp_last
value and validating the token.One solution is to add an update function to the database behaviour and the openmaize_ecto
file, and in this function use a lock to prevent any other user making a similar query at the same time.
It would be great if a confirmation email feature can be added
NotQwerty123 provides a good service to check password strength, but this is a service that would be better performed by a front-end service, such as zxcvbn.
A good front-end service is more user-friendly, and this has a direct effect on security because it encourages users to comply with password policies.
openmaize/plugs/authenticate.ex:56
if i set config.repo and config.user_model, why not just assign current_user with ecto struct? like
defp set_current_user({:ok, data}, conn) do
case !!(Config.repo && Config.user_model) do
true ->
current_user = Config.repo.get(Config.user_model, data.id)
assign(conn, :current_user, current_user)
_ ->
assign(conn, :current_user, data)
end
end
if ok ,i can PR with test
btw, need travis config?
When a user signs up using an email that includes a plus sign (like [email protected]), the password confirmation link fails - when it looks for the user on the DB, it removes the plus sign:
[info] GET /confirm
[debug] Processing by Rocket.PageController.confirm/2
Parameters: %{"email" => "[email protected]", "key" => "2W07KNzO30VAnocM..."}
Pipelines: [:browser]
[debug] SELECT u0."id", u0."name", u0."email", u0."password_hash", u0."role", u0."confirmed_at", u0."confirmation_token", u0."confirmation_sent_at", u0."reset_token", u0."reset_sent_at", u0."inserted_at", u0."updated_at" FROM "users" AS u0 WHERE (u0."email" = $1) ["jaimeiniesta [email protected]"] OK query=13.1ms queue=0.2ms
[info] Sent 302 in 15ms
[debug] Rocket.PageController halted in :action/2
[info] GET /login
[debug] Processing by Rocket.PageController.login/2
Parameters: %{}
Pipelines: [:browser]
[info] Sent 200 in 7ms
As the title says, I'm quite a newbie in Phoenix / Elixir. How would you proceed on creating the functionality which verifies the confirmation link that is sent by ask_confirm
? I am not looking for a full-fledged tutorial, but a small top-level explanation.
I imagine you could have a function which is associated with a route that is supposed to receive the link and then add the current date to :confirmed_at
? Would it be a good idea to add a confirmed
boolean to the User schema and then switch the boolean to true when the user accesses the link sent in the email?
Thanks in advance!
At the moment, mix openmaize.gen.phoenixauth
has a --no-html
option, but this does not generate all the necessary files to get started with an api.
Depending on the outcome of this issue, we need to generate files that either use OpenmaizeJWT or Phoenix.Token.
I just noticed that with deployment, or a restart, the session is no longer valid. Any insights would be helpful here.
Is it possible? In dev it's a pain when every app restart it leads to user logout. For production all users are kicked on app/vm restart
By making the generators do more work, it should be a lot easier to get a site up and running.
Work on this is in progress on the update_generators
branch.
Enhancement proposal for AcessControl:
Will it be possible to do something like:
plug :authorize, roles: ["admin", user: when action in [:index, :show] ]
making explicit for the Access Control that in that controller, admin has privileges to do all operations but user can only do index, or show?
Hey David,
I am trying to configure the redirects that occur upon a successful login and registration. For context, my app has user profiles. When they first register, I want them redirected to http://app/profiles/new so they can initially create their profile. But, once they create it, when they log in, I want them redirected to their specific profile page as in http://app/profiles/show/:id. I see that I can configure basic redirects such as "admin" => "/admin", but I need more customization in where users are redirected to. I guess I could configure a basic redirect, then have that route redirect again to the profile page, but I wanted to see if you knew an easier way this could be done within the config.exs file.
The initial reason for having the database calls in the developer's project, instead of in the Openmaize library, was to accommodate people who were not using Ecto - specifically users of RethinkDB. This adds a layer of complexity that I would like to remove, and as RethinkDB is no more and has ceased to be, I think we can make Ecto a hard dependency (no longer optional).
Work on this is in progress on the force_ecto
branch.
I'm trying to use Openmaize 0.17 for building an Elixir API, and got my session controller set up with plug Openmaize.Login, [storage: nil, unique_id: :email] when action in [:create]
. This correctly returns an access_token
when logging in with a valid email and password.
If I try to use this token for subsequent requests to routes piped through plug Openmaize.Authenticate
in an Authorization-Header formatted Bearer <token>
I get a 401 Unauthorized, and further research shows that Openmaize.JWT.Verify.check_sign
fails.
Creating and verifying a token in iex -S mix
works perfectly. Is there something else to configure when using Openmaize.Login
to create a token?
Hi @riverrun
Thanks a lot for great yet simple lib :)
I have an question, how I can restrict some controller/routes only for authenticated user?
Maybe something like this?
defmodule MyAwesomeApp.PageController do
use Phoenix.Controller
plug Openmaize.Authenticated when action != :index
# ...
end
Thank you in advance for any help you can provide :)
Regards
I’m using the "confirmation email after signup" functionality similar to the one in the openmaize-phoenix example app with using the ConfirmEmail plug in my controller.
plug Openmaize.ConfirmEmail, [key_expires_after: 30] when action in [:confirm]
It looks like the confirmation link can be requested multiple times and always updates the user’s confirmed_at
timestamp.
Is this expected behaviour, or should there be a check and an error message (sth. like "Your account is already confirmed") once the email was confirmed? Or is this something I would have to care about explicitly? If, what would be a good approach to do this check?
At the moment, logging in requires that the developer state which identifier, such as email or username, is used. Add support for allowing end users to have a choice of input, such as "phone or email" or "email or username".
When user values are being assigned in the conn, it is being set as a vanilla map instead of a user struct, which will throw errors when invoking certain functions within Phoenix. For example, if you change a new action to also take the user as an argument, then in your pipeline you use |> build_assoc(:relationship) so that the form and creation are built using the current user id. Then, call whatever_path(conn, :new) in a template, you will error out because of the build_assoc function is not receiving the correct values in the conn. Ecto.build_assoc(%{id: 5, role: "user", username: "john"}, :User_profile, %{})
and it should be Ecto.build_assoc(%User{id: 5, role: "user", username: "john"}, :User_profile, %{})
According to Chris Mccord, you can convert it to a %User{} by doing struct(User, the_map)
You can see in the stack trace where the error is: https://gist.github.com/iovative/9d374f092faed74a2f9c
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.