Jump to content
Craig A Rodway

ProcessLoginPersistent

Recommended Posts

Hello!
 
About the same time Hari KT asked about "Remember Me" functionality, I identified this as a feature I wanted to implement in some sites under development. Having done this twice before (in CodeIgniter) and based on previous research, I decided to build a ProcessWire module to provide this feature.
 
So far, I have developed and tested this on ProcessWire 2.3. I would welcome any feedback, comments, suggestions and problems from people who are keen to use this. To re-iterate the readme, this module allows users to remain logged in across browser sessions.

  • The module can operate in two ways:
    • Automatically. No code changes, but users do not have a choice.
    • Manually. The module must be called from a site's custom code.
  • Options can be changed in the module configuration page.
  • Enable fingerprinting (IP address and User Agent) as an additional security check.
  • Limit the persistent login functionality by role.
  • Set the name and age of the cookie.
  • Sets an identifier in the session when a user is logged in via a persistent login cookie. This should be used to control access to sensitive information and actions within a site's custom code.
  • Clears login tokens when a potential theft has been identified.

Updated: LoginPersist on GitHub

  • Like 14

Share this post


Link to post
Share on other sites

Thanks sounds nice! :)

Just had a quick look at the code: I think that it does not need to be a Process module. Process modules are only needed if you have a module that runs in the Pw backend. In your case, you could just extend WireData instead of Process. Anyway, thanks again for writing this!

Cheers

  • Like 1

Share this post


Link to post
Share on other sites

Thanks Wanze! I really wasn't sure what the best naming format for this was, so I'm definitely open to changing it to something more suitable :)

Edit: I have just discovered this post - How to present your module - which confirms that Process definitely isn't needed here. It has now been renamed to LoginPersist. If anyone has already installed it, please uninstall, remove, and install again :)

  • Like 1

Share this post


Link to post
Share on other sites

@Craig, thanks for this - just the job for a project I'm on at the moment. Installed on PW 2.4.4 and seems to be working fine.

Share this post


Link to post
Share on other sites

Thanks Dave.

That's not something that I've looked at specifically - I copied the parameter values from elsewhere in ProcessWire - and the domain one is just set to null.

setcookie($this->get('cookieName'), $value, $expires, '/', null, false, true);

I haven't been caught out by this issue as I've always set up individual hosts for each site I work on; but definitely something to be aware of.

It would be relatively easy to add a configuration field to the module for a user-specified cookie domain though, if it was required :)

  • Like 1

Share this post


Link to post
Share on other sites

I quite often use Chrome & Chrome Canary so that I can be logged in to the same site (PW sites or others) as two different users, and to avoid even trying to be logged into 2 Google accounts in the same Chrome instance. The only problem is that, by its very nature, Canary can be 'unpredictable', shall we say.

Best thing is to use Chrome & Firefox and avoid all the problems. ;)

FWIW, Craig, I shouldn't go out of your way just to accommodate oddballs like me. :P

Share this post


Link to post
Share on other sites

@Dave, I use Incognito Window for that. I love it because I don't have to start 2 browsers and the Incognito window looks different then the default.

Chrome on the mac: [ shift ] + [ command ] + [ n ]

  • Like 1

Share this post


Link to post
Share on other sites

I use Chrome as my main browser; and when I need to do account or session based testing I usually head to Incognito mode as well :)

  • Like 1

Share this post


Link to post
Share on other sites

This is a great module, appears to work great and is exactly what I needed.

I just tripped over something, not necessarily an issue with this specific module, but I'm getting this

Notice: Undefined index: HTTP_USER_AGENT in <CUT>/modules/LoginPersist/LoginPersist.module on line 508

When I bootstrap Processwire for use in a backend cron job.  It seems like in init() there should be some check to see if Processwire is running in the context of a web site.

Not sure the best way to fix it, and I admit most users probably don't bootstrap PW for use in a cron.  It's an edge case for sure.  Here's what I did:

   public function init() {
        if (php_sapi_name() != 'cli') {
            $this->set('doLoginHook', true);
            $this->session->addHookAfter('login', $this, 'loggedIn');
            $this->session->addHookAfter('logout', $this, 'loggedOut');
            $this->_pruneLogins();
            $this->attemptLogin();
        }
    }

