CVS edit link for andrewfn

I have developed the urllogin module for my company who would like to release it back the community.

This module provides a way to transparently log a user into the web site when they follow a link. Every effort has been made to minimize the potential security risks.

USE CASE
========

* The main use case is for mass emailing where it is unlikely
that the recipients will go through the hassle of creating
accounts and passwords. Assuming an account has been created
for them, email to them contains a customized link which will
automatically log them in and take them to a target page.
* This permission would only be given to accounts with "low
value" privileges (e.g. no admin, financial or access to
confidential data).
* The reason for logging users into the site would typically be
so that they can do activities such as:
o sign up for events
o comment, rate, "like", or otherwise interact with the site
o unsubscribe from email or change email preferences
* Usage tracking
o Widely used mass email tools such as MailChimp and Campaign
Monitor allow the sender to track which links in the email
recipients have clicked on.
o Using this module, Drupal's own tracking system can be used
to accomplish this, providing a far more integrated
solution than provided by third-party mailers.

FEATURES
========

* Security
o The login access link is encoded with a high level of
security based on sha256
o All encryption/decryption functions are encapsulated in a
separate file so that an alternative can easily be dropped
in as a replacement
o All currently issued access links may be instantly
"expired" by simply changing an administration setting,
giving full control over the active lifetime of the links.
o All access failures are logged together with the reason for
the failure
o The main security weakness would be from emails going
astray or being intercepted. This can be mitigated by:
- giving access links a short lifetime
- limiting the permissions of users who are allowed this
mode of access.

* Design Features
o The module is designed to scale to over 100,000 users,
(although only tested with 15,000).
o Both users and spam detectors are suspicious of long URL's,
so every effort has been make to keep the login link as
short as possible
o For this reason, the embedding login string is only 11
characters long.
- e.g. HTTP://example.com/l/zjIR0AeOzef/blog/myarticle
o base64URL encoding has been used to avoid problems
o The link can take the user directly to any page on the site
for which they have permission
o The module is integrated with persistent_login

DIFFERENCES FROM OTHER SIMILAR MODULES
======================================

The most similar module is easylogin although the similarities
are only superficial because easylogin has an entirely different
use case. There is almost zero overlap of code between these two
projects because of the opposite approach to architecting the
solution. Both projects have valid use cases so there would be
nothing to be gained by attempting to combine them.

USE CASE

* urllogin:
o mass emailing
* easylogin:
o allowing a small number of individual users to manage their
access using a URL string

ARCHITECTURE

* urllogin:
o All encryption/decryption done on the fly
* easylogin:
o All users have an extra "password" added to the database.
User can log in by putting this "password" in a URL

ARCHITECTURE STRENGTHS

* urllogin:
o Highly secure
o Large number of users can be managed easily
o No database tables need to be created/maintained
o mass download of access strings to csv file
* easylogin:
o Detailed individual-level control possible

ARCHITECTURE WEAKNESSES

* urllogin:
o No individual control (except by permission)
o no way of re-setting an individual access string
* easylogin:
o Low Security: access strings are stored unencrypted in the
database
o No way of making access strings have an expiry date
o methodology does not scale to a large number of users
o no mass download of access strings possible

CONFIGURATION
=============

1. Set a passphrase and validation numbers on the urllogin
administration page (/admin/settings/urllogin)
2. Give the "login via URL" permission to users who are allowed
to log in with this module
3. Generate login strings (can be downloaded as a CSV file)

POSSIBLE FUTURE DEVELOPMENT
===========================

* Integration into simplemail

Licensed under the GPL 2.0.
http://www.gnu.org/licenses/gpl-2.0.txt

Comments

andrewfn’s picture

Component: Miscellaneous » miscellaneous
Status: Postponed (maintainer needs more info) » Needs review
StatusFileSize
new13.73 KB
andrewfn’s picture

Component: miscellaneous » new project application
StatusFileSize
new14.97 KB

Updated version of module: Improved documentation and tidied up help messages.

andrewfn’s picture

StatusFileSize
new60.33 KB

Attached screenshot of administration page.

andrewfn’s picture

Project: Drupal.org security advisory coverage applications » Drupal.org CVS applications

My initial description of the project seems to have lost its formatting and is hard to read. Here is the formatted version of the above description.

Description

I have developed the urllogin module for my company who would like to release it back the community.

This module provides a way to transparently log a user into the web site when they follow a link. Every effort has been made to minimize the potential security risks.

Use Case

  • The main use case is for mass emailing where it is unlikely that the recipients will go through the hassle of creating accounts and passwords. Assuming an account has been created for them, email to them contains a customized link which will automatically log them in and take them to a target page.
  • This permission would only be given to accounts with “low value” privileges (e.g. no admin, financial or access to confidential data).
  • The reason for logging users into the site would typically be so that they can do activities such as:
    • sign up for events
    • comment, rate, “like”, or otherwise interact with the site
    • unsubscribe from email or change email preferences
  • Usage tracking
    • Widely used mass email tools such as MailChimp and Campaign Monitor allow the sender to track which links in the email recipients have clicked on.
    • Using this module, Drupal’s own tracking system can be used to accomplish this, providing a far more integrated solution than provided by third-party mailers.

Features

  • Security
    • The login access link is encoded with a high level of security based on sha256
    • All encryption/decryption functions are encapsulated in a separate file so that an alternative can easily be dropped in as a replacement
    • All currently issued access links may be instantly “expired” by simply changing an administration setting, giving full control over the active lifetime of the links.
    • All access failures are logged together with the reason for the failure
    • The main security weakness would be from emails going astray or being intercepted. This can be mitigated by:
      • giving access links a short lifetime
      • limiting the permissions of users who are allowed this mode of access.
  • Design Features
    • The module is designed to scale to over 100,000 users, (although only tested with 15,000).
    • Both users and spam detectors are suspicious of long URL’s, so every effort has been make to keep the login link as short as possible
    • For this reason, the embedding login string is only 11 characters long.
      • e.g. HTTP://example.com/l/zjIR0AeOzef/blog/myarticle
    • base64URL encoding has been used to avoid problems
    • The link can take the user directly to any page on the site for which they have permission
    • The module is integrated with persistent login

Differences from other similar modules

The most similar module is easylogin although the similarities are only superficial because easylogin has an entirely different use case. There is almost zero overlap of code between these two projects because of the opposite approach to architecting the solution. Both projects have valid use cases so there would be nothing to be gained by attempting to combine them.

  urllogin easylogin
Use case mass emailing allowing a small number of individual users to manage their access using a URL string
Architecture All encryption/decryption done on the fly All users have an extra “password” added to the database. User can log in by putting this “password” in a URL
Architecture
strengths
  • Highly secure
  • Large number of users can be managed easily
  • No database tables need to be created/maintained
  • mass download of access strings to csv file
Detailed individual-level control possible
Architecture
weaknesses
  • No individual control (except by permission)
  • no way of re-setting an individual access string
  • Security: access strings are stored unencrypted in the database
  • No way of making access strings have an expiry date
  • methodology does not scale to a large number of users
  • no mass download of access strings possible

Another similar module is One-time login links which is a very minimal utility module that simply re-creates the link that a user would get had they forgotten their password and needed to re-create it.

  • This module has a very limited number of use cases because the landing page is (of necessity) the user’s account where they need to create a password.
  • This limits the use of the module to those cases where users are willing to create themselves a password as the first step to viewing the site.
  • There is no way of expiring the links if the user has not logged in before. They last indefinitely—a security risk.
  • It is not suitable for sending in mass email because experience shows that email recipients will often go back to the original email to re-gain access to the site. Drupal’s one-time link mechanism that this module utilizes will not allow this behaviour.

Configuration

  1. Set a passphrase and validation numbers on the urllogin administration page (/admin/settings/urllogin)
  2. Give the “login via URL” permission to users who are allowed to log in with this module
  3. Generate login strings (can be downloaded as a CSV file)

Possible Future Development

  • Integration into simplemail

Licensed under the GPL 2.0.
http://www.gnu.org/licenses/gpl-2.0.txt

arianek’s picture

Status: Needs review » Postponed

Hi. Please read all the following and the links provided as this is very important information about your CVS Application:

Drupal.org has moved from CVS to Git! This is a very significant change for the Drupal community and for your application. Please read the following documentation on how this affects and benefits you and the application process:
Migrating from CVS Applications to (Git) Full Project Applications

  • The status of this application will be put to "postponed" and by following the instructions in the above link, you will be able to reopen it.
  • Or if your application has been "needs work" for more than 5 weeks, your application will be marked as "closed (won't fix)". You can still reopen it, by reading the instructions above.
