ejabberd: Saving of roster not working with external Authentication Script enabled - perl

I have successfully configured an ejabberd server with an extauth script (perl).
It is working correctly and only allowing users from my mysql DB.
But following features are not working anymore: roster management, adding users to rosters, authorization of users (for adding them to the roster)
With the internal auth it works. Both times ejabberd is configured to use the internal amnesia db.
Please help me figure out, why it is not working with extauth enabled. Do I have to write my own methods in the extauth script? (That I don't really want...)

So after doing some research on my problem, I think that switching to the external authentication will not support roster management.
What I ended up doing is swichting back to internal authentication and using mod_admin_extra to add users and update passwords with this php script:
<?php
class Jabber
{
public static function registerAndAddToSharedRoster($userId, $sessionToken)
{
$url = "http://localhost:5280/rest";
$register = "register $userId jabber.YOUR_DOMAIN.com $sessionToken";
sendRESTRequest($url, $register);
$sharedRoster = "srg_user_add $userId jabber.YOUR_DOMAIN.com shared jabber.YOUR_DOMAIN.com";
sendRESTRequest($url, $sharedRoster);
}
public static function updatePassword($userId, $newPassword)
{
$url = "http://localhost:5280/rest";
$register = "change_password $userId jabber.YOUR_DOMAIN.com $newPassword";
sendRESTRequest($url, $register);
}
}
function sendRESTRequest ($url, $request)
{
// Create a stream context so that we can POST the REST request to $url
$context = stream_context_create (array ('http' => array ('method' => 'POST'
,'header' => "Host: localhost:5280\nContent-Type: text/html; charset=utf-8\nContent-Length: ".strlen($request)
,'content' => $request)));
$result = file_get_contents($url, false, $context);
return $result;
}
?>
Hope this helps someone!

This answer is late but it could help someone:
Contrary to #ben-marten's answer, Switching to the external authentication does support roster management.
When you add someone to the roster, ejabberd is 'calling' the isuser operation - check if it’s a valid user - you have to provide that method in the script: see ejabberd Developers Guide - External Authentication
I ignored that operation, and I could not add a user to the roster.
For other script examples see Authentication Scripts

Related

What is the best way to connect TYPO3 fe_users from an Azure AD with SAML 2?

I need to implement SSO on a TYPO3 intranet, where the fe_users are synchronized from an Azure AD. the platform will be in V9.
Is there a compatible extension that I haven't found yet ?
If no, what would be the best way to implement the automatic authentication with SAML 2.0 ?
thanks in advance,
Rachel
Thanks to #Rakel (and others) I managed to finally solve my SAML authentication requirement. Still I used a slightly different and more direct approach then described in her solution.
I used an Authentication Service to implement the SAML Login Process.
For handling the SAML login itself I used the library SimpleSamlPHP, which I can truly recommend. Its really simple and the provided frontend to test the SAML configuration comes really handy to test the Identity Provider (Idp) configuration without dealing with TYPO3.
For details please look into this: https://docs.typo3.org/m/typo3/reference-coreapi/master/en-us/ApiOverview/Authentication/Index.html
First you need to create a class which extends TYPO3\CMS\Core\Authentication\AuthenticationService. This class must implement the methods "getUser" and "authUser".
namespace Vendor\Extension\Service;
use SimpleSAML\Auth\Simple;
use TYPO3\CMS\Core\Authentication\AuthenticationService;
class SamlAuth extends AuthenticationService
{
public function getUser() {
// Create new Simple Auth with SimpleSamlPHP
$as = new Simple($config['sp']);
// Require authentication, this redirects you to the Idp and then comes back
$as->requireAuth();
// Get the attributes provides by your Idp
$attributes = $as->getAttributes();
// Please consult the API for details on fetchUserRecord
// Also the SAML attributes may vary depending on your Idp implementation
$user = $this->fetchUserRecord($attributes['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name'];
}
public function authUser(array $user): int {
return is_array($user) ? 200 : 0;
}
}
Then you need to register the service in your extensions "ext_localconf.php".
...
TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addService(
'my_extension',
'auth',
Vendor\Extension\Service\SamlAuth::class,
[
'title' => 'Saml Authentication for Frontend Users',
'description' => 'Authenticates FeUsers via Saml',
'subtype' => 'authUserFE,getUserFE',
'available' => true,
'priority' => 80,
'quality' => 80,
'os' => '',
'exec' => '',
'className' => Vendor\Extension\Service\SamlAuth::class
]
);
...
Please note:
This is just a over simplified version of my final code. Just to get you started on the idea.
Also you need to configure SimpleSamlPHP correctly. Please look at their documentation for details.
The method "getUser" is supposed to return an array holding the to be logged in FeUser with all its parameters.
The method "authUser" is only to return 200 or 0. Take a look at this link to understand which number are there to return: https://docs.typo3.org/m/typo3/reference-services/7.6/en-us/Authentication/Index.html#authentication-service-chain
After returning "200" the FeUser object is created and the user is logged in. No need to fiddle around with $GLOBALS['TSFE'] by yourself. This is a huge benefit, as it makes your code shorter and easier to read.
Nethertheless I learned a lot from reading through all the documentations and responses here and on Slacks TYPO3 channel.
Thanks to everybody who helped me. Greatly appreciated.
Yes we solved that requirements. We used SimpleSAMLphp to implement the authentication, following this great tutorial :
https://www.lewisroberts.com/2015/09/05/single-sign-on-to-azure-ad-using-simplesamlphp/.
When you are able to connect then you just have to implement a process to auto connect a fe_user when you get the saml user attributes.
Here is a simplified summary of the process:
if we reach a TYPO3 site url without being authenticated then redirection to a script like this :
// SimpleSamlPHP library
require_once (dirname(__FILE__) . /../../../../../../simplesamlphp/lib/_autoload.php');
//instanciation of a simple authentication
$as = new SimpleSAML_Auth_Simple('default-sp');
//requires authentication from Office 365
$as->requireAuth();
//retrieving information from the logged-in user
$attributes = $as->getAttributes();
//retrieve original url
$returnURL = $_GET['returnURL'];
//if a user is well connected
if($attributes){
//redirection to the TYPO3 site with the username
header('Location: /auth/?samlUident='.$attributes['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name'][0].'&recupURL='.$returnURL);
}
and here's a simplified summary of what the auth page does:
//if a get saml is in the url
if(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('samlUident')){
//recovering username for TYPO3 authentication
$loginData = array(
'uname' => \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('samlUident'), //username
'status' => 'login'
);
//TYPO3 session creation
$frontendUserAuthentication = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Authentication\\FrontendUserAuthentication');
$frontendUserAuthentication->checkPid = false;
$info = $frontendUserAuthentication->getAuthInfoArray();
$user_db = $frontendUserAuthentication->fetchUserRecord($info['db_user'], $loginData['uname']);
//if a user exists
if ($user_db){
//authentication
$GLOBALS['TSFE']->fe_user->forceSetCookie = TRUE;
$GLOBALS['TSFE']->fe_user->dontSetCookie = false;
$GLOBALS['TSFE']->fe_user->start();
$GLOBALS['TSFE']->fe_user->createUserSession($user_db);
$GLOBALS['TSFE']->fe_user->user = $user_db;
$GLOBALS['TSFE']->fe_user->setAndSaveSessionData('dummy', TRUE);
$GLOBALS['TSFE']->fe_user->loginUser = 1;
}
}
Cheers,
Rachel

Laravel Ratchet socket Auth

I am starting learning Ratchet (reactPHP) I am using laravel. But I came to a line about security.
How can I deny websocket connection based on user is logged in or not
public function onOpen(ConnectionInterface $conn)
{
$this->clients->attach($conn);
$this->users[$conn->resourceId] = $conn;
if(Auth::check()){
echo 'user logged in';
}else{
echo "New connection! ({$conn->resourceId})\n";
}
}
I used something like this but it passes the Auth::check and console always shows New Connection.
Ok Playing around found solution and it seems ok:
I am using Sentinel
$session = (new SessionManager(App::getInstance()))->driver();
$cookies = $conn->WebSocket->request->getCookies();
$laravelCookie = urldecode($cookies['timeline_auth']);
$idSession = Crypt::decrypt($laravelCookie);
$user = Sentinel::findByPersistenceCode($idSession);
If there is better solution please leave a comment
You cannot use Auth::user() anymore with WebSocket. The WebSocket server is handling multiple connections (so Auth::user() dosent have any sense). BUT you can access the user session.
more details here
https://laravel.io/forum/01-16-2015-loading-laravels-session-using-ratchet
Use laravel-ratchet package.
It will handle connection to auth conversion and laravel session for you.

How do I connect to external API from Magento

I am looking for some assistance in creating an API based module to push customer information out of Magento into a Third party loyalty program.
So far I have created a basic module but cannot find any good information on creating API based modules in Magento and could really do with some advice please...
I need to somehow hook into the Checkout success page in Magneto and add a form the will POST the customers information (name, address etc) to a third party loyalty program. I also need to be able to login to complete the billing information etc...
Does anyone know of any handy tutorials or documentation for such an implementation?
So far I have setup an API user with the appropriate roles. I have also created a very basic module for test purpses but browsing to the file I get a 404 error
apitest.php
<?php
$proxy = new SoapClient('http://mysite.com/api/?wsdl'); //edit the address and put the url to your magento here
$sessionId = $proxy->login('######', '#######'); // put in the info for your user here
echo "Login ID : $sessionId";
$result = $proxy->call($sessionId, 'Mymodule.testConnection', array('param1' => ' This string was sent from soap client'));
echo $result;
Objectmodel/api.php
<?php
class MyModule_MyModule_Model_ObjectModel_Api extends Mage_Api_Model_Resource_Abstract
{
public function testConnection($arg)
{
return "Hello World! My argument is : " . $arg;
}
}
I followed the example from here for getting a basic 'Hello world' module up and running if anyone could assist me with getting the correct setup I would be grateful
Instead of connect magento API you can create customer like this.
define('INCLUDE_PATH', '/var/www/QA/mojostage/app/');
define('INCLUDE_FILE', 'Mage.php');
Mage::app();
$customer = Mage::getModel('customer/customer');
$customer->setWebsiteId($wesite_id);
$customer->loadByEmail($customer_email);
/*
* Check if the email exist on the system.
* If YES, it will not create a user account.
*/
if (!$customer->getId()) {
//setting data such as email, firstname, lastname, and password
$customer->setEmail($customer_email);
$customer->setTaxvat($value['cus_vatnumber'])
->setCreatedAt($date1)
->setDob($value['date_of_birth'])
->setGroupId($cus_group_id)
->setConfirmation($is_active)
->setCreatedIn('Admin')
->setStoreId($store_id)
->setWebsiteId($wesite_id)
->setEntityId($value['cus_id']);
$customer->setFirstname($customer_fname);
$customer->setLastname($customer_lname);
$customer->setPassword($value['password']);
$subscriber = Mage::getModel('newsletter/subscriber');
$subscriber->setStoreId($store_id)
->setCustomerId($value['cus_id'])
->setSubscriberEmail($customer_email)
->setSubscriberStatus($value['cus_spam'])
->setSubscriberConfirmCode($subscriber->randomSequence());
}
//the save the data and send the new account email.
$customer->save();
$subscriber->save();

fetch emails with php lib that suports oauth 2

I'm trying to get mail(imap) from google by oauth authorization . I have got the authorization to work, but I can not retrieve the emails. As I understand it should be posible. But Google does not have any api to retrieve mail(?). However, I found the following:
https://developers.google.com/google-apps/gmail/oauth_overview
That says:
Accessing mail using IMAP and sending mail using SMTP is often done
using existing IMAP and SMTP libraries for convenience. As long as
these libraries support the Simple Authentication and Security Layer
(SASL), they should be compatible with the OAuth mechanism supported
by Gmail. In addition to using a library which supports IMAP and SMTP,
developers also will want to use one of the many existing libraries
for handling OAuth
Do anyone know a existing library that i can use and that has some documentation as well. Im using google-api-php-client.
The code
session_start();
ini_set('display_errors',1);
error_reporting(-1);
require_once '../../src/apiClient.php';
$client = new apiClient();
$client->setApplicationName('Mailendar');
$client->setScopes("http://www.google.com/m8/feeds/");
// Documentation: http://code.google.com/apis/gdata/docs/2.0/basics.html
// Visit https://code.google.com/apis/console?api=contacts to generate your
// oauth2_client_id, oauth2_client_secret, and register your oauth2_redirect_uri.
$client->setClientId('secret');
$client->setClientSecret('secret');
$client->setRedirectUri('secret');
$client->setDeveloperKey('secret');
if (isset($_GET['code'])) {
$client->authenticate();
$_SESSION['token'] = $client->getAccessToken();
$redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
}
if (isset($_SESSION['token'])) {
echo "token is set";
$client->setAccessToken($_SESSION['token']);
}
if (isset($_REQUEST['logout'])) {
unset($_SESSION['token']);
$client->revokeToken();
}
if ($client->getAccessToken()) {
MAGIC HAPPENS HERE!!!...but is unkown for me ofc
// The access token may have been updated lazily.
$_SESSION['token'] = $client->getAccessToken();
} else {
$auth = $client->createAuthUrl();
}
if (isset($auth)) {
print "<a class=login href='$auth'>Connect Me!</a>";
} else {
print "<a class=logout href='?logout'>Logout</a>";
}
Thanks!
Google doesnt allow you to retrieve mail with oauth 2.0 at the moment.
Now you can fetch mails using OAuth.
Implemented a simple library.
Delete mail function is not yet added. But you can take a look if it satisfies your need.
Try example. https://github.com/vmuthal/VivOAuthIMAP

Adding authentication functionality to soap server (Using Zend)?

I have a soap server that is created like so:
class ServerController extends Zend_Controller_Action
{
public function serverAction()
{
memcache_flush();
Zend_Registry::get('cache')->clean(Zend_Cache::CLEANING_MODE_ALL);
$server = new SoapServer("http://####/services/soap-server/wsdl");
$server->setClass('SOAP_Server_Map');
$server->handle();
}
}
I want to add authentication to it so that whenever anyone makes a call to a function in "SOAP_Server_Map", it checks that the credentials supplied in the SoapClient options array('login' and 'password') are valid.
Does anyone have any suggestions/help?
To add authentication to either Zend_Soap_Server or Zend_Json_Server, simply specify the HTTP authentication in either your HTTP server (ie: Apache) config or .htaccess file. The following .htaccess file should work:
AuthType Basic
AuthName "Supreme Data Services"
AuthUserFile /var/www/localhost/passwd
Require valid-user
Make sure you keep your password file out of the docroot for security purposes. The password file can be made by using htpasswd that comes with Apache. Naturally, you can use more advanced authentication types.
In order to make use of the service(s), you must now specify a username and password when making a request. If you are using Zend Framework to create your client, you can do the following for SOAP:
$client = new Zend_Soap_Client($wsdl, array('login' => $username, 'password' => $password));
And the following for JSONRPC:
$http = new Zend_Http_Client();
$http->setAuth($username, $password);
$client = new Zend_Json_Client($uri, $http);
Try this: http://pt.php.net/manual/en/soapclient.soapclient.php#101503
I have exactly the same problem and I have the following thoughts:
I do not know if SOAP is/should be state-full or stateless, can we open a session and if the user has supplied some form of credential keep her logged in for some period of time?
The other way I am thinking of solving this is through API-keys, say for example giving a key: ABCDKEY and having the url as:
http://####/services/soap-server/ABCDKEY
This introduces security risks (the magic link attack), but I've seen it implemented in RSS personalized feeds etc.
Any comments?