Jump to content
Craig

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 15

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

You're welcome. Thanks for the feedback DaveP! :)

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 3

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

The module will handle all of that for you :)

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

Hi!

Great Module.

I just want to have a "remember me" checkbox in the login form.
So the user can decide ...
Ho can i add this?

Share this post


Link to post
Share on other sites

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

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Marvin
      Hi,
      I'm still new at processwire, i want to ask, i was create a website with sign in system, but i want to add a access roles/permission for each user at my website. For now, i just can create a login user without any permission and the user data became as a pages in my processwire.
      Here i attach my code for login
      <?php $note = $note2 = $hidden =""; if($input->get->id == "logout") { $session->remove('login_id'); } if($input->post->submit) { $email = $sanitizer->email($input->post->email); $pass = $sanitizer->text($input->post->pass); $result = $pages->find("email=$email, text_1=$pass"); if(!$email || !$pass) { $note = "Data belum lengkap"; } else { if($result->count > 0) { $session->login_id = "$result"; $hidden = "style = 'diplay:none'"; $url=$pages->get("/files/")->httpUrl; header("Location:$url"); die(); } else { $note = "Akun tidak ditemukan"; } } } ?> And this code for login form
      <div class="frow-container"> <div class="frow centered mt-50"> <div class="col-md-1-3"> <div class="box p-40 shadow-light"> <h2 class="mb-20 text-center" <?=$hidden?>>Database Partitur<br>GII HIT</h2> <form method="post" <?=$hidden?>> <label>Username <input type="text" name="email"></label> <label>Password <input type="password" name="pass"></label> <input type="submit" name="submit" value="Masuk"> </form> <p class="notif"><?=$note;?></p> <div class="text-center"><?=$note2;?></div> </div> </div> </div> </div> Just for remember, my user data now is a pages, and i cannot give any permission to user data.
      Thank you very much for help.
    • By kyksh
      Hi!
      I need users to login by their email address. This works when I change the value in ProcessLogin.module
       122     protected $useEmailLogin = null;
      to
      122     protected $useEmailLogin = true;
      What would be a recommended way to enable this?
      There's this line in ProcessLogin.module:
        15  * @property bool|int $allowEmail Whether or not email login is allowed (0|false=off, 1|true=Yes, 2=Yes or name also allowed)
      But I can't figure out how to set this. I tried next to $useEmailLogin in ProcessLogin.module and in config.php, but neither takes effect.
      BTW I tried module LoginWithEmail but it seems outdated. My PW version is 3.0.165
    • By jploch
      Hey folks,
      Iam working on a new Admin Theme, based on AdminThemeReno, which I would like to release for the public soon.
      Now I want to style the login page to fit the look and feel of the backend.

      After some research, I found out that I have to set the "$config->defaultAdminTheme = 'AdminThemeName' " inside my site config.php file to load all the styles from my admin theme on the login page instead of the default ones.
      Is it possible to set this via api from my Admin Theme settings, without the need of editing the config file?
       
    • By DanielKit
      Hi. I'm currently stuck at the login page in my project. Once I enter my admin username and my password and press login, nothing happens. The page just reloads. However, the URL changes from http://myipaddress/processwire to http://myipaddress/processwire/?login=1. I've checked all of my server settings, and to my knowledge, all seems to be fine there. I don't know where to go from here.. Thanks in advance!
    • By Tyssen
      I have a client who is reporting that in the last couple of days they can no longer login to their site with their normal browser (Chrome). Using another browser or an incognito window works.
      I've tried logging into the site using the same login details in my usual browser (Firefox) and have had no problems.
      The site is a membership site and today other members are reporting the same problem.
      The site is running 3.0.148 and has the session handler DB and login throttle modules installed. It was recently upgraded to 3.x from 2.x. But no changes have been made to the site between the time when they were able to login OK and when the problem started happening.
×
×
  • Create New...