cakephp authentication by user id - cakephp

Is it possible in CakePHP 1.3 to login a user by indicating the user's id in the users table?
Now, to do a "manual" login, I do this (which works):
$this->data['User']['username'] = username;
$this->data['User']['password'] = password;
$this->Auth->login($this->data);
I would like to be able to indicate the specific user, for example adding $this->data['User']['user_id'] before the login() function. (I've tried that but it doesn't work).
The reason I want to do this is because in the users table there are different users records of users who have the same username and password. It seems odd but in my case makes sense, since one same user may create several accounts for different reasons, and he may choose the same username/password.
Any ideas would be much appreciated!
EDIT:
I'm going to give a specific example of what I'm trying to do, maybe it helps to bring some ideas.
Say I have this 2 records in the users table (fields are user_id / username / password / account_id):
Record 1: 1 / johndoe / password1 / 10
Record 2: 2 / johndoe / password1 / 15
So this 2 records have same username and password, but different user_id and account_id. When the login is processed, I know what account_id the user has chosen. So I want to log in the corresponding user. So if the user chooses account 15, then logs is, I should be logging in the user with id 2.
However, the way cake's login works, it always retrieves the first record that matches username / password. In this example, cake would be logging in the user with id 1.
Is there any way I can do what I want?

Doesn't sound like a very good idea to me, but if you really want/must do it that way, then have a look at AuthComponent::userScope. You can use it to define additional conditions for authentication lookups, for example:
$this->Auth->userScope = array('User.account_id' => 15);
That way authentication would only be successful when username and password match and the users account_id is 15, ie the resulting query would look something like this
User.username = 'abc' AND User.password = 'xyz' AND User.account_id = 15

Related

API to check if user signup is spam/invalid?

We have a signup form for companies where user must enter
first and last name
their desired subdomain name
email
company name
We would like to run the input through some kind of spam/fraud (fake account, accounts with curse words, etc.) verification API which would create a score for the signup input and we could act accordingly.
While googling I only found akismet which supports signup mode and user first/last name and email fields, but when testing with John Doe john.doe#example.org with user agent set to CURL it says that it's not spam..
Any other solutions out there?

Command in command in Redis

I just started Redis. I need to create a database for online store or whatever. Main idea to show functionality. I never worked in Redis and terminal, so a bit confusing. Firstly I want to create a database of users with id users counter:
SET user:id 1000
INCR user:id
(integer) 1001
Can I use somehow command in command like:
HMSET incr user:id username "Lacresha Renner" gender "female" email "renner#gmail.com"
(error) ERR wrong number of arguments for HMSET
in case that my database automatically count new users in database. Or it's not possible in Redis? Should I do it by hands, like user:1, user:2, user:n?
I am working in terminal (MacOS).
HMSET receives a key name, and pairs of elements names and values.
Your first argument (incr) is invalid, and the id part of the second should be explicit id.
e.g.:
HMSET user:1000 username "Lacresha Renner" gender "female" email "renner#gmail.com"
Regarding your first SET, you should have one key that its whole purpose is a running uid, you should use the reply of INCR as the new UID for the new user HASH key name (1000 in the above example).
If you never delete users, the value of the running UID will be the number of users in your system. If you do delete users, you should also insert the UID into a SET and remove the UID once you delete the user. In that case, an SCARD should give you the number of users in your system, and SMEMBERS (or SSCAN) will give you all of their UIDs.

What's the safest encryption I can use for a user to login to my program?

I'm writing a program and before it loads I want the user to enter the correct password without storing the password anywhere in my code. I've implemented MD5 hashes before but from what I've read they're outdated and can be broken. There are a few sites out there that attempt to reverse engineer and MD5 hash. What's the strongest encryption I can use to keep prying eyes out of my program (e.g., The NSA)?
"Encryption" is not the right thing to do for storing user passwords - as by design an encrypted password can be decrypted. As you said - hashing is the way to go.
MD5 is outdated, and I believe the current recommendation is sha1.
Note that there are ways to reverse any hashing algorithm to acceptable input. The commonly accepted standard to make this much more dificult is to add a unique "salt" to all passwords before putting them through the hashing function. A common mistake made when adding salts to passwords is to use the same salt value on every password in the database.
When salting passwords, use a unique value, for example the user ID, or the created date/time string for the user record. This will prevent attacks based on rainbow tables because there will be no existing ready to use rainbow table for your stored password hashes.
I personally like the approach of using the created date / time string of the user as it's a value that should never change and will be available and will likely be different for each user the the database.
Eexamples below assume you are familiar with PHP - however the concepts can be applied to any language.
Example:
Before saving a new user into the database:
$date = date('Y-m-d H:i:s');
// save this same value into the user record somewhere
$passwordHash = sha1($user['created_date'].$_POST['password']);
// and save the $passwordHash value into the password field for that user
To authenticate a login attempt, use something like the following:
function authenticateUserLogin($email, $password) {
$user = $db->fetchRow('SELECT * FROM users WHERE email=?', array($email));
if (!$user) return false;
$passwordHash = sha1($user['created_date'].$password);
return $user['password_hash'] !== $passwordHash;
}
To update an existing users password, use something like...
$passwordHash = sha1($user['date_created'].$newPassword);
$db->query('UPDATE users set password_hash=? WHERE id = ?', array($passwordHash, $user['id']));

In Facebook graph API how to find which all of your friends like a particular page with detail info?

