Simple Machines Community Forum

Customizing SMF => Bridges and Integrations => Topic started by: Xteven on October 05, 2008, 02:18:59 PM

Title: Writing an external registration service for SMF
Post by: Xteven on October 05, 2008, 02:18:59 PM
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...
Title: Re: Writing an external registration service for SMF
Post by: Kindred on October 05, 2008, 04:25:19 PM
smf 2.0 supports openID
Title: Re: Writing an external registration service for SMF
Post by: Xteven on October 08, 2008, 03:35:18 PM
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.
Title: Re: Writing an external registration service for SMF
Post by: Kindred on October 08, 2008, 03:41:06 PM
ah... then you need to look at the integration arrays sticky at the top of this board.
Title: Re: Writing an external registration service for SMF
Post by: Xteven on October 09, 2008, 01:50:28 AM
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.
Title: Re: Writing an external registration service for SMF
Post by: Nathaniel on October 09, 2008, 02:07:09 AM
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.
Title: Re: Writing an external registration service for SMF
Post by: Xteven on November 01, 2008, 12:03:54 PM
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";

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 ?
Title: Re: Writing an external registration service for SMF
Post by: Orstio on November 01, 2008, 03:48:51 PM
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',
Title: Re: Writing an external registration service for SMF
Post by: Xteven on November 09, 2008, 04:02:57 PM
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.
Title: Re: Writing an external registration service for SMF
Post by: Orstio on November 09, 2008, 04:08:02 PM
Remove this:

'openid' => $escvars['openid'],
Title: Re: Writing an external registration service for SMF
Post by: Xteven on November 09, 2008, 07:16:49 PM
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 ?
Title: Re: Writing an external registration service for SMF
Post by: Xteven on November 09, 2008, 07:46:00 PM
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 :)
Title: Re: Writing an external registration service for SMF
Post by: Kindred on November 09, 2008, 08:57:06 PM
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.
Title: Re: Writing an external registration service for SMF
Post by: Xteven on November 10, 2008, 03:48:01 AM
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.
Title: Re: Writing an external registration service for SMF
Post by: Kindred on November 10, 2008, 08:06:17 AM
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.
Title: Re: Writing an external registration service for SMF
Post by: Xteven on November 10, 2008, 12:31:43 PM
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 ?
Title: Re: Writing an external registration service for SMF
Post by: Kindred on November 10, 2008, 08:01:32 PM
register them all and then turn on OpenID?
Title: Re: Writing an external registration service for SMF
Post by: Xteven on November 11, 2008, 10:20:43 AM
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 ?
Title: Re: Writing an external registration service for SMF
Post by: Xteven on November 16, 2008, 05:35:01 AM
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";

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:


Even after setting an entry in smf_openid_assoc manually, SMF still thinks the user doesn't exist.
What am I doing wrong ?
Title: Re: Writing an external registration service for SMF
Post by: Xteven on November 26, 2008, 02:03:57 AM
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...