Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Identity data stays in session if findIdentity() returns null #18646

Closed
mikehaertl opened this issue May 12, 2021 · 10 comments
Closed

Identity data stays in session if findIdentity() returns null #18646

mikehaertl opened this issue May 12, 2021 · 10 comments
Labels
Milestone

Comments

@mikehaertl
Copy link
Contributor

What steps will reproduce the problem?

  1. Login a user
  2. Make findIdentity() return null for that user (e.g. disable the user in the database)
  3. Load any page that checks the login status (getIsGuest())

What is the expected result?

If findIdentity() returns null the user should be logged out properly and the identity information should be deleted from the session.

What do you get instead?

The user seems to be logged out (i.e. getIsGuest() returns true) but the identity information is still present in the session. The user is redirected to the login page on next request.

If now the user record is re-enabled in the DB the user suddenly is logged in again.

This is an unexpected user experience and can also lead to weird errors on the login page.

Additional info

This is related to #9718 but to me the issue here is more fundamental. It is unrelated to auth_key and the like.

I'm unsure about BC issues but wonder why this was implemented this way. I can't think of a situation where it would make sense to keep the idParam in session if the asssocitated identity is gone/no longer valid and getIsGuest() returns true.

The comment for IdentityInterface::findIdentity() also seems to suggest that this can be used to immediately un-authenticate (read: logout) a logged in user:

    /**
     * ...
     * @return IdentityInterface|null the identity object that matches the given ID.
     * Null should be returned if such an identity cannot be found
     * or the identity is not in an active state (disabled, deleted, etc.)
     */
    public static function findIdentity($id);
Q A
Yii version 2.0.41
PHP version 7.4.15
Operating system Debian
@mikehaertl
Copy link
Contributor Author

My workaround is to use my custom User class and override renewAuthStatus() like this:

    /**
     * @see \yii\web\User
     */
    protected function renewAuthStatus()
    {
        parent::renewAuthStatus();
        if ($this->getIdentity() === null) {
            $this->switchIdentity(null);
        }
    }

I suggest to add this to the implementation of yii\web\User.

@bizley
Copy link
Member

bizley commented May 12, 2021

This sounds good, at least without digging more into the problem. @samdark ?

@bizley
Copy link
Member

bizley commented May 12, 2021

Hmm, I can see that renewAuthStatus is setting identity to null when this is returned by findIdentity, and since isGuest is checking for that all should be good, right? What am I missing?

@mikehaertl
Copy link
Contributor Author

Right, setting identity to null is the one part. But like I said: the identity params are not removed from the session (e.g. you still see __id with the correct user id there). So the user is suddenly logged in again if findIdentity() returns the user record again.

I can't see, why it would make sense to have the id params kept in session if the user is actually seen as guest.

@bizley
Copy link
Member

bizley commented May 12, 2021

So the problem is more with that and enabling auto login, right? Is setting it to false fixing that use-case?

@mikehaertl
Copy link
Contributor Author

mikehaertl commented May 12, 2021

It has nothing to do with auto login. It's really about proper cleanup if the identity ist not valid anymore. The implementation of getIsGuest() shows, that findIdentity() is the single source of truth, whether a user is authenticated or not.

If the return value of findIdentity() changes to null all authentication data should be completely removed:

  1. Remove identity params from session
  2. Delete auto login cookie, if enabled

Point 2) already happens, but I think this is rather by accident:

  • After findIdentity() returns null, on the next request, it will try to login by cookie
  • loginByCookie() will call getIdentityAndDurationFromCookie()
  • There the cookie is deleted if findIdentity() returns null

Point 1) remains open.

@bizley
Copy link
Member

bizley commented May 12, 2021

Ok, I agree with what you are saying here. Would it work if the line I pointed previously was changed to $this->switchIdentity($identity);? There might be a wee overhead with the lines underneath it.

@samdark samdark added the type:bug Bug label May 12, 2021
@samdark
Copy link
Member

samdark commented May 12, 2021

Yes, doing a cleanup is a good idea. Since you're into it, may I ask if you have time for a pull request?

@samdark samdark added this to the 2.0.43 milestone May 12, 2021
@mikehaertl
Copy link
Contributor Author

mikehaertl commented May 12, 2021

@bizley I think it must be done after the call to loginByCookie() because switchIdentity(null) would delete that cookie and thus break auto login. So probably the end of renewAuthStatus() is a good place to do the check.

@samdark Sure, I can provide a PR and we can discuss things further there.

mikehaertl added a commit to mikehaertl/yii2 that referenced this issue May 12, 2021
@samdark samdark modified the milestones: 2.0.43, 2.0.44 Aug 7, 2021
mikehaertl added a commit to mikehaertl/yii2 that referenced this issue Aug 10, 2021
mikehaertl added a commit to mikehaertl/yii2 that referenced this issue Aug 10, 2021
mikehaertl added a commit to mikehaertl/yii2 that referenced this issue Aug 10, 2021
bizley pushed a commit that referenced this issue Aug 11, 2021
#18649)

* Issue #18646 Cleanup auth data from session if findIdentity() returns null

* Issue #18646 Refactor fix to remove stale identity data from session

* Issue #18646 Fix test for HttpBasicAuth (#15658)

Co-authored-by: Alexander Makarov <sam@rmcreative.ru>
Co-authored-by: Bizley <pawel@positive.codes>
@bizley
Copy link
Member

bizley commented Aug 11, 2021

Closed via c94d704

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

No branches or pull requests

3 participants