[Solved] Authentification with webservice

Hello,

(For the context, I’m a total beginner on Yii2 and PHP)

I try to change the authentification methode of the demo by an webservice authentification

I have two webservices : webserviceReturnOK and webserviceLogin

webserviceReturnOK return “OK” and nothing else, it’s just a test and it work.

webserviceLogin doesn’t work and return me a SoapFault (looks like we got no XML document) instead of the class User. If I return an array, it work fine (infos returned are good) but login doesn’t work (doesn’t show “logout” menu)

I’m not sure to understand how the authentification/identityInterface work…

Can I have some help?

Thanks.

Result of http;//test.mylocalhost.net/index.php?r=site/webservice




<definitions name="SiteController" targetNamespace="urn:app/controllers/SiteControllerwsdl">

	<wsdl:types>

		<xsd:schema targetNamespace="urn:app/controllers/SiteControllerwsdl">

			<xsd:complexType name="User">

				<xsd:all>

					<xsd:element name="id" type="xsd:string"/>

					<xsd:element name="username" type="xsd:string"/>

					<xsd:element name="password" type="xsd:string"/>

					<xsd:element name="authKey" type="xsd:string"/>

					<xsd:element name="accessToken" type="xsd:string"/>

				</xsd:all>

			</xsd:complexType>

		</xsd:schema>

	</wsdl:types>

        <wsdl:message name="webserviceLoginIn">

		<wsdl:part name="login" type="xsd:string"/>

		<wsdl:part name="password" type="xsd:string"/>

	</wsdl:message>

	<wsdl:message name="webserviceLoginOut">

		<wsdl:part name="return" type="tns:User"/>

	</wsdl:message>

	<wsdl:message name="webserviceReturnOKIn"/>

	<wsdl:message name="webserviceReturnOKOut">

		<wsdl:part name="return" type="xsd:string"/>

	</wsdl:message>

	<wsdl:portType name="SiteControllerPortType">

		<wsdl:operation name="webserviceLogin">

			<wsdl:documentation/>

			<wsdl:input message="tns:webserviceLoginIn"/>

			<wsdl:output message="tns:webserviceLoginOut"/>

		</wsdl:operation>

		<wsdl:operation name="webserviceReturnOK">

			<wsdl:documentation/>

			<wsdl:input message="tns:webserviceReturnOKIn"/>

			<wsdl:output message="tns:webserviceReturnOKOut"/>

		</wsdl:operation>

	</wsdl:portType>

        <wsdl:binding name="SiteControllerBinding" type="tns:SiteControllerPortType">

        <soap:binding style="rpc" transport="https;//chemas.xmlsoap.org/soap/http"/>

        <wsdl:operation name="webserviceLogin">

			<soap:operation soapAction="urn:app/controllers/SiteControllerwsdl#webserviceLogin" style="rpc"/>

			<wsdl:input>

				<soap:body use="encoded" encodingStyle="http;//schemas.xmlsoap.org/soap/encoding/" namespace="urn:app/controllers/SiteControllerwsdl"/>

			</wsdl:input>

			<wsdl:output>

				<soap:body use="encoded" encodingStyle="http;//schemas.xmlsoap.org/soap/encoding/" namespace="urn:app/controllers/SiteControllerwsdl"/>

			</wsdl:output>

		</wsdl:operation>

		<wsdl:operation name="webserviceReturnOK">

			<soap:operation soapAction="urn:app/controllers/SiteControllerwsdl#webserviceReturnOK" style="rpc"/>

			<wsdl:input>

				<soap:body use="encoded" encodingStyle="http;//schemas.xmlsoap.org/soap/encoding/" namespace="urn:app/controllers/SiteControllerwsdl"/>

			</wsdl:input>

			<wsdl:output>

				<soap:body use="encoded" encodingStyle="http;//schemas.xmlsoap.org/soap/encoding/" namespace="urn:app/controllers/SiteControllerwsdl"/>

			</wsdl:output>

		</wsdl:operation>

	</wsdl:binding>

	<wsdl:service name="SiteControllerService">

		<wsdl:port name="SiteControllerPort" binding="tns:SiteControllerBinding">

			<soap:address location="http;//test.mylocalhost.net/index.php?r=site%2Fwebservice&ws=1"/>

		</wsdl:port>

	</wsdl:service>

</definitions>

User


<?php


namespace app\models;


