Giter Site home page Giter Site logo

phoenix_token_auth's Introduction

[ProjectTalk] (http://www.projecttalk.io/boards/manukall%2Fphoenix_token_auth?utm_campaign=gh-badge&utm_medium=badge&utm_source=github)

PhoenixTokenAuth is not really maintained. I do not recommend starting a new project with it.

I'm not actively using this project at the moment. I also implmemented most of it when I just started with Elixir, so the code is not exactly great. If you want to use it, be prepared to fork the project and invest some work.

PhoenixTokenAuth

Adds token authentication to Phoenix apps using Ecto.

An example app is available at https://github.com/manukall/phoenix_token_auth_react.

Setup

You need to have a user model with at least the following schema and callback:

defmodule MyApp.User do
  use Ecto.Model

  schema "users" do
    field  :email,                       :string     # or :username
    field  :hashed_password,             :string
    field  :hashed_confirmation_token,   :string
    field  :confirmed_at,                Ecto.DateTime
    field  :hashed_password_reset_token, :string
    field  :unconfirmed_email,           :string
    field  :authentication_tokens,       {:array, :string}, default: []
  end

  @required_fields ~w(email)
  @optional_fields ~w()

  def changeset(model, params \\ :empty) do
    model
    |> cast(params, @required_fields, @optional_fields)
  end

end

Make sure that you have uniqueness constraints on the email or username columns.

Then add PhoenixTokenAuth to your Phoenix router:

defmodule MyApp.Router do
  use Phoenix.Router
  require PhoenixTokenAuth

  pipeline :authenticated do
    plug PhoenixTokenAuth.Plug
  end

  scope "/api" do
    pipe_through :api

    PhoenixTokenAuth.mount
  end

  scope "/api" do
    pipe_through :authenticated
    pipe_through :api

    resources "/messages", MessagesController
  end
end

This generates routes for sign-up and login and protects the messages resources from unauthenticated access.

The generated routes are:

method path description
POST /api/users sign up
POST /api/users/:id/confirm confirm account
POST /api/session login, will return a token as JSON
DELETE /api/session logout, invalidated the users current authentication token
POST /api/password_resets request a reset-password-email
POST /api/password_resets/reset reset a password
GET /api/account get information about the current user. at the moment this includes only the email address
PUT /api/account update the current users email or password

If you want to customize the routes, instead of

  scope "/api" do
    pipe_through :api

    PhoenixTokenAuth.mount
  end

add

  scope "/api" do
    pipe_through :api

    post  "users",                 PhoenixTokenAuth.Controllers.Users, :create
    post  "users/:id/confirm",     PhoenixTokenAuth.Controllers.Users, :confirm
    post  "sessions",              PhoenixTokenAuth.Controllers.Sessions, :create
    delete  "sessions",            PhoenixTokenAuth.Controllers.Sessions, :delete
    post  "password_resets",       PhoenixTokenAuth.Controllers.PasswordResets, :create
    post  "password_resets/reset", PhoenixTokenAuth.Controllers.PasswordResets, :reset
    get   "account",               PhoenixTokenAuth.Controllers.Account, :show
    put   "account",               PhoenixTokenAuth.Controllers.Account, :update
  end

And customize, change names/pipeline of the routes.

Inside the controller, the authenticated user is accessible inside the connections assigns:

def index(conn, _params) do
  user_id = conn.assigns.authenticated_user.id
  ...
end

Now add configuration:

# config/config.exs
config :phoenix_token_auth,
  user_model: Myapp.User,                                                              # ecto model used for authentication
  repo: Myapp.Repo,                                                                    # ecto repo
  crypto_provider: Comeonin.Bcrypt,                                                    # crypto provider for hashing passwords/tokens. see http://hexdocs.pm/comeonin/
  token_validity_in_minutes: 7 * 24 * 60,                                              # minutes from login until a token expires
  email_sender: "[email protected]",                                                   # sender address of emails sent by the app
  emailing_module: MyApp.EmailConstructor,                                             # module implementing the `PhoenixTokenAuth.MailingBehaviour` for generating emails
  mailgun_domain: "example.com",                                                       # domain of your mailgun account
  mailgun_key: "secret",                                                               # secret key of your mailgun account
  user_model_validator: {MyApp.Model, :user_validator}                                 # function receiving and returning the changeset for a user on registration and when updating the account. This is the place to run custom validations.

The secret key for signing tokens must be provided for Joken to work. You must also configure the JSON encoder for Joken to use. For using the Poison Encode function, we provide the PhoenixTokenAuth.PoisonHelper. The secret_key should be set per environment and should not be committed to the repository.

# config/config.exs
config :joken,
  json_module: PhoenixTokenAuth.PoisonHelper,
  algorithm: :HS256 # Optional. defaults to :HS256
# config/[dev|test|prod].exs
config :joken,
  # Environment specific secret key for signing tokens.
  # This should be a very long random string.
  secret_key: "very secret test key",

Usage

Signing up / Registering a new user

  • POST request to /api/users.
  • Body should be JSON encoded {user: {email: "[email protected]", password: "secret"}}.
  • This will send an email containing the confirmation token.

Signing up / Registering a new user with username

  • POST request to /api/users.
  • Body should be JSON encoded {user: {username: "usernameexample", password: "secret"}}.
  • The user will be registered and, comparing to the email implementation, already confirmed.

Confirming a user

  • POST request to /api/users/:id/confirm
  • Body should be JSON encoded {confirmation_token: "token form the email"}
  • This will mark the user as confirmed and return an authentication token as JSON: {token: "the_token"}.

Logging in

  • POST request to /api/sessions
  • Body should be JSON encoded {email: "[email protected]", password: "secret"}
  • Will return an authentication token as JSON: {token: "the_token"}

Logging in with username

  • POST request to /api/sessions
  • Body should be JSON encoded {username: "usernameexample", password: "secret"}
  • Will return an authentication token as JSON: {access_token: "the_token", token_type: "bearer", id: "recordid"}

Requesting a protected resource

  • Add a header with key Authorization and value Bearer #{token} to the request.
  • #{token} is the token from either account confirmation or logging in.

Logging out

  • DELETE request to /api/sessions
  • Just stop sending the Authorization header.

Resetting password

  • POST request to /api/password_resets
  • Body should be JSON encoded {email: "[email protected]"}
  • This will send an email as configured.
  • Once the reset token is received in the email, make a POST request to /api/password_resets/reset with body {user_id: 123, password_reset_token: "the_token_from_the_email", password: "the_new_password"}
  • This will change the users password and return an authentication token as JSON: {token: "the_token"}.

Change the current user's password

  • PUT request to /api/account
  • Body should be JSON encoded {account: {password: "newpassword"}}

Change the current user's email address

  • PUT request to /api/account
  • Body should be JSON encoded {account: {email: "[email protected]"}}
  • This will send an email containing the confirmation token.
  • The change will only be effective after the email address was confirmed.

TODO:

  • Better documentation
  • Clean up expired authentication tokens in the db
  • Merge the Joken secret_key config into the phoenix_token_auth config.
  • Custom work factor config for crypto_provider
  • Allow use of scrypt as an alternate crypto_provider
  • Example Ecto Phoenix migration, with indexes.

phoenix_token_auth's People

Contributors

alfert avatar clekstro avatar falti avatar grempe avatar joeyates avatar leeroyding avatar manukall avatar opakalex avatar pap avatar pinx avatar zerotao avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

phoenix_token_auth's Issues

Using with MySQL

Hi,

I'd like to use this library with MySQL, but MySQL doesn't support arrays. Would it kill the library if I changed the authentication_tokens column to a string? Ideally, I guess, this should be a lookup table. Thoughts?

Thanks,
Lee

Updated Module in APP: undefined function: CallRedApp.Mailer.welcome_subject/2

When I pulled the latest changes, I now get "undefined function: CallRedApp.Mailer.welcome_subject/2". Do I need to change some mail paths as I'm using the ones from the older Phoenix_token_auth sample app?

Here's what is showing up in the logs:

web/mailers/mailer.ex:1: warning: undefined behaviour function new_email_address_body/3 (for behaviour PhoenixTokenAuth.MailingBehaviour)
web/mailers/mailer.ex:1: warning: undefined behaviour function new_email_address_subject/2 (for behaviour PhoenixTokenAuth.MailingBehaviour)
web/mailers/mailer.ex:1: warning: undefined behaviour function password_reset_body/3 (for behaviour PhoenixTokenAuth.MailingBehaviour)
web/mailers/mailer.ex:1: warning: undefined behaviour function password_reset_subject/2 (for behaviour PhoenixTokenAuth.MailingBehaviour)
web/mailers/mailer.ex:1: warning: undefined behaviour function welcome_body/3 (for behaviour PhoenixTokenAuth.MailingBehaviour)
web/mailers/mailer.ex:1: warning: undefined behaviour function welcome_subject/2 (for behaviour PhoenixTokenAuth.MailingBehaviour)
web/mailers/mailer.ex:3: warning: unused alias Endpoint

It seems like these are the changes (7872e56) which require the mailers to be changes. Any suggestions would be appreciated!

Some routes changes

 defmacro mount do
    quote do
      post  "users",                 PhoenixTokenAuth.Controllers.Users, :create
      post  "users/:id/confirm",     PhoenixTokenAuth.Controllers.Users, :confirm
      post  "sessions",              PhoenixTokenAuth.Controllers.Sessions, :create
      delete  "sessions",            PhoenixTokenAuth.Controllers.Sessions, :delete
      post  "password_resets",       PhoenixTokenAuth.Controllers.PasswordResets, :create
      post  "password_resets/reset", PhoenixTokenAuth.Controllers.PasswordResets, :reset
      get   "account",               PhoenixTokenAuth.Controllers.Account, :show
      put   "account",               PhoenixTokenAuth.Controllers.Account, :update
    end
  end

I thinks, we need change some url, for example:
post "sessions" it must be post "users/sign_in"
delete "sessions" it must be 'delete' "users/sign_out"

What are you think?

Security Recommendations

Awesome job and hopefully this project will gain similar traction to the Ruby Token Gem (https://github.com/lynndylanhurley/devise_token_auth).

For security reasons:

  1. The API should update the auth token for each request, except for a 5 second buffer for batch processes (see: https://github.com/lynndylanhurley/devise_token_auth#about-token-management).
  2. Besides the token, the header should pass along the client (enables the use of multiple simultaneous sessions on different clients), expiry, and uid.
  3. Signing out will invalidate the user's authentication token for the client.

Working with ember simple auth

Hi, Thanks for the plugin.

I managed to make it work with an existing ember app.
The ember app is using simple auth with oauth2 bearer.

For it to work i had to make a few changes: In the sessions controller, something like this:

def create(conn, %{"email" => email, "password" => password}) do
    case Authenticator.authenticate(email, password) do
      {:ok, token} ->
        user_json = %{id: "1"}
        json conn, %{access_token: token, token_type: "bearer", user: user_json}

      {:error, errors} -> Util.send_error(conn, errors, 401)
    end
  end

In here seems that simple auth needs the user id in the token reply, as also access_token key, not only token.

Also, would it be possible to allow identification with username instead of email ?

Question : How the confirmation link can be a post ?

When someone clicks on a link contained into an email, it triggers a get on the server and not a post, doesn't it ? So, in the phoenix_token_auth.ex, why do we have to put a post :
# Confirm url
post "users/:id/confirm", PhoenixTokenAuth.Controllers.Users, :confirm

How can the email send something via json ? I don't get it.

Authorization JWT in socket

Plug is not works in chanel (sockets), so there is no way to do Authorization in chanels. The easiest way it's to make defp check_token public and execute in chanel controller.

Feature: Move email to background

When testing the API response time for /api/users, I'm getting anywhere between 3.5 to 5 seconds. I am assuming this is due to Mailgun, so would it be possible to have the email sent after the Phoenix Token Auth API response is sent to the client?

Phoenix 0.14 and phoenix_token_auth 0.2.0 - Error: protocol Phoenix.Param not implemented for []

I just updated Phoenix and Phoenix_token_auth but get the following error when trying to create the user via our API.

[error] #PID<0.399.0> running CallRedApp.Endpoint terminated
Server: 16c1026536f.a.passageway.io:80 (http)
Request: POST /v1/users
** (exit) an exception was raised:
    ** (Protocol.UndefinedError) protocol Phoenix.Param not implemented for []
        (phoenix) lib/phoenix/param.ex:122: Phoenix.Param.Any.to_param/1
        (call_red_app) web/router.ex:1: CallRedApp.Router.Helpers.page_path/4
        (call_red_app) web/router.ex:1: CallRedApp.Router.Helpers.page_url/4
        (call_red_app) web/mailers/mailer.ex:10: CallRedApp.Mailer.welcome_body/2
        lib/phoenix_token_auth/mailer.ex:30: PhoenixTokenAuth.Mailer.send_welcome_email/2
        (ecto) lib/ecto/pool.ex:292: Ecto.Pool.with_rollback/2
        (ecto) lib/ecto/adapters/sql.ex:567: Ecto.Adapters.SQL.transaction/8
        (ecto) lib/ecto/pool.ex:244: Ecto.Pool.outer_transaction/6

How to provide "remember me" mode

Is it possible to refresh token and implement "remember me" mode?

And clarification about login (sorry for question mix in one ticket):
Login by email and username return different JSON not clear the reason for me?

Thanks

mix deps.get not working for phoenix_token_auth

defp deps do
[{:phoenix, "> 1.0.2"},
{:phoenix_ecto, "
> 1.1"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "> 2.1"},
{:phoenix_live_reload, "
> 1.0", only: :dev},
{:cowboy, "> 1.0"},
{:maru, "
> 0.8.1"},
{:maru_swagger, "> 0.5", only: :dev },
{:comeonin, "
> 1.0"},
{:phoenix_token_auth, "0.0.13"}]
end

Looking up alternatives for conflicting requirements on poison
From mix.lock: 1.5.0
From phoenix_ecto v1.2.0: ~> 1.3
From phoenix_token_auth v0.0.13: ~> 1.3.1

** (Mix) Hex dependency resolution failed, relax the version requirements or unlock dependencies

Thank you.

Improvement: HTML mails

Hi,

I'm using this lib in a project and I found myself having the need to send mails with html body. so I was thinking what do you think if I add the setting to this and make the PR?

Regards

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.