andrewfn’s picture

Project: Drupal.org CVS applications » Drupal.org security advisory coverage applications
Status: Postponed » Needs review

Here is a link to the sandbox project: http://drupal.org/sandbox/andrewfn/1076736

berdir’s picture

Project: Drupal.org CVS applications » Drupal.org security advisory coverage applications
Status: Needs review » Needs work

- I suggest you integrate your (awesome) project description from above into your sandbox project.

That project is not a temporary thing, it will simply be marked as a public project as soon as you're through the approving process. So everything you can do to make it look real will help you :)

You even got issue about it already which you can close after you've done that ;)

- Also, you need to remove the LICENSE.txt file, that will be automatically added by the packing script, it's not necessary that every single module on d.o has it version controlled.

- Next thing, you need to use {some_table} in all SQL queries and none of , for example this one:

    $sql="SELECT u.uid, u.mail, u.name FROM `users` AS u
            JOIN users_roles AS r ON r.uid = u.uid
            JOIN permission AS p ON p.rid = r.rid
            WHERE p.perm = 'login via url';";

Drupal needs {} to apply an eventually existing $table_prefix.

- version = "6.x-1.x-dev"
You can remove this from your .info file, it will be added automatically by the packing script.

- ; $Id: urllogin.info 102 2011-02-16 20:57:42Z andrew $
You can also remove these lines, git doesn't use them.

- function urllogin_version()
You can probably just remove that function because with git, these placeholders aren't updated anymore and the version is already visible on the modules page.