Detecting if PHP is being used via CLI with php_sapi_name() is based off an answer on stackoverflow at http://stackoverflow.com/questions/343557/how-to-distinguish-command-line-and-web-server-invocation

Great work on this module!

  • Like 2

Share this post


Link to post
Share on other sites

@bracketfire: that's a cool way to do it, but whether it's the best approach depends on what you're trying to achieve. It's entirely possible, although quite rare, for $_SERVER['HTTP_USER_AGENT'] to be missing from non-cli requests too (it's a header after all), so checking for cli use doesn't entirely prevent this notice from appearing.

If the underlying issue is that $_SERVER['HTTP_USER_AGENT'] isn't found and it's necessary for this module to work at all (haven't checked the code so can't really tell), it would probably make more sense to simply check for that specifically with isset().

On the other hand, if the module isn't useful in cli use at all and $_SERVER['HTTP_USER_AGENT'] isn't necessary for it to work properly in non-cli use case, it would make most sense to apply your fix (skip the module entirely for cli users) and add an isset() check to prevent unnecessary notices for non-cli clients that don't, for any given reason, send this header :)

(Sorry, meant to point out something simple, but this turned into a kind of a long rant anyway..)

  • Like 2

Share this post


Link to post
Share on other sites

Hi bracketfire, thanks for your comments! I'm pleased you're finding the module useful.

The HTTP_USER_AGENT is used in conjunction with the IP address for "fingerprinting" - adding additional security checks against the client. It utilises the same methods as the main ProcessWire session class.

In the first instance, I should probably update the fingerprinting code to use the user agent value only if its present; and additionally, look into changing the init() function to not do anything on the command line.

I'm not sure that there will be one true way to detect with absolute certainty CLI vs HTTP, as this SO thread discusses, but php_sapi_name() looks the closest. It's probably no use running this module when in CLI mode anyway, so this is something I will look at.

Thanks again!

Craig.

Share this post


Link to post
Share on other sites

I'm not sure that there will be one true way to detect with absolute certainty CLI vs HTTP, as this SO thread discusses, but php_sapi_name() looks the closest. It's probably no use running this module when in CLI mode anyway, so this is something I will look at.

Just for the record, here's how PW itself (in current dev branch) is doing it:

$config->cli = (!isset($_SERVER['SERVER_SOFTWARE']) && (php_sapi_name() == 'cli' || ($_SERVER['argc'] > 0 && is_numeric($_SERVER['argc']))));
  • Like 4

Share this post


Link to post
Share on other sites

Thank you for this module!

I'm trying to implement it on a 2.5.2 install and have some issues/questions.

I installed, activated and configured the module to be automatic without fingerprint and only assigned to 1 specific role.

 

These might me dumb questions, but I'm still asking  :undecided:

1) is this module intended for backend or frontend usage or both?

2) how do I go about testing?

I logged in to the backend on a live server in Chrome with a user that has the specified role. After login I can see that a persist cookie has been created.

Then I opened a Chrome incognito window and went to the backend login address. But I'm still presented with the login form.

I want to use it on the frontend. So I switched off automatic mode and added this to my login logic:

	//login user
	$u = $session->login($username, $pass);

	if($u) {
		// make login persistent if user checked Remember me
		if ($u->login_persist && $u->login_persist == "1") {
			$persist = wire('modules')->get('LoginPersist');
			$persist->persist();
		}
        }
 

When I now login to the frontend, I can also see that a persist cookie is created.

I tried testing it the same way as above with the backend login. No success.

When I log out of the frontend session, the cookie is gone.

4) Will the login still persist, even if the user logged out of there previous session? I guess not.

Share this post


Link to post
Share on other sites

Hi gebeer

It is designed to work for either back, or front, or both. It's up to you.

The main flaw in your testing is using incognito mode. That is a totally separate browser session, with different cookies. So there is no way that logging in with persist, in one browser window will work as you expect it to with incognito.

The better way to test it is to delete the ProcessWire session cookie. This will log you out. But then LoginPersist will see the persist cookie is present, and log you back in.

The module is designed to remove the persistent cookie when the user actively chooses to log out. The idea behind it is to allow the user to have a persistent login state until they choose to log out. To remain logged in with this, simply do not log out.

  • Like 2

Share this post


Link to post
Share on other sites

Thank you for clarifying.

So I guess your module is restoring the session then.

Or do I have to pick up and process the cookie data in my custom login logic?

Cheers

Share this post


Link to post
Share on other sites

Thank you again for the explanation. I followed your advice for testing and can see now that it is working.

Share this post


Link to post
Share on other sites

For some reason, this module doesn't work for me on my site. PW 2.7.2 and only the Superuser given a persistent login. Both sessionExpireSeconds and session.cookie.lifetime are set to 86400, still login lasts less than an hour. This works fine on a local MAMP server.

Share this post


Link to post
Share on other sites
4 hours ago, franctic-aerobic said:

@Craig A Rodway: Is this module compatible with ProcessWire 3.0+?

It works without problems with the latest stable version 😉 

  • Like 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Anton
      Hi there,
      I'm working with Processwire 3. Before summer I had issues to load to my backend. I finally managed to connect thanks to this : 
      $admin = wire('users')->get('admin');
      $admin->setOutputFormatting(false);
      $admin->set('pass', 'yo12345ZZ')
      $admin->save('pass');
      But later, the problem evolved: when I logged in to the site, the login page redirected me to the home. I didn't find any information about it on the web.
      But recently, the redirection has changed, now it is the login page that reloads when you connect. 
      I don't know where to start to fix this. It looks like sorcery.
      Thank you for all the help you can give me.
       
    • By angelo, italy
      Hi guys,
      I've always used WP but I want to swtich to PW. I'm not sure ....
      I'd like to know if it's possible to create a website for an online photo contest.
      The participants of the competition could create their own account, in which they upload their photos. The photos uploaded remain visible only to themselves and the judges.
      From their account they can make the "entrance fee" payment.
      The judges of the competition can create their own account... entering they see the photos of the participants and vote photos
      At the main page I imagine the title of the competition, a button to read the regulation, and a button to register.
      The website should be in Italian and English.
      Thank you!!
       
       
    • By Peter Knight
      I have a demo site which I moved to a new VPS for client testing
      We noticed that leaving a page open and then revisiting the site can result in a 25 second(ish) to load time and will then throw a 500 Error.
      The hosting guys had a look and confirmed that the server is fine but the issue could be related to authentication or sessions.
      We are running Page Protector and ProCache so I wondered if there were any known bugs here and any recommended actions.
      My actual PW log doesn't show anything but the server log has plenty of these
       
      2018-12-06 08:14:00 Error xxx.141.1x.101 500 POST /who-we-are/ HTTP/1.0     1.58 K Apache access 2018-12-06 08:14:45 Warning xxx.141.1x.131   mod_fcgid: read data timeout in 45 seconds, referer: http://demo.abc.not/who-we-are/       Apache error 2018-12-06 08:14:45 Error xxx.141.1x.131   End of script output before headers: index.php, referer: http://demo.abc.not/who-we-are/       Apache error 2018-12-06 09:03:18 Error xxx.141.1x.131   2614#0: *667 recv() failed (104: Connection reset by peer) while reading response header from upstream       nginx error Thanks
      P
    • By Marcel
      Hey all,
      I want to customize the mywebsite/processwire/profile page. It's almost all good but I want to get rid of the sections 'Admin Theme' and 'Language' so that the user can just set a new password. (see image)
      Do I have to modify the admin template or how can I do that? Because when I go tree>Admin>Profile there are no fields to add or remove.
      Or where can I find the php file?
      I would appreciate your help.

    • By ridgedale
      Reference: PW 3.0.111 and uikit3 based site using the Regular-Master profile.
      I'm trying to automatically redirect a logged-in user to a custom profile page using $session->redirect() and need to add $user->name to the redirect path.
      All my attempts appear to have failed:
      $session->redirect('/user-profile/')->name; $session->redirect('/user-profile/')->$user->name; $session->redirect('/user-profile/' . get($user->name . '/')); $session->redirect('/user-profile/' & get($user->name)); Can anyone point out where I am going wrong?
×
×
  • Create New...