# `MishkaCmsCore.Accounts.Changes.LogOutEverywhereOnPasswordChange`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core/accounts/__changes/log_out_everywhere_on_password_change.ex#L5)

Revokes every token a user holds once a write that changed their password has committed, through
the `log_out_everywhere` add-on's own action, and hands the device that made the change a new one.

| Event | Other sessions | The device that did it | Old reset links, sign-in links, pending codes |
|---|---|---|---|
| Password reset | signed out | stays signed in (new token) | all dead |
| Password change, or a first password | signed out | stays signed in (new token, the API's `meta.token`) | all dead |
| An admin sets someone's password | that account's sessions signed out | the admin is unaffected | all dead |

Every token the account holds is revoked, not only its sessions: a reset or sign-in link sent
before the change no longer works. The device that did it is the one the write signed in (a reset)
or the account changing its own password; an admin's edit gives the account no token.

AshAuthentication's `apply_on_password_change?` does the same inside the write. A password reset
then fails: the reset token is stored like any other token, the add-on revokes it with the rest,
and the reset's own single-use revocation of that token finds it revoked already ("token has
already been revoked"). After the commit, the reset has spent its token first.

**Whether the password changed is decided after the commit, not when the change is attached.**
`AshAuthentication.Strategy.Password.HashPasswordChange` writes the hash in a `before_action` hook,
so a `where: [changing(:hashed_password)]` on this change reads "not changing" for every action
that hashes a password itself, and the change is never attached: a changed password then signed
nobody out. The hook is attached to each action that can set a password, and does nothing when
the write left the hash as it was.

    changes do
      change LogOutEverywhereOnPasswordChange,
        on: [:update],
        where: [action_is([:change_password, :set_password, :reset_password_with_token])]
    end

---

*Consult [api-reference.md](api-reference.md) for complete listing*