ini_set("soap.wsdl_cache_enabled",0);

ini_set("soap.wsdl_cache_ttl",0);


class User extends \yii\base\Object implements \yii\web\IdentityInterface

{

    /**

     * @var string

     * @soap

     */

    public $id;

    /**

     * @var string

     * @soap

     */

    public $username;

    /**

     * @var string

     * @soap

     */

    public $password;

    /**

     * @var string

     * @soap

     */

    public $authKey;

    /**

     * @var string

     * @soap

     */

    public $accessToken;

// -----------------------------------------------------------------------------  

    /**

     * @inheritdoc

     */

    public static function findIdentity($id){}

    /**

     * @inheritdoc

     */

    public static function findIdentityByAccessToken($token, $type = null){}

    /**

     * @inheritdoc

     */

    public function getId()

    {

        return $this->id;

    }

    /**

     * @inheritdoc

     */

    public function getAuthKey()

    {

        return $this->authKey;

    }

    /**

     * @inheritdoc

     */

    public function validateAuthKey($authKey)

    {

        return $this->authKey === $authKey;

    }

    /**

     * Validates password

     *

     * @param  string  $password password to validate

     * @return boolean if password provided is valid for current user

     */

    public function validatePassword($password)

    {

        return $this->password === $password;

    }

// -----------------------------------------------------------------------------    

    /**

     * Finds user by username

     *

     * @param  string      $login

     * @param  string      $password

     * @return app\models\User|null

     */

    public static function checkUser($login, $password)

    {

        // Validation par le webservice 

        $wsdl="http;//test.mylocalhost.net/index.php?r=site/webservice";

        $services=new \SoapClient($wsdl);

            

        try {        

             $userFound = $services->webserviceLogin($login,$password); // <- SoapFault here ! not catched

             if ($userFound===null){

                 return null;

             }

             $newuser = new User();

             $newuser->id = $userFound["id"];

             $newuser->username = $userFound["username"];

             $newuser->password = $userFound["password"];

             $newuser->authKey = $userFound["authKey"];

             $newuser->accessToken = $userFound["accessToken"];

                                          

             return $newuser;

        } catch (SoapFault $exc) {

            $this->addError($attribute, 'Incorrect username or password.');

        }

        return null;

    }

// -----------------------------------------------------------------------------    

    /**

     * Finds user by username

     *

     * @param  string      $username

     * @return static|null

     */

    public static function checkOK()

    {

        // Validation par le webservice 

        $wsdl="http;//test.mylocalhost.net/index.php?r=site/webservice";

        $services=new \SoapClient($wsdl);

            

        try {        

            return $services->webserviceReturnOK();

        } catch (SoapFault $exc) {

            $this->addError('Error', 'Not OK.');

        }

        return null;

    }

}



SiteController




<?php


namespace app\controllers;


use Yii;

use yii\filters\AccessControl;

use yii\web\Controller;

use yii\filters\VerbFilter;

use app\models\LoginForm;

use app\models\ContactForm;


class SiteController extends Controller

{

    public function behaviors()

    {

        return [

            'access' => [

                'class' => AccessControl::className(),

                'only' => ['logout'],

                'rules' => [

                    [

                        'actions' => ['logout'],

                        'allow' => true,

                        'roles' => ['@'],

                    ],

                ],

            ],

            'verbs' => [

                'class' => VerbFilter::className(),

                'actions' => [

                    'logout' => ['post'],

                ],

            ],

        ];

    }


    public function actions()

    {

        return [

            'error' => [

                'class' => 'yii\web\ErrorAction',

            ],

            'captcha' => [

                'class' => 'yii\captcha\CaptchaAction',

                'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,

            ],

            'webservice' => [

                'class' => 'conquer\services\WebServiceAction',

            ],

        ];

    }


    public function actionIndex()

    {

        return $this->render('index');

    }


    public function actionLogin()

    {

        if (!\Yii::$app->user->isGuest) {

            return $this->goHome();

        }


        $model = new LoginForm();

        if ($model->load(Yii::$app->request->post()) && $model->login()) {

            return $this->goBack();

        } else {

            return $this->render('login', [

                'model' => $model,

            ]);

        }

    }


    public function actionLogout()

    {

        Yii::$app->user->logout();

        return $this->goHome();

    }


    public function actionContact()

    {

        $model = new ContactForm();

        if ($model->load(Yii::$app->request->post()) && $model->contact(Yii::$app->params['adminEmail'])) {

            Yii::$app->session->setFlash('contactFormSubmitted');


            return $this->refresh();

        } else {

            return $this->render('contact', [

                'model' => $model,

            ]);

        }

    }


    public function actionAbout()

    {

        return $this->render('about');

    }

// -----------------------------------------------------------------------------    

    /**

     * @param string $login

     * @param string $password

     * @return app\models\User

     * @soap

     */

    public function webserviceLogin($login, $password)

    {

        $resultat = new app\models\User();

        

        if ($login == 'US1'){

            $resultat->id = "1";

            $resultat->username = "User1";

            $resultat->password = "****";

            $resultat->authKey = "key1";

            $resultat->accessToken = "token1";

        }

        return $resultat;

    }

    

    /**

     * @return string

     * @soap

     */

    public function webserviceReturnOK()

    {

        return 'OK';

    }

}



LoginForm


<?php


namespace app\models;


use Yii;

use yii\base\Model;


ini_set("soap.wsdl_cache_enabled",0);

ini_set("soap.wsdl_cache_ttl",0);


/**

 * LoginForm is the model behind the login form.

 */

class LoginForm extends Model

{

    public $username;

    public $password;

    public $rememberMe = true;


    private $_user = false;




    /**

     * @return array the validation rules.

     */

    public function rules()

    {

        return [

            // username and password are both required

            [['username', 'password'], 'required'],

            // rememberMe must be a boolean value

            ['rememberMe', 'boolean'],

        ];

    }


    /**

     * Logs in a user using the provided username and password.

     * @return boolean whether the user is logged in successfully

     */

    public function login()

    {

        if ($this->validate()) {

            $user = $this->getUser();


            if (!$user) {

                $this->addError('Error', 'Incorrect username or password.');

                return false;

            }            

            return Yii::$app->user->login($user, $this->rememberMe ? 3600*24*30 : 0);

        } else {

            return false;

        }

    }


    /**

     * Finds user by [[username/password]]

     *

     * @return app/models/User|null

     */

    public function getUser()

    {

        if ($this->_user === false) {

                if (User::checkOK()==="OK"){ // <- this work !

                    $this->_user = User::checkUser($this->username, $this->password);

                }

        }

        return $this->_user;

    }

}



OK, I have found an answer to my problem.

On login validation, I call the webservice. If it return a user, I create it in the database. Then the code continu like before.




    /**

     * Validates the password.

     * This method serves as the inline validation for password.

     *

     * @param string $attribute the attribute currently being validated

     * @param array $params the additional name-value pairs given in the rule

     */

    public function validatePassword($attribute, $params)

    {

        if (!$this->hasErrors()) {

            

            // Validation par le webservice 

            

            // Lien du webservice

            $wsdl="http;//test.mylocalhost.net/frontend/web/index.php?r=site/webservice";

            

            // Création de la liaison

            $services=new \SoapClient($wsdl);


            // Initialisation de la variable au cas où le webservice ne trouve rien

            $user=null;

            

            try {        

                // Appel de la fonction Login du webservice qui doit me retourner un utilisateur (ou pas)

                $userFound = $services->webserviceLogin($this->username, $this->password);

                 

                // Si des données sont retournées, on les traites

                if ($userFound<>null){

                    

                    // Suppression de l'utilisateur de la base de données locale (s'il existe)

                    $deleteUser = User::find()->where(['username'=>$this->username])->one();

                    if ($deleteUser<>null){

                        $deleteUser->delete();

                    }


                    // Création de l'enregistrement dans la base via le formulaire Signup


                    // Création du formulaire

                    $createUser = new SignupForm();

                    

                    // On rempli les champs nécessaires

                    $createUser->username = $userFound['username'];

                    $createUser->email = $userFound['email'];

                    $createUser->password = $userFound['password'];


                    // Validation du formulaire et enregistrement

                    $user = $createUser->signup();

                 }

            } catch (SoapFault $exc) {

                $this->addError($attribute, Yii::t('app', 'Incorrect username or password.'));

            }

            

            if ($user === null){

                $user = $this->getUser();

            }


            // Vérification que l'enregistrement est OK 

            if (!$user || !$user->validatePassword($this->password)) {

                $this->addError($attribute, Yii::t('app', 'Incorrect username or password.'));

            }

        }

    }