I'm trying to figure out how to find how many of my friends "like" a particular page
and friends' detailed information such as id, name, and picture.
For example: for a given page ID, how can I look up how many of my friends have already liked the same page for the ID?
I just know that when I use this FQL ==>
SELECT uid FROM page_fan WHERE page_id = 114719705207104 AND uid IN (SELECT uid2 FROM friend WHERE uid1=me())
I only got a list of a friends' uids.
But I'd like to get friend list with name, id, picture, and URL.
Simple, just add another IN to the query
SELECT uid, pic, name, username FROM user WHERE uid in (SELECT uid FROM page_fan WHERE page_id = 114719705207104 AND uid IN (SELECT uid2 FROM friend WHERE uid1=me()))
The UID is the user id you want.
The URL for the user is equal to www.facebook.com/UID or www.facebook.com/USERNAME
Since not every user has a username I advise you to use the first option with the UID.
You have many ways of retrieving the user pic, with the uid you can use the graph api to fetch the pic in various sizes, doing this
https://graph.facebook.com/UID/picture or https://graph.facebook.com/USERNAME/picture
Then adding some get parameters you can configure the size of the pic. You can read more about that here
If you want to keep using FQL for selecting the pic, you have many fields in the User table that return different sizes. You can read more about the user table here and see the available fields for the pic

restricting aro scope in cakephp

Ok, I'll preface this by saying i'm a noob to cake and ACL, and MVC architecture. I'm following a cakephp tutorial from its site, http://book.cakephp.org/2.0/en/tutorials-and-examples/simple-acl-controlled-application/part-two.html. I understand the content of the tutorial, but wonder about the easiest way to take this simple group based ACL to the next level. I've searched SO to no avail. So, on with the question.
Lets take a slightly modified version of the function in the above tutorial, for example. It simply sets up ARO permissions for ACOs.
There are many districts, and many departments, all with many users, in each.
relationships are as follows:
A district hasMany Departments -- one to many.
A district has many users, and users can potentially have many districts(so long as they belong to a dept in that district).
A department hasAnBelongsToMany Users -- many to many.
public function initDB() {
$group = $this->User->Group;
//Allow admins to everything
$group->id = 1;
$this->Acl->allow($group, 'controllers');
// issue 1) allow district managers to districts, departments, users
$group->id = 2;
$this->Acl->deny($group, 'controllers');
$this->Acl->allow($group, 'controllers/Districts');
$this->Acl->allow($group, 'controllers/Departments');
$this->Acl->allow($group, 'controllers/Users');
//issue 2) allow department managers to edit departments and users
$group->id = 3;
$this->Acl->deny($group, 'controllers');
$this->Acl->allow($group, 'controllers/Departments');
$this->Acl->allow($group, 'controllers/Users');
//we add an exit to avoid an ugly "missing views" error message
echo "all done";
exit;
}
Ok, so these permissions being set-up, although it's definitely convenient, really solve a small part of the problem. As it stands, I've really only prevented the department admins from performing district level functions. Both district admins and dept admins can perform user CRUD without restrictions
What i'd like to do, is limit the scope of each of the admin types USER CRUD to only those users residing within their department or district. for example, Department Admin Foo can't delete another Dept Admin's Users, and Dist Admin Bar can't change all of another Dist Admin's Users first names to nancy.
lol. I'm seriously at a loss with how to accomplish this.
I guess one approach would be get an administrators rank, dist admin for example, then figure out in which district he is a user. lastly, return all of the users in this district into a variable $userScope. Again, I am new to cake php and would be unsure of how to carry out the this proposal, even if it were a good idea and the best way to handle this. Any suggestions?? Thanks in advance!!!
edit: helpful answer, #nicolae.
however, it still seems that i could write a function that returns all users that any given admin(of any given aco) is permitted to edit. is seems this way to me because i'm assuming the admin, him/herself to be a part of the returned user base. for example, dist admin of dist 9, resides in dist 9; likewise, dept admin of dept 1, resides in dept 1.
could i write something like:
public getUserScope(){
$id = $this->Auth->user('id');
$dept = $this...
$dist = $this...
$access_level = $this->Session->read('Auth.User.group_id');
if($access_level == 3){
//get all users in this user's dept
} elseif($access_level == 2) {
//find all users in this user's dist
} elseif($access_level == 1) {
//find all users
}
}
ouch. granted all of the join tables involved in bringing this info together, this is bound to look like medusas hair when actually typed up. can you see my line of logic. this is a bit difficult for me to articulate. let me know if i should clarify anything further.
So you're trying to set up an ACL system that manages restrictions based on more than group ID and controller/action - you need department- and district-based restrictions.
As far as I know, the embedded ACL system in CakePHP can not manage this level of restrictions.
As a solution, I recommend you allow the users to the places they need to access (e.g. dept admins have ACL access to the user CRUD interface) and insert specific restrictions in the controller.
function editUserFromDepartment($userId = NULL) {
// Custom ACL check
if (! $this->__checkDepartmentByUserId($userId)) {
// Show the user a custom error message and redirect him to index page
}
// User editing code ...
}
function __checkDepartmentByUserId($userId) {
$dept = $this->Department->getByUserId($userId);
// Check if the current user belongs to this department
$currentUserDepartmentId = $this->Session->read('Auth.User.department_id');
return ($dept['Department']['id'] != $currentUserDepartmentId);
}
Good luck and let me know if my explanation was clear enough.
Nicolae
Edit (trying to answer to #Todd's edit):
I get your point.
Your code aims at obtaining all users of that the current user has access of.
Rather than that, I would have an event-based approach: when the user X tries to be edited, perform a query that finds if Auth.User is allowed to perform this action on user X.
E.g. You (Todd) are trying to edit my profile (NicolaeS) to change my employee ID, as my current one is wrong.
The function $this->getUserScope('user-ID-of-NicolaeS') will check if your department ID or district ID is the same as main and allow/disallow you to continue in your actions according to this check.
Does this look clear/straightforward enough?
Greets,
Nicolae

Resources