expected v0.1.1 Expected.Plugs View Source

Plugs for registering logins and authenticating persistent cookies.

Requirements

For the plugs in this module to work, you must plug Expected in your endpoint:

plug Expected

As Expected calls Plug.Session itself, you must not plug it in your endpoint. You must however configure the session in the :expected configuration:

config :expected,
  store: :mnesia,
  table: :logins,
  auth_cookie: "_my_app_auth",
  session_store: PlugSessionMnesia.Store,  # For instance.
  session_cookie: "_my_app_key"  # The Plug.Session `:key` option.

For the login registration to work, Expected needs to get the session ID from the session cookie. You must use a session store that stores the session server-side and uses the cookie to store the session ID.

Link to this section Summary

Functions

Authenticates a connection

Logs a user out

Link to this section Functions

Link to this function authenticate(conn, opts \\ []) View Source
authenticate(Plug.Conn.t(), keyword()) :: Plug.Conn.t()

Authenticates a connection.

Session authentication

This plug first checks if the session is already authenticated. It does so by reading the :authenticated field in the session. If it is true, it assigns :authenticated and :current_user in the conn according to their value in the session.

The names of these fields can be changed by setting the corresponding options:

conn
|> authenticate(authenticated: :logged_in, current_user: :user_id)

They can also be set application-wide in the configuration:

config :expected,
  ...
  plug_config: [authenticated: :logged_in, current_user: :user_id]

If the session is not yet authenticated, this plug checks for an authentication cookie. By default, it is valid for 90 days after the last successful authentication. You can change this in the application configuration:

config :expected,
  ...
  cookie_max_age: 86_400  # Set to one day, for example.

Alternatively, you can set it locally:

conn
|> authenticate(cookie_max_age: 86_400)

Alerts

For security purpose, an authentication cookie can be used only once. If an authentication cookie is re-used, conn.assigns.unexpected_token is set to true and the session is not authenticated. You can check this value using Expected.unexpected_token?/1 and accordingly inform the user of a possible malicious access.

User loading

After a successful cookie authentication, the :current_user field in both the session and the conn assigns is set to an Expected.NotLoadedUser, featuring the user’s username:

%Expected.NotLoadedUser{username: "user"}

You should load this user from the database in another plug following this one if the session has been authenticated.

Link to this function logout(conn, opts \\ []) View Source
logout(Plug.Conn.t(), keyword()) :: Plug.Conn.t()

Logs a user out.

This plug deletes the login and its associated session from the stores and their cookies. If there is no authentication cookie, it does nothing.

Link to this function register_login(conn, opts \\ []) View Source
register_login(Plug.Conn.t(), keyword()) :: Plug.Conn.t()

Registers a login.

Requirements

This plug expects that the session contains a :current_user key featuring a :username field:

conn
|> put_session(:current_user, %User{username: "user", name: "A User"})
|> register_login()

The names of these fields can be changed by setting the corresponding options:

conn
|> put_session(:logged_in_user, %User{user_id: "user", name: "A User"})
|> register_login(current_user: :logged_in_user, username: :user_id)

They can also be set application-wide in the configuration:

config :expected,
  ...
  plug_config: [current_user: :logged_in_user, username: :user_id]

Authentication information is stored in a cookie. By default, it is valid for 90 days after the last successful authentication. You can change this in the application configuration:

config :expected,
  ...
  cookie_max_age: 86_400  # Set to one day, for example.

Alternatively, you can set it locally:

conn
|> put_session(:current_user, %User{username: "user", name: "A User"})
|> assign(:persistent_login, true)
|> register_login(cookie_max_age: 86_400)