Currently there is no primary key for this table. Depending on whether the user is anonymous or authenticated, the primary key will either be anon_mail + nid, or uid + nid.

Setting aside any other issues, this makes it difficult to build other modules which contain a foreign key reference to the signup_log table.

I have encountered another problem in a module I am writing. This module will generate a URL which can be used to cancel a signup, and which can be included in the confirmation email message. In order to make that work in a relatively secure manner, I would like a non-obvious way of identifying the signup to cancel: in other words I do not want to include the user's email address, never mind both their email address and the signup's nid, as part of the URL. Having a numeric primary key that I could expose in the URL would solve this problem.

I have created a patch which adds a new auto-incrementing (serial) primary key to the signup_log table. Since it is the id for a signup, I have called the column sid.

I have tested this with MySQL. Although I believe the code is correct for postgre, I would appreciate somebody else checking it since I do not have experience with that database.

Comments

Sid_M’s picture

StatusFileSize
new1.87 KB
dww’s picture

Category: bug » task

I'm not convinced this is a bug, but I agree something like this would probably be worth adding. For example, it'd provide most of the solution for #325237: Allow users (even anonymous) to cancel signup via secure URL.

That said, please don't write your external module to be insecure by taking URLs like http://example.com/cancel-signup/sid. That provides all sorts of potential for abuse and CSRF. If sid is a monotonically increasing integer, it's trivial to guess the sid for other signups and cancel other people's signups, etc. Bad, bad. Instead, you want to use a "signup token". Something like:

function signup_get_token($sid) {
  $private_key = drupal_get_private_key();
  return md5('signup_token' . $sid . $private_key);
}

function signup_valid_token($token, $sid) {
  $private_key = drupal_get_private_key();
  return $token == md5('signup_token' . $sid . $private_key);
}

Then, in the signup confirmation email, you'll know the sid, so you can generate the right token and create a URL like http://example.com/cancel-signup/sid/token -- the menu handler for that URL can then validate the token based on the sid and either allow or deny the request.

In fact, I'd rather this functionality (a secure way to cancel a signup via a given URL) was in signup itself instead of an external module -- so after I add the numeric sid here, let's move the rest of this discussion over to #325237 to provide a secure signup-cancel URL.

Sid_M’s picture

Thanks for the thoughtful response. Rereading my message, I see why you said what you did about the URL. In fact, the module I wrote does something pretty similar to what you suggested. I'm moving the rest of the conversation to the other thread, as suggested.

dww’s picture

Version: 6.x-1.0-rc1 » 6.x-2.x-dev
Status: Needs review » Fixed
StatusFileSize
new1.45 KB

This patch had a few fatal flaws:

A) 'serial' fields (e.g. auto_increment in MySQL) cannot have a DEFAULT value of 1.

B) The DB update should use db_add_field() instead of trying to manually alter the tables to add the new field.

I fixed both, renumbered the update (6200), tested the upgrade path and a new install, and this is all working now. Earlier tonight I created the DRUPAL-6--1 branch for the 6.x-1.* stable series, and I just created a 6.x-2.x-dev release node pointing to HEAD. So, I committed the attached patch to HEAD as the first new feature for 6.x-2.*. Thanks!

dww’s picture

Version: 6.x-2.x-dev » 6.x-1.x-dev

FYI: After further consideration, I just backported this (and related changes) into DRUPAL-6--1: http://drupal.org/cvs?commit=159750

Status: Fixed » Closed (fixed)

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