Skip to content

Commit

Permalink
Merge pull request #2 from danschultzer/master
Browse files Browse the repository at this point in the history
Update to master
  • Loading branch information
esse authored Mar 5, 2020
2 parents 42c6fb0 + a1b9416 commit ff3d4c8
Show file tree
Hide file tree
Showing 99 changed files with 2,674 additions and 1,116 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
language: elixir
elixir: 1.9
elixir: 1.10
otp_release: 22.0
services:
- postgresql
Expand Down
113 changes: 113 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,118 @@
# Changelog

## v1.0.19 (TBA)

**Warning:** This release will now sign and verify all tokens, causing previous tokens to no longer work. Any sessions and persistent sessions will be invalidated.

### Enhancements

* [`Pow.Plug.Session`] Now sets a global lock when renewing the session
* [`PowPersistentSession.Plug.Cookie`] Now sets a global lock when authenticating the user
* [`PowEmailConfirmation.Plug`] Added `PowEmailConfirmation.Plug.sign_confirmation_token/2` to sign the `email_confirmation_token` to prevent timing attacks
* [`PowEmailConfirmation.Plug`] Added `PowEmailConfirmation.Plug.confirm_email_by_token/2` to verify the signed `email_confirmation_token` to prevent timing attacks
* [`PowInvitation.Plug`] Added `PowInvitation.Plug.sign_invitation_token/2` to sign the `invitation_token`
* [`PowInvitation.Plug`] Added `PowInvitation.Plug.load_invited_user_by_token/2` to verify the signed `invitation_token` to prevent timing attacks
* [`PowResetPassword.Plug`] Changed `PowResetPassword.Plug.create_reset_token/2` to sign the `:token`
* [`PowResetPassword.Plug`] Added `PowResetPassword.Plug.load_user_by_token/2` to verify the signed token to prevent timing attacks
* [`PowResetPassword.Plug`] Changed `PowResetPassword.Plug.update_user_password/2` so it decodes the signed token
* [`PowPersistentSession.Plug.Cookie`] Now uses signed tokens to prevent timing attacks
* [`Pow.Plug.Session`] Now uses signed session ID's to prevent timing attacks
* [`Pow.Plug`] Added `Pow.Plug.sign_token/4` to sign tokens
* [`Pow.Plug`] Added `Pow.Plug.verify_token/4` to decode and verify signed tokens
* [`Pow.Plug.MessageVerifier`] Added `Pow.Plug.MessageVerifier` module to sign and verify messages

### Deprecations

* [`PowEmailConfirmation.Plug`] `PowEmailConfirmation.Plug.confirm_email/2` has been deprecated in favor of `PowEmailConfirmation.Plug.confirm_email_by_token/2`
* [`PowInvitation.Plug`] `PowInvitation.Plug.invited_user_from_token/2` has been deprecated in favor of `PowInvitation.Plug.load_invited_user_by_token/2`
* [`PowInvitation.Plug`] `PowInvitation.Plug.assign_invited_user/2` has been deprecated
* [`PowResetPassword.Plug`] `PowResetPassword.Plug.user_from_token/2` has been deprecated in favor of `PowResetPassword.Plug.load_user_by_token/2`
* [`PowResetPassword.Plug`] `PowResetPassword.Plug.assign_reset_password_user/2` has been deprecated

### Documentation

* Updated the [API guide](guides/api.md) with signed tokens

## v1.0.18 (2020-02-14)

### Bug fixes

* [`Pow.Phoenix.Routes`] Fixed bug where callback route methods is not using the overridden method
* [`PowPersistentSession.Plug.Cookie`] `PowPersistentSession.Plug.Cookie.delete/2` now correctly pulls token during `:before_send` callback
* [`Pow.Plug.Session`] `Pow.Plug.Session.delete/2` now correctly pulls session id during `:before_send` callback so `PowEmailConfirmation` will remove set session

## v1.0.17 (2020-02-04)

### Enhancements

