yii-user extension include(WebUser.php) No such file or directory - yii

i'm trying to install the extension of yii-user following this official tutorial
http://www.yiiframework.com/extension/yii-user/#hh2
But i'm having some problems, specially when i'm adding this
user'=>array(
// enable cookie-based authentication
'class' => 'WebUser',
'allowAutoLogin'=>true,
'loginUrl' => array('/user/login'),
to the configuration main. When i add this code, i have this message error
include(WebUser.php) [function.include]: failed to open stream: No such file or directory
Any clue? I need to do something before?
Thanks in advance

I searched a little bit and i found the solution. But it wasn't in the documentation.
So, we should create the WebUser.php in protected/components like this :
<?php
// this file must be stored in:
// protected/components/WebUser.php
class WebUser extends CWebUser {
// Store model to not repeat query.
private $UserLogin;
// Return first name.
// access it by Yii::app()->user->first_name
function getFirst_Name(){
$user = $this->loadUserLogin(Yii::app()->user->user_id);
return $user->first_name;
}
// This is a function that checks the field 'role'
// in the User model to be equal to 1, that means it's admin
// access it by Yii::app()->user->isAdmin()
function isAdmin(){
$user = $this->loadUser(Yii::app()->user->user_id);
return intval($user->user_role_id) == 1;
}
// Load user model.
protected function loadUserLogin($id=null)
{
if($this->UserLogin===null)
{
if($id!==null)
$this->UserLogin=UserLogin::model()->findByPk($id);
}
return $this->UserLogin;
}
}?>
and should work.

Did you follow the instructions at http://www.yiiframework.com/extension/yii-user/#hh2?
You probably forgot to specify import paths to the user module in config.php
'import'=>array(
...
'application.modules.user.models.*',
'application.modules.user.components.*',
),

