SMF 2.0.15 external authentication

Started by anonymous001, April 13, 2019, 06:13:38 AM

Previous topic - Next topic

anonymous001

Dear users,

I'm using SMF version 2.0.15 at the moment for one of my projects.


  • The need is to get the authentication done using my own current php based application, is there some helper library to register a user with an API or some documentation how to insert the user into the SMF database?
  • Is there some code how to "login" a user using code? I would like to login a user directly using my own application, meaning no SSO from SSF,
    but vice versa


Arantor

SMF *can* be used for that, though it's really fiddly to do, and honestly I don't think we encourage it on the basis that SMF's session handling system is robust and proven after more than 15 years (including hardened against session fixation attacks, something most libraries don't actually do well)

In theory you can do it off the integrate_verify_member hook provided you return the user id of an account in SMF from the function you need to call.

The opposite, though, integrating into SMF is really easy where it's just including one file (SSI.php) and you're done for authentication, and it's fairly easy to register a new user in that situation (include Subs-Members.php, then call registerMember())

anonymous001

Dear Arantor,

thanks, where to find infos about integrate_verify_member()?
So I would use integrate_verify_member() to sign in a user?

SSI.php is used to register a new user (insert it into database).

Arantor

No, integrate_verify_member is a hook; you set it to be a function in your application so that SMF will call it during authentication. Check the manual for Integration Hooks.

And no, SSI.php is used for external integrations, you include it and the SMF user is then loaded, it's also useful as a mini bootstrap outside of SMF for accessing SMF methods in external systems.

Though honestly, I get the horrible impression that this is going to be a long, painful journey for you because you haven't given any details of your app. For example, what password storage method are you using? More or less secure than SMF's?

anonymous001

I would like to "insert" the user into the SMF users table too.
I would generate a "random" password, it's never shown to the user, in the end I would disable all SMF based login routes.

-Registration is already done, since I included the register function into the SSI.php

function ssi_RegisterUser($options)
{
require_once($sourcedir . '/Subs-Members.php');
        //call the registerMember() with parameters...


}


Now I only would like to ask how I can login / logout a user by for example username or user_id into SMF application from my own code.

Arantor

So, like I said, create a function inside your code, that can work out the current user however you do that (I have no idea since you don't seem to want to tell me anything about your app which makes it hard to help you), this function must return the user ID that would be inside SMF, then you put the name of the function in the settings table under the name 'integrate_verify_user' like the manual talks about under the integration hooks page.

I'm not being funny, but the amount of evasion about your app makes me concerned about its security and that you would be infinitely better bridging out from SMF rather than bridging into it.

anonymous001

Dear Arantor,

my application is a laravel framework based application, but this isn't that important atm.
-As I understand hooks in SMF, the whole code needs to be under the SMF dir, this will not be possible, since my own application is based under another webroot, so I'm a bit confused, how to use the hooks.

All I need at the moment is a way to login / logout a user by code and using his ID. The internal user_id is stored inside my users table of my application for sure.

anonymous001

Registration is now already done, I'm using the SMF database (so no edits to the system of SMF itself is needed) and my own application just stores the internal SMF member_id.

I've extended the SSI.php by this function:

// Custom function to login a user by the internal SMF user_id into the community
function ssi_LoginUserById($userId)
{

global $txt, $scripturl, $user_info, $user_settings, $smcFunc;
global $cookiename, $maintenance, $modSettings, $context, $sourcedir;
require_once($sourcedir . '/LogInOut.php');

// Load cookie authentication stuff.
require_once($sourcedir . '/Subs-Auth.php');

//load user details
$request = $smcFunc['db_query']('', '
SELECT passwd, id_member, id_group, lngfile, is_activated, email_address, additional_groups, member_name, password_salt, openid_uri,
passwd_flood
FROM {db_prefix}members
WHERE id_member = {string:userId}
LIMIT 1',
array(
'userId' => $userId,
)
);

$user_settings = $smcFunc['db_fetch_assoc']($request);

// Call login integration functions.
call_integration_hook('integrate_login', array($user_settings['member_name'], isset($_POST['hash_passwrd']) && strlen($_POST['hash_passwrd']) == 40 ? $_POST['hash_passwrd'] : null, $modSettings['cookieTime']));

// Get ready to set the cookie...
$username = $user_settings['member_name'];
$user_info['id'] = $user_settings['id_member'];

// Bam!  Cookie set.  A session too, just in case.
setLoginCookie(60 * $modSettings['cookieTime'], $user_settings['id_member'], sha1($user_settings['passwd'] . $user_settings['password_salt']));

// Reset the login threshold.
if (isset($_SESSION['failed_login']))
unset($_SESSION['failed_login']);

$user_info['is_guest'] = false;
$user_settings['additional_groups'] = explode(',', $user_settings['additional_groups']);
$user_info['is_admin'] = $user_settings['id_group'] == 1 || in_array(1, $user_settings['additional_groups']);

// Are you banned?
is_not_banned(true);

// An administrator, set up the login so they don't have to type it again.
if ($user_info['is_admin'] && isset($user_settings['openid_uri']) && empty($user_settings['openid_uri']))
{
$_SESSION['admin_time'] = time();
unset($_SESSION['just_registered']);
}

// Don't stick the language or theme after this point.
unset($_SESSION['language'], $_SESSION['id_theme']);

// First login?
$request = $smcFunc['db_query']('', '
SELECT last_login
FROM {db_prefix}members
WHERE id_member = {int:id_member}
AND last_login = 0',
array(
'id_member' => $user_info['id'],
)
);
if ($smcFunc['db_num_rows']($request) == 1)
$_SESSION['first_login'] = true;
else
unset($_SESSION['first_login']);
$smcFunc['db_free_result']($request);

// You've logged in, haven't you?
updateMemberData($user_info['id'], array('last_login' => time(), 'member_ip' => $user_info['ip'], 'member_ip2' => $_SERVER['BAN_CHECK_IP']));

// Get rid of the online entry for that old guest....
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}log_online
WHERE session = {string:session}',
array(
'session' => 'ip' . $user_info['ip'],
)
);
$_SESSION['log_time'] = 0;

// Just log you back out if it's in maintenance mode and you AREN'T an admin.
if (empty($maintenance) || allowedTo('admin_forum'))
redirectexit('action=login2;sa=check;member=' . $user_info['id'], $context['server']['needs_login_fix']);
else
redirectexit('action=logout;' . $context['session_var'] . '=' . $context['session_id'], $context['server']['needs_login_fix']);
}


Running the function is working, but I get redirect to the board and it says:

An Error Has Occurred!
You were unable to login. Please check your cookie settings.


It seems like there is some additional cookie check, I guess on some domain based security checks?
My appllication is running on: domain.com
My SMF installation on: smf.domain.com

SMF paths itself are all correct, no missing CSS, etc. any idea how to get the automatic login running?

Kindred

Turn on subdomain independent cookies
Сл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."

Advertisement: