Writing an external registration service for SMF

Started by Xteven, October 05, 2008, 02:18:59 PM

Previous topic - Next topic

Xteven

Hi,

I'm trying to combine a whole lot of web services (mediawiki and SMF among others) in my website. I want to use OpenID for the authentication, but new users still would need to register an account with all components before being able to use them.

To make it easier for the user, I would like to create a single registration page that will create accounts on all of these subsystems automatically. For that, I need to know how to create OpenID-enabled accounts on all these subsystems, directly into their backend or by using some form of API.

In the case of SMF, is it possible to use some form of API to register a user ? Is it possible to block online account registrations, so all registrations would have to go through the central registration system ? Is it possible to disable the password-changing functionality in SMF (all users will use OpenID anyway, I don't want to store passwords)

Has anyone tried to build a central registration system like this ? It would seem more efficient than building O(n^2) bridges between n web services...

Kindred

Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

Xteven

Yes it does, and so does mediawiki. But both software systems still require you to create an account. With N systems, that means N registrations.
I would like to have a central system to create these accounts directly in the SMF backend. For that I need an API or some other way of doing that.

Kindred

ah... then you need to look at the integration arrays sticky at the top of this board.
Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

Xteven

As I understand it, the integration array is used to allow SMF to do all kinds of things when I register a new account in it. But then I need to make SMF the master in this process and I don't want to do that, I want something generic where SMF is "just another" subsystem where I need to create an account in.

Nathaniel

Have a read of the topic below:
http://www.simplemachines.org/community/index.php?topic=265568.0

You should be able to use SMF's 'registerMember()' function to do what you want.
SMF Friend (Former Support Specialist) | SimplePortal Developer
My SMF Mods | SimplePortal

"Quis custodiet ipsos custodes?" - Who will Guard the Guards?

Please don't send me ANY support related PMs. I will just delete them.

Xteven

I've tried using registerMember(), but I can't get it to work. I followed the instructions as best as I could but no new user gets registered.

This is the (only) code I use:

Quote
<?
require_once('/var/www/smf/SSI.php');

function smf_register($vars) {
   global $db_name, $db_prefix, $sourcedir, $boarddir;

   mysql_select_db($db_name);  //switch to SMF's database, in case these softwares are in different databases.

   foreach($vars as $var => $val) {
      $escvars[$var] = mysql_real_escape_string($val);
   }


   $regOptions = array(
      'interface' => 'admin',
      'password' => '',
      'password_check' => '',
      'check_reserved_name' => false,
      'check_password_strength' => false,
      'check_email_ban' => false,
      'send_welcome_email' => false,
      'require' => 'nothing',
      'extra_register_vars' => array(),
      'theme_vars' => array(),
      'auth_method' => 'openid',

      'username' => $escvars['username'],
      'email' => $escvars['email'],
      'openid' => $escvars['openid'],
      );

   require_once($sourcedir . '/Subs-Members.php');  //require the file, so that we can call the function
   $memberID = registerMember($regOptions);  //call the function.  $memberID should return a value.


   mysql_select_db($config["db_database"]); //back to the parent software's database...
}

$myvars['username'] = "SomeUser";
$myvars['email'] = "[email protected]";
$myvars['openid'] = "http://whatever.myopenid.com [nofollow]";

smf_register($myvars);

When I run this code, no user is created. Even worse, instead of the empty page I expect to see, I'm seeing a fullfletched SMF-themed login page with the warning "Only registered members are allowed to access this section. Please login below or register an account with MyForum Forum".

Is there a way to register a new member silently, meaning nothing is printed or displayed ? If so, how do I do that ? Where are errors logged, if any are logged at all ?

Orstio

QuoteWhen I run this code, no user is created. Even worse, instead of the empty page I expect to see, I'm seeing a fullfletched SMF-themed login page with the warning "Only registered members are allowed to access this section. Please login below or register an account with MyForum Forum".

This is because you have defined the interface as the SMF admin panel:

$regOptions = array(
      'interface' => 'admin',

Xteven

thanks for the tip. I changed my code, and the output no longer shows. However, the registration fails because the API claims OpenID authentication failed. It would be nice if it didn't require me to be authenticated with OpenID, especially because the user I'm creating will never authenticate with my own OpenID account.

Quote
An Error Has Occurred!
The OpenID address given has not been verified yet. Please log in to verify.


Maybe this is a bug ? I'm running SMF 2.0 beta 4.

Orstio


Xteven

I'm not sure what the would accomplish. I removed that field, it gave the same error.
So I also removed " 'auth_method' => 'openid',", which worked.

But as I understand it, this will not create an OpenID account but a regular account ?

Xteven

I traced the problem to Sources/Subs-Members.php in registerMember()

Quote
        // If they are using an OpenID that hasn't been verified yet error out.
        // !!! Change this so they can register without having to attempt a login first
        if ($regOptions['auth_method'] == 'openid' && (empty($_SESSION['openid']['verified']) || $_SESSION['openid']['openid_uri'] != $regOptions['openid']))
                $reg_errors[] = array('lang', 'openid_not_verified');


So this is a known bug :)

Kindred

why would you call it a bug?

If someone registers with an OpenID account, but does not verify it, then it indeed should error out.
Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

Xteven

true, if someone were to register his own account.

But I'm trying to use the SMF API. I assumed I could create accounts for other people using that API. I can't be logged in with their OpenID because I don't know the password.

Kindred

but, if you have openID associated to the account, then you have to be able to validate the OpenID.

You specified "authentication method = openID" which means that they system is going to TRY to authenticate the open ID on your registration of the user account

As I said, it's not a bug.
Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

Xteven

Maybe I should be more clear about what I plan to do with the SMF API.

Suppose I want to register 5000 users, all whom are using OpenID. What I want to do, is call registerMember 5000 times to create 5000 users. What I don't want to do, is authenticate with OpenID 5000 times, just so I can create those users.

So the question is still: how can I create a user using the SMF API ?

Kindred

Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

Xteven

Ah, that could work. I'll give it a try, thanks.

Is there also a way to keep the SMF API from printing anything out, including errors ?

Xteven

I've successfully created an account with OpenID enabled using the API with the following code:
Quote
<?
require_once('/var/www/smf/SSI.php');

function smf_register($vars) {
        global $db_name, $db_prefix, $sourcedir, $boarddir;

        mysql_select_db($db_name);  //switch to SMF's database, in case these softwares are in different databases.

        foreach($vars as $var => $val) {
                $escvars[$var] = mysql_real_escape_string($val);
        }

        #$newPassword = substr(preg_replace('/\W/', '', md5(mt_rand())), 0, 10);
        $newPassword_sha1 = "xxx"; #sha1($newPassword);

        $regOptions = array(
                'interface' => 'guest',
                'password' => $newPassword_sha1,
                'password_check' => $newPassword_sha1,
                'check_reserved_name' => false,
                'check_password_strength' => false,
                'check_email_ban' => false,
                'send_welcome_email' => false,
                'require' => 'nothing',
                'extra_register_vars' => array(),
                'theme_vars' => array(),
                'auth_method' => 'password',

                'username' => $escvars['username'],
                'email' => $escvars['email'],
                );

        require_once($sourcedir . '/Subs-Members.php');  //require the file, so that we can call the function
        require_once($sourcedir . '/Subs.php');  //require the file, so that we can call the function
        $memberID = registerMember($regOptions);  //call the function.  $memberID should return a value.

        updateMemberData($memberID, array('openid_uri' => $escvars['openid'], 'last_login' => 12345, 'hide_email' => 1, 'id_msg_last_visit' => 1));

        mysql_select_db($config["db_database"]); //back to the parent software's database...
}

$myvars['username'] = "SomeUser";
$myvars['email'] = "[email protected]";
$myvars['openid'] = "http://username.myopenid.net [nofollow]";

smf_register($myvars);

session_destroy();
?>

When I now try to login with that user using OpenID, SMF thinks the user doesn't exist and wants me to register a new account. I'm not sure why that is or how to get around it.
The user I created has the exact same values in the database table as one created using the SMF registration form.

Besides some new entries in the log tables (which I assume are not checked when a user registers?)
, the following tables are also altered when doing a normal registration instead of an API register:


  • smf_scheduled_tasks
  • smf_openid_assoc
  • smf_sessions

Even after setting an entry in smf_openid_assoc manually, SMF still thinks the user doesn't exist.
What am I doing wrong ?

Xteven

Has anyone else tried to create an OpenID account through the API ? Ran into similar problems ? I'm interested in knowing how this was solved, if it can be solved...


Advertisement: