Codeigniter Authentication and Authorization libraries that works well coupled toghether - codeigniter

I need functionality for authentication handling and some basic role based authorization (just block some pages to a role and allow some pages on another).
I already read this question: What is the best Authentication and Authorization library for CodeIgniter?
However the question it's from 2009 so maybe there is a new technology that works better now.
Any suggestion, expecially if you have used the library, are appreciated

All of the Auth libraries I know of restrict you in some form or other out of the bag. Its usually a good idea to build your own auth library, break it down so you dont restrict yourself to using codeigniters native AR.
For role/permissions I usually just store a json object to my permissions column in say users. I prefer this over using a more complicated technique
In my main Controller(non-restrictive) I just create a permissions(array)var and loop through it inside my child controllers to implement a restriction.
example:
sql column
`permissions` varchar(200) NOT NULL DEFAULT '["r", "u", "d"]';
main controller
protected $permissions = array();
protected function _get_permissions()
{
return (array)json_encode($this->user->permissions);
//get permissions from user (array/object)
}
extended children
if(in_array('r', $this->permissions))
{
//user can read something
}

I like skittles answer so I post it here (he is not posting):
I'm pretty sure this is not what you wanted to hear, but I prefer to
roll my own classes. I'm not afraid to re-invent the wheel
I prefer to use a salted hash. What I will typically do is take their
plain text password and add a string to it derived from a $config item
I call $config['encryption_salt']. Then I run the newly built string
through php's sha1 function and store the result in the database.
As for authorization, I will typically build a permissions lookup
table in my db and assign users a permission_id value in their user
record. Then my site can be conditionalized allow or disallow
activities based on their permission_id
If Skittle will post answer I'll mark it

Related

how to implement Single Responsibility in laravel

I am so confused about how to implement and how to follow SRP (single responsibility principle ) in a Laravel controller.
Suppose we have a controller which we have to do these things:
e.g
public function StorePost() {
// check user login()
//check number of current user Post count =>which must be less than 10
//store post
//send an email to user which your post has saved
//return =>api:json /web : redirect
}
I know that I can implement some DB queries in the repository but I don't know how to implement others of my logic code to achieve SRP
Also, I know there is a Heyman package to achieve these but I want to implement it by myself.
SRP in this context basically means each class and method should only be responsible for a single behaviour/feature. A rule of thumb is a class or method should change for one reason only, if it changes for multiple reasons, it needs to be broken down into smaller parts.
Your storePost method should not bother with checking the user login, that should be handled elsewhere before invoking storePost. storePost shouldnt change if the auth mechanism changes like switching from api token to json web token or something else. Laravel does this in the middleware level with the auth middleware.
Checking the users post count, this can be checked in the validation stage. storePost shouldn't change if we add more validation logic. In Laravel you can use FormValidation for this
For storing the post, the controller doesn't need to know how to call the DB, you can use the active record style using the model class or maybe create a service or repository class if your use case requires that. storePost shouldn't change if we decide to change DB vendor like going NoSQL.
For sending email, again the controller doesnt need to know how to send the email like what the subject/body recipients are. storePost shouldnt change if we need to change the email layout. Laravel has Notification for that
For serialising the response to json, the controller doesnt need to know how to format the response. if we decide to update how our json looks, storePost shouldnt change. Laravel has API Resources for that
So, ultimately in this example, the responsibility of the controller method is basically to glue all these together. It basically does what you wrote down, it only responsible for maintaining the step by step behavior, everything else is delegated to someone else. if the behavior change, like adding new behavior e.g notify all follower, storePost will change.

Laravel Encryptable Trait Failing Authentication

I'm running into trouble with authentication handling in my Laravel 5.5. I have installed an Encryptable trait according to this post here. I then used the authentication generator to establish the base routes, views and handler.
I can successfully register new accounts and visually see that all of the data is encrypted, but I cannot successfully authenticate through the login screen.
This seems to be failing during the Auth::attempt($credentials) call. My troubleshooting is pointing to the encryptable trait because when I comment that section out, the authentication works fine.
Can someone offer insight as to how to handle authentication using this method of model encryption?
I have attempted disabling encryption for the username field, but this didn't seem to help. The password field was never being encrypted, becasue it is being hashed by bcrypt.
1st Edit:
So, with an understanding of how traits work... The Encryptable trait seems to be overloading the getAttribute/setAttribute functions. This would mean that Eloquent's querying functions like where, find, etc. will just be "looking at" encrypted values.
2nd Edit:
The source code provided for the Encryptable trait was not returning proper values for unencrypted values. This was changed and authentication was restored. To those using the same code snippet, in the get_attribute() function, change the else block so that it return $value;.
I appreciate all insights,
Dan
This form of encryption will void your ability to search the table for the encrypted fields. You won't be able to reproduce the same string because Laravel uses a random iv when producing encrypted data. An IV, or initialization vector, serves a similar purpose as a salt in hashing, to randomize the stored data.
Due to this randomization of data, you wouldn't even be able to search your table by re-encrypting the search data:
User::where('email', Crypt::encrypt('email#email.com'));
// won't find anything even if an encrypted value of email#email.com exists
Running in an interactive shell allows you to see encrypt returns a completely different value on subsequent runs:
>>> json_decode(base64_decode(Crypt::encrypt('email#email.com')))->value
=> "zpA0LBsbkGCAagxLYB6kiqwJZmm7HSCVm4QrUw6W8SE="
>>> json_decode(base64_decode(Crypt::encrypt('email#email.com')))->value
=> "VKz8CWVzR66cv/J7J09K+TIVwQPxcIg+SDqQ32Sr7rU="
Therefore, you may want to be selective about what you actually encrypt. Encrypt things that are sensitive and you wouldn't use to lookup an entity. This could be something like social security numbers, government IDs, credit card numbers, and bank account numbers.