* [`Pow.Ecto.Context`] Calls to `Pow.Ecto.Context.get_by/2` replaced with `Pow.Operations.get_by/2` so custom users context module can be used. The following methods has been updated:
* `Pow.Ecto.Context.authenticate/2`
* `PowEmailConfirmation.Ecto.Context.get_by_confirmation_token/2`
* `PowInvitation.Ecto.Context.get_by_invitation_token/2`
* `PowResetPassword.Ecto.Context.get_by_email/2`
* [`Pow.Ecto.Schema.Changeset`] `Pow.Ecto.Schema.Changeset.confirm_password_changeset/3` now adds the default `Ecto.Changeset.validate_confirmation/3` error instead of the previous `not same as password` error
* [`Pow.Ecto.Schema.Changeset`] `Pow.Ecto.Schema.Changeset.confirm_password_changeset/3` now uses the `Ecto.Changeset.validate_confirmation/3` for validation and expects `:password_confirmation` instead of `:confirm_password` in params
* [`Pow.Ecto.Schema.Changeset`] `Pow.Ecto.Schema.Changeset.new_password_changeset/3` now only requires the `:password_hash` if there have been no previous errors set in the changeset
* [`Pow.Ecto.Schema`] No longer adds `:confirm_password` virtual field
* [`Pow.Ecto.Schema`] Now has an `@after_compile` callback that ensures all required fields has been defined
* [`PowInvitation.Phoenix.InvitationView`] Now renders `:password_confirmation` field instead of `:confirm_password`
* [`PowResetPassword.Phoenix.ResetPasswordView`] Now renders `:password_confirmation` field instead of `:confirm_password`
* [`Pow.Phoenix.RegistrationView`] Now renders `:password_confirmation` field instead of `:confirm_password`
* [`PowEmailConfirmation.Ecto.Schema`] No longer validates if `:email` has been taken before setting `:unconfirmed_email`
* [`PowEmailConfirmation.Phoenix.ControllerCallbacks`] Now prevents user enumeration for `PowInvitation.Phoenix.InvitationController.create/2`
* [`PowPersistentSession.Plug.Cookie`] Changed default cookie name to `persistent_session`
* [`PowPersistentSession.Plug.Cookie`] Removed renewal of cookie as the token will always expire
* [`PowPersistentSession.Plug.Cookie`] No longer expires invalid cookies
* [`Pow.Operations`] Added `Pow.Operations.fetch_primary_key_values/2`
* [`PowPersistentSession.Plug.Base`] Now registers `:before_send` callbacks
* [`PowPersistentSession.Plug.Cookie`] Now updates cookie and backend store in `:before_send` callback
* [`Pow.Plug.Base`] Now registers `:before_send` callbacks
* [`Pow.Plug.Session`] Now updates plug session and backend store in `:before_send` callback
* [`Pow.Plug`] Added `Pow.Plug.create/3`
* [`Pow.Plug`] Added `Pow.Plug.delete/2`

### Removed

* [`PowResetPassword.Phoenix.ResetPasswordController`] Will no longer prevent information leak by checking if `PowEmailConfirmation` or registration routes are enabled; instead it'll by default prevent user enumeration, but can be disabled if `pow_prevent_user_enumeration: false` is set in `conn.private`

### Bug fixes

* [`PowPersistentSession.Plug.Base`] With custom `:persistent_session_store` now falls back to `:cache_store_backend` configuration option
* [`PowResetPassword.Plug`] With custom `:reset_password_token_store` now falls back to `:cache_store_backend` configuration option
* [`Pow.Plug.Base`] With custom `:credentials_cache_store` now falls back to `:cache_store_backend` configuration option

### Deprecations

* [`Pow.Ecto.Changeset`] `Pow.Ecto.Schema.Changeset.confirm_password_changeset/3` has deprecated use of `:confirm_password` in params in favor of `:password_confirmation`
* [`Pow.Plug.Session`] `:session_store` option has been renamed to `:credentials_cache_store`
* [`Pow.Plug`] `Pow.Plug.clear_authenticated_user/1` deprecated in favor of `Pow.Plug.delete/1`

## v1.0.16 (2020-01-07)

**Note:** This release contains an important security fix.

### Enhancements

* [`PowPersistentSession.Plug.Cookie`] Now supports `:persistent_session_cookie_opts` to customize any options that will be passed on to `Plug.Conn.put_resp_cookie/4`
* [`PowResetPassword.Phoenix.ResetPasswordController`] Now uses `PowResetPassword.Phoenix.Messages.maybe_email_has_been_sent/1` with a generic response that tells the user the email has been sent only if an account was found
* [`PowResetPassword.Phoenix.ResetPasswordController`] When a user doesn't exist will now return success message if `PowEmailConfirmation` extension is enabled
* [`PowResetPassword.Phoenix.Messages`] Added `PowResetPassword.Phoenix.Messages.maybe_email_has_been_sent/1` and let `PowResetPassword.Phoenix.Messages.email_has_been_sent/1` fall back to it
* [`PowEmailConfirmation.Phoenix.ControllerCallbacks`] When a user tries to sign up and the email has already been taken the default e-mail confirmation required message will be shown
* [`Pow.Plug.Session`] Now renews the Plug session each time the Pow session is created or rolled

### Bug fixes