- $items['l_test'] = array(
Not sure what that test stuff is exactly doing, is that useful on a production site? If not, you might want to move it to an optional test module or something like that.

- function urllogin_uninstall() {
This needs to be in a .install file

- I think the security stuff needs review from someone with good knowledge about that stuff before it can be made public.

andrewfn’s picture

Status: Needs work » Needs review

Thanks Berdir for your very helpful review:

  • I suggest you integrate your (awesome) project description from above into your sandbox project.
    • done
  • You even got issue about it already which you can close after you’ve done that ;)
    • closed
  • Also, you need to remove the LICENSE.txt file
    • removed
  • Next thing, you need to use {some_table} in all SQL queries and none of ,
    • done
  • version = “6.x-1.x-dev” You can remove this from your .info file, it will be added automatically by the packing script.
    • removed from .info
  • ; $Id: urllogin.info 102 2011-02-16 20:57:42Z andrew $ You can also remove these lines, git doesn’t use them.
    • removed from all files
  • function urllogin_version()
    • removed
  • $items[’l_test’] Not sure what that test stuff is exactly doing, is that useful on a production site?
    • It is for testing URLs before sending out a mass emailing.
    • I have just added some documentation for this in the README.txt and on the project page under CONFIGURATION.
  • function urllogin_uninstall() This needs to be in a .install file
    • urllogin.install created
  • I think the security stuff needs review from someone with good knowledge about that stuff before it can be made public.
    • There are two aspects to the security of the module:
      1. Drupal security: i.e. does it leave the site open to XSS, buffer overflow or some other kind of attack?
      2. Encryption strength: Are there any mathematical weaknesses in the encryption algorithm?
    • The first question usually comes down to following Drupal’s security best-practices. In this case the only attack vector would be through the URL, so the question is whether data derived from the URL has been properly sanitized. I think I have done a good job, but it would be good to have a review.
    • The second question is much harder to answer because the necessary mathematical expertise is much rarer. Although I do have some experience in this area, (I was once commissioned by a bank to do a security analysis of the DES), the subject is extremely complex. That is why the module pretty much relies on SHA256 to do the security work (which is stronger than the MD5 encryption used by Drupal 6 when generating the URL in its password recovery function: user_pass_rehash()). What I have done is to follow the Drupal 7 guidelines: Use of hash functions: “For Drupal 7 modules, md5() and sha1() should never be used, since they are considered obsolete and potentially insecure for some applications. For a normal hash function use sha-256 by calling hash(’sha256’, $data).”

Thanks again for all your comments!

andrewfn’s picture

Title: andrewfn [andrewfn] » URL Login module

Changing the title to something useful.

Grayside’s picture

I took a look at this after discussing with andrewfn the distinction between this module and tokenauth in #1110002: Token Authentication difference?.

Aside from some minor whitespacing issues around parentheses, it looks pretty good. You might try running the coder module to catch that. (Example: http://drupalcode.org/sandbox/andrewfn/1076736.git/blob/HEAD:/urllogin.i...)

Two minor points worth considering, you are creating some encryption methods there, and I wonder whether it might not be better to lean on http://drupal.org/project/encrypt. Also, I find some of the page callback function names to be confusing, and wish that some of the more operational aspects of the code were handled via dedicated API functions.

andrewfn’s picture

Thanks for the review.
I had been running the module religiously against the coder module to keep it clean, and was getting zero issues. It occurred to me that you might be using the Drupal 7 coder or the online version. I tried coder (7.x-1.x-dev version) on one of my D7 sites and indeed, it caught a lot more things. I tried the online version and it was exactly the same as D7.
However neither of them caught the spacing issue you pointed out:
while ( $data = db_fetch_object($result) ) {
What version of coder were you using?

I will certainly have a look at the encrypt module.

Grayside’s picture

I didn't actually run coder, or would have known it wasn't picking up on it! :)

The whitespace pattern I saw was a space before and after parentheses. Saw maybe three different lines demonstrating it, didn't make a careful count because I thought coder would notice.

andrewfn’s picture

So coder is not quite ready to replace all humans! :)
I had a look through the style guidelines and I couldn't see anything about spaces within parentheses, so maybe coder is simply going by the book. (However it is very good at picking up missing spaces after commas in parameter lists.) So I went through by hand and corrected the lines. You are right, there were three.
Thanks!

andrewfn’s picture

#10 - I have looked at the Encrypt module. Some while ago there was a proposal to combine it with the (very similar) AES module. Since that time the AES module has been under active development and the Encrypt module has languished, so it is probably better to go with AES. A key advantage of AES is for those who do not have the ability to install mcrypt on on their webserver--it provides an alternative way of getting the required libraries.
Because of the way I have separated out the encryption aspects of URL Login, it will be very easy to integrate it with AES. I will make this an option because it does come with a disadvantage (24-character tokens instead of 12).
Thanks very much for the suggestion!

andrewfn’s picture

There was a discussion for the Encrypt module where it was decided that a good (although not perfect) place to store the passphrase is in settings.php.

The thread itself seems to have been lost in the move from cvs to git (gives a page not found) but the details of the commit can be found here:
http://drupalcode.org/project/encrypt.git/commit/baba0ec

The same ability has been added to urllogin.
Note that once an intruder has write access to the database, no solution is secure, since they can turn on the php input filter and add/modify a node to contain the php to display the passphrase. If it can be accessed from php, it can be exposed! For this reason, storing the passphrase in another file does little to improve security.

However using settings.php to store the passphrase does protect against an intruder who only has database read access (through, for example, cross site scripting).

logickal’s picture

Status: Needs review » Reviewed & tested by the community

At this point, this looks to me to be very well thought out and the code looks good to me. I'm going to mark this one reviewed at this point.

logickal’s picture

Status: Reviewed & tested by the community » Needs work

Actually, spoke a little too soon. One more pass with Coder to fix some minor code convention issues (else if, PHP constant capitalization, use of check_plain() inside l()) and you should be good to go.

andrewfn’s picture

Thanks for the review!
I'm a little confused about the coder convention issues. I ran the April 16 version of Coder on the highest setting and it didn't find any problems.

  • All of my if ... else's are in the format:
    }
    else {
      defaultaction;
    }
  • I am not defining any constants.
  • For the l() function, I usually use a t() wrapped around the first parameter which implicitly does a check_plain(). I did find one l() which didn't have a t() but when I added a check_plain(), coder gave me the following error:
    Line 136: l() already contains a check_plain() call by default. See http://drupal.org/node/28984

However, I did find an extra space in an if statement which I have corrected.
Can you point me to where you saw the problems because I have sometimes found Coder misses things.
Thanks.

logickal’s picture

Status: Needs work » Reviewed & tested by the community

Sure thing Andrew - I'm sorry, I made a hash of that whole process, apparently and got two modules I was reviewing confused. I'll go back to my original statement - "this looks to me to be very well thought out and the code looks good to me." Sorry for all of the confusion, everyone.

rfay’s picture

Status: Reviewed & tested by the community » Fixed

Git vetted user role granted - thanks for this contribution and all your future ones!

Wonderful, clear communication. Thanks for that. Please keep it up and teach others!

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.