Cakephp 3 and Authentication - authentication

Is there an easy way like in Cakephp 3 to work with roles
APP Controller
public function isAuthorized($user)
{
// Admin can access every action
if (isset($user['role']) && $user['role'] === 'admin') {
return true;
}
// Default deny
return false;
}
POSTS Contoller
public function isAuthorized($user) {
// All registered users can add posts
if ($this->action === 'edit') {
return true;
}
return parent::isAuthorized($user);
}
I know from http://book.cakephp.org/3.0/en/controllers/components/authentication.html#testing-actions-protected-by-authcomponent that
$this->auth->deny('add');
Is doing it, but how can I add the user/admin ?

I have used ACL authentication in very simple way with isAuthorised() method. I hope it would be help you.
AppController.php
you can make have to define property
/**
* ACCESS CONTROL LIST BASED ON METHODS OF CLASS FOR USER ROLES
*/
var $accessControllList = array();
Define private method
private function _checkAccessControll() {
if ($this->Auth->user('id')) {
if (!isset($this->accessControllList) || empty($this->accessControllList)) {
return true;
}
$action_name = $this->request->params['action'];
$user_role = $this->Auth->user('role');
if (isset($this->accessControllList['allowed']) && !empty($this->accessControllList['allowed']) && in_array($action_name, $this->accessControllList['allowed'])) {
return true;
} else if (isset($this->accessControllList['role_base'][$user_role]) && !empty($this->accessControllList['role_base'][$user_role]) && in_array($action_name, $this->accessControllList['role_base'][$user_role])) {
return true;
}
throw new \Cake\Network\Exception\ForbiddenException(__('You not have access for this page'));
}
return true;
}
in isAuthorized() add below line.
$this->_checkAccessControll();
In any controller, you need to mapping your ACL with roles. For you PostsController.php file something as below
/**
* List of all accessible Action from URL
* #var array
*/
var $accessControllList = array(
'allowed' => array('view','index'), // allowed for any role.
'role_base' => array(
'administrator' => array('delete', 'approve'), //specially allowed for administrator only
'publisher' => array('view','create','index','replyComment'), // specially allowed for publisher only
'reader' => array('postComment','replyComment') // specially allowed for reader
)
);

Related

How to check permissions in my controller

I'm new to Laravel and I'm writing a user management System on my own.
At this time,
I can CRUD permissions, roles and users,
I can check the permissions by the AuthServiceProvider#boot method like this:
public function boot()
{
Gate::before( function (User $user , $permission) {
// App administrator
if($user->getPermissions()->contains('appAll'))
{
return true;
}
// Permission check
return $user->getPermissions()->contains($permission);
});
}
In my AdminUserController, I can check the permissions like that:
public function index()
{
if( Gate::check('createUser') || Gate::check('readUser') || Gate::check('updateUser') || Gate::check('deleteUser')) {
return view('userMgmt/users/index', [
'users' => User::getUsersWithRolesWithTexts()
]);
}
else
{
return redirect(route('home'))->withErrors('You do not have required permission');
}
}
That is working well.
BUT
Is this the right way to wrap each controller method with:
if( Gate::check(...) ...) {
//Do what the method is supposed to do
}
else
{
return redirect(route('SOME.ROUTE'))->withErrors('SOME ERROR OCCURRED');
}
It would be nice if someone can give me some ideas.
Tank you
There is a controller helper function named authorize that you can call from any method in a controller that extends App\Http\Controllers\Controller. This method accepts the action name and the model, and it will throw an exception if the user is not authorized. So instead of the if...else statement, it will be one line:
public function update(Request $request, Post $post)
{
$this->authorize('update', $post);
// The current user can update the blog post...
}

How to login using sql password() function in laravel?