Can CakePHP offer stricter user authentication (continuous throughout session)?

I am trying to create a suitable authentication check for a CakePHP service. Currently it appears that the user session is created initially during login, but never checked beyond this during a single session.
eg. Renamed the username, changing the password or ID in the user's database entry has no effect on the session.
Is there a preferred method for this type of, constantly checked, authentication? Essentially the user should be confirmed access at every request.
My current solution would involve extending the AuthComponent and storing a hash of the user data (including the encrypted password) and checking this at every request. I also considered storing the session ID in this same token, but noticed that CakePHP does not even use the session_start() function.
This functionality appears necessary for me, and I would have thought others would also require such a solution. I have yet to find Cake documentation or community solutions similar to what I need.
Well, you can use isAuthorized() function from AuthComponent. It's being called with every request.
public function isAuthorized($user){
return true; //allow the user to see the page
}
You can debug($user) to see the actual data and if you want "new" information from your database, you can always get them like this:
public function isAuthorized($user){
$current_user_from_database = $this->User->findById($user['id']);
if($current_user_from_database['User']['username'] != $user['username']){
$this->Session->setFlash('You\'ve changed the username. Please, login again.');
$this->redirect($this->Auth->logout);
return false;
}
return true;
}
Look at the API for more info and from the PDF book. You can look at this video about AuthComponent too. It's great.
If you need any more information or help, feel free to ask.
Btw. you have to configure AuthComponent in your Controller if you want isAuthorized() function to get called with every request.
If Session.timeout will work correctly with a setting of zero minutes, you're set. http://book.cakephp.org/2.0/en/development/sessions.html

How do I set the value in User.Identity.Name to the user's real name?

My users log in using an email address and their password using my custom membership provider. Is there a way to have User.Identity.Name (or something else within there) return the users real name and not their username (or email address in my case) while keeping the email address so that can still be used? If that isn't a good way to do what I want, what do you recommend to do instead?
I think "Welcome Mike Wills" looks better than "Welcome bigdaddy124#mydomain.com".
You can add the user's profile object (or name) to a Session variable, so you won't have to query the database for each pageload.
The best way here is to implement a custom principle so the fields are available, don't try to 'misuse' existing fields. Simply cast the IPrinciple usage to your principle class and reference the FullName field (or whatever you call it)
Implementing IPrincipal and IIdentity in MVC with use of custom membership and role provider
A separate "Users" DB table to store personal info that is related to the Membership table....
That way it keeps your authentication and authorization data separated from (but linked to) your custom user data. Makes it easier to manage IMHO.

CakePHP Auth Loads Too Many Session Variables

Using CakePHP2.0 Beta I managed to write a custom login handler for my existing database schema. All's well, except that upon logging in I printed out the session variables stored and what Cake's Auth component did is store the entire record from the "Member" table (where my usernames+hashes come from) in session. It is storing an array with data fields that are totally irrelevant to the session. For instance it stores the date the member was created, their address, etc. All pretty useless information for me as I basically only need their ID and maybe username, name, email address.
The offending lines for me are found in: /lib/Cake/Controller/Component/AuthComponent.php line 512. It states,
$this->Session->write(self::$sessionKey, $user);
So my custom authenticate component returns $user and it throws this whole thing into the session. Now, I don't want to go about editing in the core libraries because this project is definitely going to be upgraded when 2.0 comes out. Is there any way to store less information in sessions? I want to keep this whole thing more lightweight.
Possible solution: Change my custom authentication component to only return the fields I need into the $user variable. Are there any concerns about what data I should/shouldn't be returning?
I've solved the problem using my "possible solution". In /app/Controller/Component/auth/MyController.php, I changed the "ClassRegistry::init($userModel)->find" method to have a parameter for 'fields' where I specify only the fields I need. Works like a charm.

Resources