* [`Pow.Ecto.Schema.Changeset`] Fixed bug where `Pow.Ecto.Schema.Changeset.user_id_field_changeset/3` update with `nil` value caused an exception to be raised
* [`PowPersistentSession.Plug.Cookie`] Now expires the cookie 10 seconds after the last request when authenticating to prevent multiple simultaneous requests deletes the cookie immediately

### Documentation

* Added mailer rate limitation section to [production checklist guide](guides/production_checklist.md)
* [`Pow.Plug.Session`] Added section on session expiration to the docs
* Updated instructions in [umbrella project guide](guides/umbrella_project.md) to Elixir 1.9
* [`Pow.Store.Backend.Base`] Updated usage example with Cachex
* Added [security practices page](guides/security_practices.md)

## v1.0.15 (2019-11-20)

### Enhancements
Expand Down
31 changes: 11 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Add Pow to your list of dependencies in `mix.exs`:
defp deps do
[
# ...
{:pow, "~> 1.0.15"}
{:pow, "~> 1.0.18"}
]
end
```
Expand Down Expand Up @@ -54,9 +54,15 @@ PRIV_PATH/repo/migrations/TIMESTAMP_create_user.ex
Add the following to `config/config.exs`:

```elixir
use Mix.Config

# ... existing config

config :my_app, :pow,
user: MyApp.Users.User,
repo: MyApp.Repo

# ... import_config
```

Set up `WEB_PATH/endpoint.ex` to enable session based authentication (`Pow.Plug.Session` is added after `Plug.Session`):
Expand All @@ -67,13 +73,8 @@ defmodule MyAppWeb.Endpoint do

# ...

plug Plug.Session,
store: :cookie,
key: "_my_app_key",
signing_salt: "secret"

plug Plug.Session, @session_options
plug Pow.Plug.Session, otp_app: :my_app

plug MyAppWeb.Phoenix.Router
end
```
Expand Down Expand Up @@ -522,7 +523,7 @@ By default `Pow.Store.Backend.EtsCache` is started automatically and can be used
For a production environment, you should use a distributed, persistent cache store. Pow makes this easy with `Pow.Store.Backend.MnesiaCache`. To start MnesiaCache in your Phoenix app, add it to your `application.ex` supervisor:

```elixir
defmodule MyAppWeb.Application do
defmodule MyApp.Application do
use Application

def start(_type, _args) do
Expand All @@ -545,7 +546,7 @@ end

Update the config `cache_store_backend: Pow.Store.Backend.MnesiaCache`.

Remember to add `:mnesia` to your `:extra_applications` so it'll be available for your release build.
Remember to add `:mnesia` to your `:extra_applications` so it'll be available for your release build. Mnesia will write files to the current working directory. The path can be changed with `config :mnesia, dir: '/path/to/dir'`.

The MnesiaCache requires write access. If you've a read-only file system you should take a look at the [Redis cache backend store guide](guides/redis_cache_store_backend.md).

Expand All @@ -563,17 +564,7 @@ If you're currently using Coherence, you can migrate your app to use Pow instead

## Pow security practices

* The `user_id_field` value is always treated as case insensitive
* If the `user_id_field` is `:email`, it'll be validated based on RFC 5322 (excluding IP validation)
* The `:password` has a minimum length of 8 characters
* The `:password` has a maximum length of 4096 bytes [to prevent DOS attacks against Pbkdf2](https://github.com/riverrun/pbkdf2_elixir/blob/master/lib/pbkdf2.ex#L21)
* The `:password_hash` is generated with `PBKDF2-SHA512` with 100,000 iterations
* The session value contains a UUID token that is used to pull credentials through a GenServer
* The credentials are stored in a key-value cache with TTL of 30 minutes
* The credentials and session are renewed after 15 minutes if any activity is detected
* The credentials and session are renewed when user updates

Some of the above is based on [OWASP](https://www.owasp.org/) or [NIST SP800-63b](https://pages.nist.gov/800-63-3/sp800-63b.html) recommendations.
See [security practices](guides/security_practices.md).

## Other libraries

Expand Down
2 changes: 1 addition & 1 deletion config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ config :pow, Pow.Ecto.Schema.Password, iterations: 1

config :phoenix, :json_library, Jason

extension_test_modules = [PowEmailConfirmation, PowInvitation, PowEmailConfirmation.PowInvitation, PowPersistentSession, PowResetPassword, PowResetPassword.NoRegistration]
extension_test_modules = [PowEmailConfirmation, PowInvitation, PowEmailConfirmation.PowInvitation, PowPersistentSession, PowResetPassword]

for extension <- extension_test_modules do
endpoint_module = Module.concat([extension, TestWeb.Phoenix.Endpoint])
Expand Down
Loading

0 comments on commit ff3d4c8

Please sign in to comment.