I want to login using the sql password() function in laravel. This is because the master database of employee table contains password in the format insert into tbl_name(' ') values (' ', password('abc'));
So I need to use this master table for login so can anyone suggest me as to how can this be possible?
public function login(Request $request) {
// dd($request->all());
if(Auth::attempt([
'tgi' => $request->tgi,
'password' => $request->password
]))
{
// $user = \DB::where('tgi', $request->tgi)->first();
$user = MasterLogin::where('tgi', $request->tgi)->first();
if($user->is_admin() == '1') {
return redirect()->route('dashboard');
}
elseif($user->is_admin() == '0'){
return redirect()->route('home');
}
elseif($user->is_admin() == '3'){
return redirect()->route('manager');
}
}
return redirect()->back();
}
public function validateCredentials(UserContract $user, array $credentials)
{
$plain = $credentials['password'];
return $this->hasher->check($plain, $user->getAuthPassword());
}
In validateCredentials i would like to know how can I pass the password here.
As of now I tried this as said:
public function login(Request $request) {
// dd($request->all());
if(Auth::attempt([
'tgi' => $request->tgi,
'password' => sha1($request->password)
]))
{
$user = User::select("SELECT * FROM emp_username_db WHERE tgi = $request->tgi AND password = sha1('$request->password')");
if (Hash::check(sha1($request->password), $user['password'])) {
// The passwords match...
return redirect()->route('dashboard');
}
}
return redirect()->back();
}
My code that I am working on
class LoginController extends Controller
{
public function login(Request $request) {
//$user = User::where('tgi', $request->tgi)->first();
$result = User::where('tgi',$request->tgi)->where('password',\DB::raw('password("$request->password")'))->exists();
if ($result) {
if($result->is_admin() == '1'){
// Authentication passed...
return redirect()->intended('dashboard');
}elseif($result->admin == '0'){
return redirect()->route('home');
}
elseif($result->admin == '3'){
return redirect()->route('manager');
}
return redirect()->back();
}
}
As SQL default password is hashed using SHA1 so we can compare user's password by using laravel raw query like this.
$result = User::where('tgi',$request->tgi)->where('password',\DB::raw('password("$request->password")'))->exists();
if($result){
your code....
}
It's redirecting to dashboard but getting 302 found.

Phalcon keep a model persistant in all the controllers?

my website application is mostly model around a User Model which has all the key data that needed for most of the times.
Once the user is logged into the website I would like to keep it as a persistent variable across all the controllers. How do i achieve this as i cannot use session to hold a class object of Type Model.
My application is based on phalcon. However any suggestions are welcome.
I suggest you to write a simple class for user authentication & other user data manipulation, i wrote this Component and using in my project :
use Phalcon\Mvc\User\Component;
class Auth extends Component {
public function login($credentials) {
if(!isset($credentials['email'],$credentials['password'])) {
return FALSE;
}
if($this->isAuthorized()) {
return true;
}
$user = Users::findFirstByEmail($credentials['email']);
if($user == false) {
//block user for seconds
return false;
}
if($this->security->checkHash($credentials['password'],$user->password) && $user->status == 1) {
$this->_saveSuccessLogin($user);
$this->_setUserLoginSession($user);
return true;
} else {
return false;
}
}
public function isAuthorized() {
return $this->session->has('auth');
}
public function logout() {
$this->session->remove('auth');
return true;
}
public function user($key = null) {
if(!$this->isAuthorized()) {
return null;
}
if(is_null($key)) {
return $this->session->get('auth');
} else {
$user = $this->session->get('auth');
return array_key_exists($key, $user) ? $user[$key] : null;
}
}
private function _saveSuccessLogin(Users $user){
$userLogin = new UserLogins();
$userLogin->user_id = $user->id;
$userLogin->ip = $this->request->getClientAddress();
$userLogin->user_agent = $this->request->getUserAgent();
$userLogin->dns = gethostbyaddr($userLogin->ip);
if(!$userLogin->save()) {
return false;
}
return true;
}
private function _setUserLoginSession(Users $user) {
if(!$user) {
return false;
}
$this->session->set('auth',array(
'id' => $user->id,
'firstname' => $user->firstname,
'lastname' => $user->lastname,
'email' => $user->email,
'role_id' => $user->role_id
));
return true;
}
}
And in my services.php added into DI with this code :
$di->setShared('auth', function () {
return new Auth();
});
So when i want to get user info i use this :
$this->auth->user('email')
Also you can add more functionality to this component & modify it.
I hope that's useful for You.
You can use memcached and save it as key => value:
userId => serialized User model

Where do i override authentication method in yii?

I need to override both authentication (for when user's trying to logging in) and also the function is being used to check if the user is logged in in the header of the application (the function that check the sessions and cookie to check if the user is logged in) but i don't know where are these methods? and also i don't know how to find where are these methods!
** The reason of ovveride is to also check a Flag, if the flag is FLASE don't authenticate the user, or even if the user is also authenticated on page change (header reload) log-out the user if the flag changed to FLASE**
It would be appreciated if you also helping me to find adequate references that can help me in similar situations beside yii/wiki and google i tried them :)
Regards,
For custom authentication extend CUserIdentity class:
app/components/UserIdentity.php
<?php
class UserIdentity extends CUserIdentity
{
const ERROR_USER_NOT_APPOVED=200;
private $_id;
/**
* Authenticates a user.
*
* #return boolean whether authentication succeeds.
*/
public function authenticate()
{
$criteria = new CDbCriteria;
$criteria->condition = 'LOWER(email.email)=LOWER(:email)';
$criteria->params = array(':email' => $this->username);
$member = Member::model()
->with('email')
->together()
->find($criteria);
if ($member === null) {
$this->errorCode = self::ERROR_USERNAME_INVALID;
} elseif (!hash::check($this->password, $member->pass_hash)) {
$this->errorCode = self::ERROR_PASSWORD_INVALID;
} elseif (! $member->is_approved) {
$this->errorCode = self::ERROR_USER_NOT_APPOVED;
} else {
$this->_id = $member->id;
$this->username = $member->full_name;
$this->setState('email', $member->email->email);
$this->errorCode = self::ERROR_NONE;
}
return !$this->errorCode;
}
/**
* #return integer the ID of the user record
*/
public function getId()
{
return $this->_id;
}
}
then create custom form (app/models/MainLoginForm.php):
<?php
/**
* MainLoginForm class.
* MainLoginForm is the data structure for keeping
* user login form data.
*/
class MainLoginForm extends CFormModel
{
public $email;
public $password;
public $rememberMe;
/**
* Declares the validation rules.
* The rules state that email and password are required,
* and password needs to be authenticated.
*/
public function rules()
{
return array(
array('email', 'filter', 'filter' => 'trim'),
array('email', 'required',
'message' => Yii::t('auth', 'Email address is required.')),
array('email', 'email',
'message' => Yii::t('auth', 'Enter a valid Email address.')),
array('password', 'required',
'message' => Yii::t('auth', 'Password is required.')),
// password needs to be authenticated
array('password', 'authenticate'),
array('rememberMe', 'safe'),
);
}
/**
* Declares attribute labels.
*/
public function attributeLabels()
{
return array(
'email' => Yii::t('auth', 'Email Address'),
'password' => Yii::t('auth', 'Password'),
'rememberMe' => Yii::t('auth', 'Remember me.'),
);
}
/**
* Authenticates the password.
* This is the 'authenticate' validator as declared in rules().
*/
public function authenticate($attribute, $params)
{
// we only want to authenticate when no input errors
if (! $this->hasErrors()) {
$identity = new UserIdentity($this->email, $this->password);
$identity->authenticate();
switch ($identity->errorCode) {
case UserIdentity::ERROR_NONE:
$duration = ($this->rememberMe)
? 3600*24*14 // 14 days
: 0; // login till the user closes the browser
Yii::app()->user->login($identity, $duration);
break;
default:
// UserIdentity::ERROR_USERNAME_INVALID
// UserIdentity::ERROR_PASSWORD_INVALID
// UserIdentity::ERROR_MEMBER_NOT_APPOVED
$this->addError('', Yii::t('auth',
'Incorrect username/password combination.'));
break;
}
}
}
}
and finally update your login method (actionLogin):
$form = new MainLoginForm;
if (isset($_POST['MainLoginForm'])) {
$form->attributes = $_POST['MainLoginForm'];
$valid = $form->validate();
if ($valid) {
// redirect
}
}
For auto logout you can extend CController:
app/components/MainBaseController.php
<?php
class MainBaseController extends CController
{
public $settings = array();
public function init()
{
parent::init();
// set global settings
// $this->settings = ...
if (YOUR_FLAG_VALIDATION AND !Yii::app()->user->isGuest) {
Yii::app()->user->logout();
}
}
}
and then use custom base controll:
class YourController extends MainBaseController
{
....
}

how to get or create role in yii

I am a newbie to yii. I have stuck my mind with yii-tutorials for creating roles in yii. but I am not getting how can I create role in yii. means I want to create two roles admin & staff and I want to give different priviliage to them.
I have created a role in user table, but I am not getting that how can I create a role and can assign priviliages to them, please help me guys
Thanks in advance
In your copenents/UserIdentity.php
class UserIdentity extends CUserIdentity{
private $_id;
public function authenticate()
{
$record=Members::model()->findByAttributes(array('username'=>trim($this->username)));
if($record===null)
$this->errorCode=self::ERROR_USERNAME_INVALID;
else if($record->password!==md5(trim($this->password)))
$this->errorCode=self::ERROR_PASSWORD_INVALID;
else
{
$this->_id=$record->id;
$this->setState('username', $record->username);
$this->setState('name', $record->name);
$this->setState('type', $record->role);
$this->errorCode=self::ERROR_NONE;
}
return !$this->errorCode;
}
public function getId()
{
return $this->_id;
}
public function setId($id)
{
$this->_id = $id;
}
}
You can create a new column name as "role". set the members type "admin" or "staff" to role column.
Be careful to that line.
$this->setState('type', $record->role);
Create a new helper file. /protected/helpers/RoleHelper.php
class RoleHelper {
public static function GetRole(){
if (Yii::app()->user->type == "admin"){
//set the actions which admin can access
$actionlist = "'index','view','create','update','admin','delete'";
}
elseif (Yii::app()->user->type = "staff"){
//set the actions which staff can access
$actionlist = "'index','view','create','update'";
}
else {
$actionlist = "'index','view'";
}
return $actionlist;
}
}
and in your controllers -> accessRules function
public function accessRules()
{
return array(
array('allow', // allow authenticated user to perform 'create' and 'update' actions
'actions'=>array(RoleHelper::GetRole()),
'users'=>array('#'),
),
array('deny', // deny all users
'users'=>array('*'),
),
);
}
and dont forget to add 'application.helpers.*' to /config/main.php
'import'=>array(
'application.models.*',
'application.components.*',
'application.helpers.*',
),
This source is pretty good specially for beginners..I am using this method till now:
Simple RBAC in YII
Just follow the instructions given while having your desired modifications.
Concrete Example:
WebUser.php (/components/WebUser.php)
<?php
class WebUser extends CWebUser
{
/**
* Overrides a Yii method that is used for roles in controllers (accessRules).
*
* #param string $operation Name of the operation required (here, a role).
* #param mixed $params (opt) Parameters for this operation, usually the object to access.
* #return bool Permission granted?
*/
public function checkAccess($operation, $params=array())
{
if (empty($this->id)) {
// Not identified => no rights
return false;
}
$role = $this->getState("evalRoles");
if ($role === 'SuperAdmin') {
return 'SuperAdmin'; // admin role has access to everything
}
if ($role === 'Administrator') {
return 'Administrator'; // admin role has access to everything
}
if ($role === 'Professor') {
return 'Professor'; //Regular Teaching Professor, has limited access
}
// allow access if the operation request is the current user's role
return ($operation === $role);
}
}
Just connect it with your components/UserIdentity.php and config/main.php:
'components' => array(
// ...
'user' => array(
'class' => 'WebUser',
),
and thats it..
to check the role of the logged in:
Yii::app->checkAccess("roles");
where checkAccess is the name of your function in WebUser...
Please note that evalRoles is a column in your table that will supply the role of an account (on my link provided, that would be the word roles used in the major part snippet)