Skip to content
This repository has been archived by the owner on Sep 2, 2021. It is now read-only.

Auth Tokens invalidated in future due to user.ChangePassword() #135

Closed
benagricola opened this issue Sep 5, 2018 · 1 comment
Closed

Comments

@benagricola
Copy link
Contributor

Versions: tip from installer and current code in master both exhibit the same behaviour.

TL;DR Writing an Ansible playbook to deploy DRP, in the following order:

  1. Download and install DRP Binaries
  2. Configure Service & Start
  3. Create user accounts
  4. Set passwords of created user accounts
  5. Delete rocketskates user
  6. Download and activate DRP content packs using newly created admin account

Expressed as shell commands, the relevant part is something like this:

drpcli users create '{"Name":"admin","Description":"Admin User","Roles":["superuser"],"Available":true}'
drpcli users password admin "password"
drpcli users destroy rocketskates
export RS_TOKEN=`drpcli users token admin | jq -r '.Token'`
drpcli contents create dev-library.json # Works
drpcli contents create drp-community-content.json # Fails
drpcli contents create ansible.json # Fails
...

It doesn't matter what order the contents create lines are in, it always fails on the second line.

I built a local copy of dr-provision from master and added debug logging to frontend.userAuth(), which shows that the userSecret and grantorSecret were changing between the first and second contents create calls around here.

Checking this manually using drpcli users list showed the user Secret being updated as well.

I tracked this back to user.ChangePassword() which modifies the Secret whenever a users' password is changed, but does not appear to save it to the User store at the same time.

Currently, the users password call changes the PasswordHash and the Secret, but does not commit the new Secret into the store (changing the Secret happens after the User is saved).

A token is then generated from this User - either using the 'old' Secret which had been previously persisted, or possibly the 'new' Secret which is stored ephemerally in the existing User object but not persisted to the backing store (not sure which one happens here).

The first content create call (or some other consistently occurring action) then either:

  • Causes the User to be reloaded from the store, invalidating any Tokens generated using the ephemeral Secret, or
  • Causes the ephemeral User to be saved to the store, invalidating any Tokens generated using the previously stored Secret.

To test if this is the cause, I made the following change:

diff --git a/backend/user.go b/backend/user.go
index dea0cca1..da0cd801 100644
--- a/backend/user.go
+++ b/backend/user.go
@@ -95,9 +95,9 @@ func (u *User) ChangePassword(rt *RequestTracker, newPass string) error {
                return err
        }
        u.PasswordHash = ph
-       _, err = rt.Save(u)
        // When a user changes their password, invalidate any previous cached auth tokens.
        u.Secret = randString(16)
+       _, err = rt.Save(u)
        return err
 }

Which appears to fix the issue and causes a consistent Secret to be returned and used for all runs of content create.

@benagricola benagricola changed the title Auth Tokens invalidated due to user.ChangePassword() invalidation Auth Tokens invalidated in future due to user.ChangePassword() Sep 5, 2018
@benagricola
Copy link
Contributor Author

This is quite clearly on the wrong repo so I'm just going to go ahead and close this one 🤦‍♂️

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant