MishkaCmsCore.Accounts.Changes.LogOutEverywhereOnPasswordChange (Mishka CMS Core v0.0.1)

Copy Markdown View Source

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.

EventOther sessionsThe device that did itOld reset links, sign-in links, pending codes
Password resetsigned outstays signed in (new token)all dead
Password change, or a first passwordsigned outstays signed in (new token, the API's meta.token)all dead
An admin sets someone's passwordthat account's sessions signed outthe admin is unaffectedall 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