Jump to content

ProcessLoginPersistent


Craig
 Share

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 16
Link to comment
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
Link to comment
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
Link to comment
Share on other sites

  • 1 month later...

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
Link to comment
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

Link to comment
Share on other sites

  • 4 weeks later...

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 3
Link to comment
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
Link to comment
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.

Link to comment
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
Link to comment
Share on other sites

  • 3 months later...

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.

Link to comment
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
Link to comment
Share on other sites

  • 1 year later...
  • 2 months later...
  • 2 years later...
  • 6 months later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...