I had the same problem and found that it's the permission problem. Apache user (www-data in my case) couldn't access protected/modules/users/* files.

Related

Laravel 8 Jetstream: unable to login with the account seeded using factories and seeder

I am working on a Laravel 8 project. I have noticed that a couple of things have changed including authentication. I am using Jetstream for authentication.
I have installed the Jetstream and I can register and login going to the route /register and /login on the browser. What I am doing now is that for local development, I am creating seeder class so that I can seed the users and log in using those seeded users for local development. But when I log in using those account, it is always complaining that "These credentials do not match our records.".
This is what I have done. I have registered an account on browser using password, "Testing1234". The password hash is saved in the users table. I copied the password and use it in the UserFactory class as follow.
<?php
namespace Database\Factories;
use App\Models\Role;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
class UserFactory extends Factory
{
use WithFaker;
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = User::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
return [
'name' => $this->faker->name,
'email' => $this->faker->unique()->safeEmail,
'email_verified_at' => now(),
'password' => '$2y$10$tive4vPDzIq02SVERWxkYOAeXeaToAv57KQeF1kXXU7nogh60fYO2', //Testing.1234
'remember_token' => Str::random(10),
];
}
}
Then I created a user using factory as follow.
User::factory()->create(['email' => 'testing#gmail.com']);
Then I tried to log in using the user I just created. But it is always complaining, "These credentials do not match our records.". I cannot use the other passwords too. Even the default password that comes with the default user factory class. What is wrong with my code and how can I fix it?
Try using
User::factory()->make([
'email' => 'testing#gmail.com',
]);
I have finally found the issue.
In the JetstreamServiceProvider class, I have added the following code to customise the login flow.
Fortify::authenticateUsing(function (Request $request) {
});
My bad. That is what makes it failing.

Why is the callback identifier not being invoked?

I'm trying to implement matching a Kerberos authentication with a local user database in CakePHP4. So I installed CakePHP 4 and the Authentication plugin 2.0. Since Kerberos auth is managed by our IIS WebServer, only thing I have to do is check if the authenticated user is known by my webapp.
The callback authentication should let me implement something like this, right ?
So I put this function in Application.php :
<?php
public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
{
$service = new AuthenticationService();
// Define where users should be redirected to when they are not authenticated
$service->setConfig([
'unauthenticatedRedirect' => '/users/login',
'queryParam' => 'redirect',
]);
// Load the authenticators. Session should be first.
$service->loadAuthenticator('Authentication.Session');
$service->loadIdentifier('Authentication.Callback', [
'callback' => function($data) {
// do identifier logic
if (empty($_SERVER['REMOTE_USER'])) {
return new Result(
null,
Result::FAILURE_OTHER,
['message' => 'Unknown user.']
);
} else {
// On vérifie que l'utilisateur est autorisé à utiliser cette application
$users = TableRegistry::getTableLocator()->get('Users');
$remoteUserNoDomain = str_replace("DOMAIN\\", "", $_SERVER['REMOTE_USER']);
$result = $users->find()
->where(['username' => $remoteUserNoDomain]);
if ($result) {
return new Result($result, Result::SUCCESS);
}
return new Result(
null,
Result::FAILURE_OTHER,
['message' => 'Removed user.']
);
}
return null;
}
]);
return $service;
}
But so far, it doesn't seem to work, like it won't call the callback function at all. I tried to put some debug code, exits... Nothing works.
I would assume that you've also done all the other required configuring for authentication to work, ie loading the plugin, adding the authentication middleware, etc.!?
https://book.cakephp.org/authentication/2/en/index.html
That said, identifiers do not do any work on their own, they are being triggered by authenticators in case they actually require them. You only have the Session authenticator loaded, which in its default configuration doesn't make use of identifiers, but even if you configure it to use identifiers (by setting its identify option to true), it will only use them when there already is an identity in the session, then the identifier is being used to validate that identity.
https://github.com/cakephp/authentication/blob/2.3.0/src/Authenticator/SessionAuthenticator.php#L52
I'm not familiar with Kerberos authentication, but if it pre-populates $_SERVER['REMOTE_USER'] (btw. never access superglobals in CakePHP directly, it will only cause trouble down the road), then what you need is a custom authenticator. You could then re-use the password identifier for the ORM access part, as it allows finding something without checking the password (weirdly enough, given its name).
Quick and dirty example based on your snippet:
// src/Authenticator/KerberosAuthenticator.php
namespace App\Authenticator;
use Authentication\Authenticator\AbstractAuthenticator;
use Authentication\Authenticator\Result;
use Authentication\Authenticator\ResultInterface;
use Psr\Http\Message\ServerRequestInterface;
class KerberosAuthenticator extends AbstractAuthenticator
{
public function authenticate(ServerRequestInterface $request): ResultInterface
{
$server = $request->getServerParams();
if (empty($server['REMOTE_USER'])) {
return new Result(null, Result::FAILURE_CREDENTIALS_MISSING);
}
$remoteUserNoDomain = str_replace("DOMAIN\\", "", $server['REMOTE_USER']);
$user = $this->_identifier->identify(['username' => $remoteUserNoDomain]);
if (empty($user)) {
return new Result(
null,
Result::FAILURE_IDENTITY_NOT_FOUND,
$this->_identifier->getErrors()
);
}
return new Result($user, Result::SUCCESS);
}
}
Your service authenticator/identifier setup would then look like this:
$service->loadAuthenticator('Authentication.Session');
$service->loadAuthenticator('Kerberos');
$service->loadIdentifier('Authentication.Password');
Nore sure if you'd then really want to use the session authenticator like that though, ie whether you only want to identify the remote user once per session.

How to allow to unauthenticated users see some specific pages or actions pages in Cake PHP 3?

With CakePHP 3 we used Auth component and this worked like this CakePHP - How to allow unauthenticated access to specific pages
Now I'm trying to use the new Authentication and Authorization plugins instead (I don't know if it is the best solution).
I have this case:
I have some tables in the database for entities (cars, brands, and users). I have users and 4 level user roles (pyramid).
- Admins can change everything
- Editors can see and add brands and cars, but only can edit or update cars and brands created by themselves.
- Registered users can add only cars and edit their cars (and see all cars and brands).
- Anonymous users can see all but only can create a user account.
Authentication works well alone. To allow anonymous user access to content I use $this->Authentication->allowUnauthenticated(['login', 'add']); but when I load Authorization plugin, everything give error.
Do I need to specify all Authorization access with authorizeModel and other functions? There is a way to authorize at the same time with both plugins? Do I really need Authorization plugin for this and is recommended or Authentication plugin can handle this?
With previous Auth component I worked with something like this piece of code:
In AppController.php
public function beforeFilter(Event $event)
{
$this->Auth->allow(['view', 'display']);
}
public function isAuthorized($user)
{
return true;
}
In UsersController.php
public function beforeFilter(Event $event)
{
parent::beforeFilter($event);
$this->Auth->allow('add', 'logout');
}
In Cars and Brands controllers
public function isAuthorized($user)
{
if (isset($authUser['role']) && $authUser['role'] === 'admin') {
return true;
}
if ($this->request->action === 'add') {
return true;
}
if ($this->request->action === 'index') {
return true;
}
if (in_array($this->request->action, ['edit'])) {
$carId = (int)$this->request->params['pass'][0];
if ($this->Cars->exists(['id' => $carId, 'user_id' => $authUser['id']])) {
return true;
}
}
return false;
}
Followed from https://book.cakephp.org/3/es/tutorials-and-examples/blog-auth-example/auth.html
My versions are:
- CakePHP 3.8
- Authentication plugin 1.4
- Authorization plugin 1.3
Sorry if my question is a bit basic but documentation is not very clear with this. I can add more details if needed.
Edit: If I quit unauthenticatedRedirect I get:
No identity found. You can skip this check by configuring `requireIdentity` to be `false`.
Authentication\Authenticator\UnauthenticatedException
If I add requireItentity as false, in AppController
$this->loadComponent('Authentication.Authentication', [
'requireIdentity' => false
]);
I get (where / is the path, can be /cars /brands)
The request to `/` did not apply any authorization checks.
Authorization\Exception\AuthorizationRequiredException
If I use this in AppController (always Authentication before Authorization)
$this->loadComponent('Authentication.Authentication', [
'requireIdentity' => false
]);
$this->loadComponent('Authorization.Authorization', [
'skipAuthorization' => [
'login',
]
]);
and this in Application
$service->setConfig([
'unauthenticatedRedirect' => \Cake\Routing\Router::url('/users/login'),
'queryParam' => 'redirect',
]);
I send all users to login page but authorization checks error appears.
With $this->Authorization->skipAuthorization(); in beforeFilter() user can see the pages and works but I don't know if it is appropriated.
If I use this in any controller beforeFilter $this->Authorization->authorizeModel('index', 'add', 'display' ...);
I get
Policy for `App\Model\Table\CarsTable` has not been defined.
Authorization\Policy\Exception\MissingPolicyException
In home (or pages controller) I get
Policy for `Cake\ORM\Table` has not been defined.
Authorization\Policy\Exception\MissingPolicyException
Do I really need to create policies for each table? I think is more complex than previous Auth component or maybe I'm doing something wrong.

How do I access the oauth2 authenticated user in a Lumen controller?

I have followed this excellent tutorial Building a Web App with Lumen and OAuth2 for setting up OAuth2 and Lumen. Everything is working fine apart from now I want to access the currently authenticated user information/model.
My route correctly posts the supplied information after I have logged in and I can break with Netbeans inside the controller but I am not clear how to get the user from the underlying Auth framework. I have tried the three methods indicated here Authentication - Laravel but to no avail. The lumen logs shows:
==== routes.php ====
$app->group(['namespace' => 'App\Http\Controllers','prefix' => 'api', 'middleware' => 'oauth'], function($app)
{
$app->post('info', 'InfoController#send');
}
==== InfoController.php ====
namespace App\Http\Controllers;
// the controllers
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Contracts\Auth\Authenticatable;
class InfoController extends Controller{
/* /api/info methods */
public function send(Request $request){
// can iterate over the entire users table but I just
// want the current user (must be some method through
// the authentication stack)
$users = \App\Auth\User::all();
foreach ($users as $user) {
$name = $user->name;
$key = $user->getAuthIdentifier();
$pwd = $user->getAuthPassword();
}
// CODE GETS HERE BUT how to get the current user?
// Authenticated OK (request supplies "Access-Token: Bearer ...")
}
}
This is probably not the cleanest solution and may not match your requirements exactly but it does retrieve the user.
I decided to make another DB query in the proxy to get the user with the same key (in my case, email address) that was requested by the client.
In my case I was sending the user id along with the standard oauth token.
You could use the same technique to set some value in the session.
// ../app/Auth/Proxy.php
namespace App\Auth;
use App\User; // ----- added this line
use GuzzleHttp\Client;
class Proxy {
...
private function proxy($grantType, array $data = [])
{
...
$response = json_decode($guzzleResponse->getBody());
if (property_exists($response, "access_token")) {
...
// added the following line to get the user
$user = User::where('email',$data['username'])->get()->first();
// untested, but you could add the user to your session here
$request = app()->make('request');
$request->session()->put('current_user', $user);
$response = [
'accessToken' => $response->access_token,
'accessTokenExpiration' => $response->expires_in,
'userId' => $user->id,
];
}
...

Phalcon forward to different module

Trying to work my way through setting up a phalcon mvc application.
I have 2 modules current set up for testing. "Frontend" and "Admin".
I have different views set up so I can confirm I am getting through to each of the modules. When I change the defaultnamespace and defaultmodule I can indeed see that both modules are being accessed fine and loading ok. I can see that the admin controllers are being accessed correctly and the frontend controllers are being accessed when I change this.
The problem I am currently having is when I try to authenticate a user and start the session I want to forward the request over from "Frontend" to "Admin":
return $this->dispatcher->forward(array(
'namespace' => 'Qcm\Admin\Controllers',
'action' => 'index',
'controller' => 'index'
));
Again I have confirmed these namespaces work fine. The problem is when I now forward onto the new namespace it can no longer find the admin index controller?
"Qcm\Admin\Controllers\IndexController handler class cannot be loaded"
However I have already confirmed that I can switch between the modules by changing the defaultnamespace/defaultmodule. Is this a limitation within the dispatcher that I can not forward to a different module?
Just to clarify I am also using the same url's so for example after login I want it to go back to '/' (root) but because it has forwarded to the admin module this should work fine correct?
The phalcon dispatcher can only forward to actions within the same module. It cannot forward you outside the current module. This restriction comes because the dispatcher is only aware of the module in which it is declared.
In order to forward to another module, you must instead return a redirect response from a controller action. In my case, I wanted to forward the user to a login screen or a 404 error page based on their ACL permissions in the beforeDispatch() method of a plugin. The dispatcher is native to this method, but cannot forward the user outside of the current module. Instead, I have the dispatcher forward the user to a controller in the same module that has a custom action that in turn performs the redirect.
// hack to redirect across modules
$dispatcher->forward(
array(
'controller' => 'security',
'action' => 'redirect',
'params' => array(
'redirect' => '/home/index/login'
),
)
);
return false; // stop progress and forward to redirect action
This means that each module needs to have a copy of this custom redirect action in one of its controllers. I accomplished this by putting the action in the base controller that all of my controllers extend from.
/**
* the phalcon dispatcher cannot forward across modules
* instead, forward to this shared action which can then redirect across modules
* */
public function redirectAction(){
$this->view->disable();
$params = $this->dispatcher->getParams();
$redirect = '/';
if( ! empty( $params['redirect'] ) ){
$redirect = $params['redirect'];
}
return $this->response->redirect( $redirect );
}
Because phalcon didn't add all modules to global loader, so the namespace is not registered. you need to register another module in current module bootstrap file, modify your Module.php as
class Module
{
public function registerAutoloaders()
{
$loader = new \Phalcon\Loader();
$loader->registerNamespaces(array(
//Your current module namespaces here
....
//Another module namespaces here
'Qcm\Admin\Controllers' => 'controller path',
));
$loader->register();
}
}
The main reason it shows IndexController class not loaded is because you might not have added Dispatcher in that module or in the bootstrap file(depending on your approach)
Add
$debug = new \Phalcon\Debug();
$debug->listen();
to your code before
$application->handle()->getcontent();
to view erros.
Before the replacement line:
echo $application->handle()->getContent();
code:
$router = $this->getDi()->get("router");
$params = $router->getParams();
$modName = $router->getModuleName();
$url = null;
if ($modName == "admin" && isset($params[0])) {
$module = "/" . $params[0];
$controller = isset($params[1]) ? "/" . $params[1] . "/" : null;
$action = isset($params[2]) ? $params[2] . "/" : null;
$params = sizeof($params) > 3 ? implode("/", array_slice($params, 3)) . "/" : null;
$url = $module . $controller . $action . $params;
}
echo $application->handle($url)->getContent();