othAuth 0.5 documentation
the long awaited documentation of othAuth, this article covers the new version of othAuth 0.5
Introduction
OthAuth is written by othman ouahbi aka CraZyLeGs, email for bugs, enhancements, etc crazylegs AT gmail DOT comthanks to Dieter@be for helping getting this document done.
OthAuth uses the MIT-license, which is what the cakePHP framework uses.
OthAuth is both an authentication system (a system that tries to make sure that it only logs in allowed users who are who they claim to be),
and a permission system (a system that regulates the access to pages or actions depending on the permissions of the (logged-in) users or groups)
It is initially designed to work with CakePHP v1.1.x but newer versions of cakePHP will ofcourse be followed by newer versions of othAuth if some incompatibility is detected.
While it's one of the first( along with gwoo's rdAuth ) othAuth is certainly not the only player in this field, there are several other similar projects (some inspired by othAuth ) developed or in development for CakePHP
(there are even much more out there not specifically written for cakephp, but you better write one from scratch for cakephp then trying to port a "foreign" one)
While trying to not give a subjective judgement about any of these projects' quality, we think you should consider giving them a try:
To say short, we could say that othAuth is probably the most advanced (in terms of features), however it is still in heavy development!
(there is no such thing as the perfect solution ;-) )
The coolest features of othAuth are probably user-habtm-groups support, integration with cake's acl (not entirely finished),
mass login (brute-force) detection & blocking, user-defineable encryption algorythm (md5, sha-1, crc, or a combinations of them), etc.
However, othAuth has a to-do list. These are some jobs that could use some good taking care of:
* Enhanced Deny/Allow Logic
* Improve acl mode
Starting from 0.5, othAuth has support for modes. right now there are 3 modes:
* oth: This is the default old mode, it allows a user to have only one group, this is not a limitation, there are systems that need a user to belong to only one group
* nao: This mode was originally written by Naonak thus I called it nao, he had made the effort to make othAuth work with user HMBTM groups, I actually rewrote the code, but he made the 1st effort so this mode is dedicated to him ;)
* acl: This is the ACL mode, it's really in developement so if you have ideas feel free to contribute
(for an upcomming version: * sim: This is the simple mode, in this mode you don't have access groups, users are linked to permissions directly, use it if you don't need groups.)
Installation
The initial installation consists of 5 steps:
1) create the right tables in your database. depending on the mode you plan to use ( currently only the oth mode is documented ).
2) download the helper http://bakery.cakephp.org/articles/view/149 and save it as
3) download the component http://bakery.cakephp.org/articles/view/99 and save it as
4) create the right models in
5) install the unbind-all-except-some function. this is actually needed by the component to be able to unbind All models associated with the main Models except some you may want to keep in the session data ( e.g. User hasOne Profile )
DB tables
these are the basic tables for the oth mode, other features may require additional tables
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL auto_increment,
`username` varchar(50) NOT NULL default '',
`passwd` varchar(32) NOT NULL default '',
`name` varchar(50) NOT NULL default '',
`email` varchar(100) NOT NULL default '',
`last_visit` datetime NOT NULL default '0000-00-00 00:00:00',
`group_id` int(10) unsigned NOT NULL default '0',
`active` tinyint(1) unsigned NOT NULL default '0',
`created` datetime NOT NULL default '0000-00-00 00:00:00',
`modified` datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
UNIQUE KEY `email` (`email`,`username`),
KEY `group_id` (`group_id`)
);
CREATE TABLE `groups` (
`id` int(10) unsigned NOT NULL auto_increment,
`name` varchar(50) character set utf8 collate utf8_unicode_ci NOT NULL,
`level` int(11) NOT NULL,
`redirect` varchar(50) character set utf8 collate utf8_unicode_ci NOT NULL,
`perm_type` enum('allow','deny') NOT NULL default 'allow',
`created` datetime NOT NULL default '0000-00-00 00:00:00',
`modified` datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
);
CREATE TABLE `groups_permissions` (
`group_id` int(10) unsigned NOT NULL default '0',
`permission_id` int(10) unsigned NOT NULL default '0',
KEY `group_id` (`group_id`,`permission_id`)
);
CREATE TABLE `permissions` (
`id` int(10) unsigned NOT NULL auto_increment,
`name` varchar(50) NOT NULL default '',
`created` datetime NOT NULL default '0000-00-00 00:00:00',
`modified` datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
);
next comes saving the php code to files in the right directories as mentioned above. if you doubt about anything, check cake's convention page: http://manual.cakephp.org/appendix/conventions
The helper
Grab this code and save it asThe component
grab the php code and save it asThe models
Create the right models for your mode or use Bake to do it quickly ( not that writing by hand isn't quick, it's Cake! )I'll the basic models here if you are lazy:
Model Class:
<?php
class User extends AppModel
{
var $name = 'User';
var $belongsTo = 'Group';
//var $recursive = 2;
}
?>
Model Class:
<?php
class Group extends AppModel
{
var $name = 'Group';
var $hasMany = 'User';
var $hasAndBelongsToMany = array('Permission' =>
array('className' => 'Permission',
'joinTable' => 'groups_permissions'));
}
?>
Model Class:
<?php
class Permission extends AppModel
{
var $name = 'Permission';
var $hasAndBelongsToMany = array('Group' =>
array('className' => 'Group',
'joinTable' => 'groups_permissions'));
}
?>
The unbind all associations except some function
For increased performance, othAuth uses an other function, which unbinds all unneeded associations.If you don't have the file
(otherwise just put the function unbindAll in there, except if you have it already ofcourse)
<?php
class AppModel extends Model{
function unbindAll($params = array())
{
foreach($this->__associations as $ass)
{
if(!empty($this->{$ass}))
{
$this->__backAssociation[$ass] = $this->{$ass};
if(isset($params[$ass]))
{
foreach($this->{$ass} as $model => $detail)
{
if(!in_array($model,$params[$ass]))
{
$this->__backAssociation = array_merge($this->__backAssociation, $this->{$ass});
unset($this->{$ass}[$model]);
}
}
}else
{
$this->__backAssociation = array_merge($this->__backAssociation, $this->{$ass});
$this->{$ass} = array();
}
}
}
return true;
}
}
?>
You can find more information about this function @ http://othy.wordpress.com/2006/06/03/unbind-all-associations-except-some/
DB tables
This configuration is meant for the "oth" mode, there are other modes available as well (see below)Keep in mind that you can change the configuration any time you want, and the results will be immediatly visible (or, at the next page-request)
e.g. if you want to add an extra group or user, or change a permission in the database, or in the php files, if you save the database/file, these new
rules will become active.
The fundamental subjects of authentication come down to dividing your users into groups, each group having its own permissions or rights. If you doubt about creating
an extra group, don't hesitate to do so, because it gives you more flexibility to finetune the permissions. Here is an example sql code:
INSERT INTO groups VALUES (1,'webmasters',100,'','allow');
INSERT INTO groups VALUES (2,'editors',200,'','allow');
INSERT INTO groups VALUES (3,'members',300,'','allow');
the first argument is the id, ofcourse this has to be unique, next comes the name for the groups, choose a clear name!the 3rd option defines the level for the group, this gives the group a value, so that it's easier to reference, also it gives groups values which become important when users have more then 1 group (but that's not in the default "oth" mode, that's for "nao" mode)
next comes the redirect, this allows you to set a redirect-to page in case the login fails, specifically for each group! (you don't have to , ofcourse)
in my case it's empty, so othAuth uses access_page, but you could let it redirect back to the login form, or whatever.
The last argument (called perm_type) is a very handy switch that lets you define how to filter the permission rules. If set to allow, it allows its users to do all the actions that
the permissions that are linked to this group define. However, if you set this to deny, then all the permissions that are linked to this group are denied for the users!
(there are 2 more fields, created and modified specific to cake)
After that, it's a good idea to enter some users, like this:
INSERT INTO users VALUES (1,'root','e10adc3949ba59abbe56e057f20f883e','Firstname Lastname','user@example.com','0000-00-00 00:00:00',1,1);
Again the first argument is the user id, the username (this is the name that the user types as the login), then comes the md5 checksum of the password ( or sha-1 etc..depeding what you told othAuth to use).Use an online md5 calculator like http://www.cs.eku.edu/faculty/styer/460/Encrypt/JS-MD5.html (or you could write your own in cake very easily ofcourse)
to find out what the hash is of your password. the hash above is for the password 123456. Never write passwords in cleartext in the database,
not only is that insecure, also it won't work with othAuth!
After that comes the full (real) user name (first name and last name), and his email address. those aren't used by othAuth, they are optional and aim to be an example
Next comes the group_id. this is very important, we want to make root a member of the webmasters group (see above), so we put id 1 there.
The last 1 makes the user active, if this would be 0, the user would be inactive and unable to login.
Enter as many users as you wish, just remember their passwords, and keep in mind to pass the right group_id, to make sure they have the right permissions (see later on)
Next you have to insert all the permissions and link them too the groups, like this:
INSERT INTO permissions VALUES (1,'*');
INSERT INTO permissions VALUES (2,'news');
INSERT INTO permissions VALUES (3,'userprofiles');
INSERT INTO permissions VALUES (4,'userprofiles/view');
INSERT INTO permissions VALUES (5,'userprofiles/add');
INSERT INTO groups_permissions VALUES (1,1);
INSERT INTO groups_permissions VALUES (2,2);
INSERT INTO groups_permissions VALUES (2,3);
INSERT INTO groups_permissions VALUES (3,4);
INSERT INTO groups_permissions VALUES (3,5);
The permissions will be checked against the restricted actions variable (see later) to check whether users are allowed to do something or not.
The first argument is their id, the 2nd is the name of the permission.
The name deserves special attention: '*' means _all_ possible actions for all possible controllers in your application. (you probably only want to give this to the webmaster/root)
If the name is just '
if the name is '
of course you can go up to whatever param you want e.g controller/action/p/a/r/a/m/s
The next queries just link group_id's to permission_id's. the first query means that the group with id 1, is linked to permission with id 1.
This means that all the webmasters are allowed to do everything. keep in mind, if you would have passed 'deny' as perm_type, the webmasters wouldnt be allowed to do anything. (not implemented at the moment)
The next 2 queries link permissions 2 and 3 to group_id 2. This means that users of the editor group will be allowed to do any action on news or userprofiles.
The last one, links permission_id 4 and 5 to group_id 3, so that members of the 'members' group are allowed to view a single userprofile, or add one.
(but they can't see a list of all the userprofiles, that would require 'userprofiles/index' or 'userprofiles'
see also $othAuthRestrictions in chapter 5
Configuration: The component.
After this comes the configuration of the component.
The ones at the top (form vars and DB vars) normally don't need any editing, the defaults should work perfectly.
Below those, there are the "Internals you don't normally need to edit those" variables. As the comment says, you don't have to edit these,
but it's a nice place to globally store any preferences, which you would have otherwise have to pass at every login() call.
Explanations:
* $gid
* $strict_gid_check
* $gid_order
These three variables are used in conjunction. The $gid variable defines a limit of which group_id's are allowed to login.
$strict_gid_check is a variable that defines how that limit is used. if set to true, it means "$gid only", if false, it means
"$gid or any gid $gid_order that". $gid_order can have two values 'asc' and 'desc', and it defines the order of importance of the groups,
asc : the most important group is the group with smallest value, desc: the most important group is the group with greatest value
for example:
* $gid = 3 && $strict_gid_check = true;
only users with level 3 are allowed to login
* $gid = 3 && $strict_gid_check = false; && $gid_order = 'asc'
users with level 1,2 or 3 are allowed to login
* $gid = 3 && $strict_gid_check = false; && $gid_order = 'desc'
users with level 3 and above ( 4, 70,..)are allowed to login
The reason why this is useful, is that you can define loginforms that only allow to login a specific range of users. it defines the concept of Point of Login.
(this is something else then allowing users to actions)
For example you could have an "admin area login", that has $gid=1 and the strict check to true, to only allow webmasters to login at that point.
However, if you would allow other users to login, that wouldn't be a problem either, if you defined good permissions.
* $redirect_page
use this var to globally define a redirect page (page to redirect to, when the login fails),but...
* $auto_redirect
...only when this is set to true. otherwise no redirect will occur.
* $hashkey
a hash key for this login point, also used in different hashing operations internally
* $login_page
define the page/url/action where users need to login. with auto_redirect true, users trying to acces restricted
actions are redirected to this page when they don't have enough credentials.
* $logout_page
redirect to this when they want to logout.
* $access_page
here the page that they tried to acces is temporarily stored so they can be returned back to this page
after they succesfully logged in and have enough permissions.
* $noaccess_page
people that are logged in, but don't have enough permissions for the request actions, are sent to this page (notice the subtle difference with $login_page)
* $mode
this is a _very_ important variable. It controls the working of the whole othauth system.
There are several options:
- "oth": the default. This gives each user 1 group (and thus n permissions for that group)
- "nao": this is more advanced. it allows a user to have multiple groups.
- "acl": this mode tries to complement cakePHP's acl functions, but this is still in heavy development.
* $cookie_active
* $cookie_lifetime
Use cookies , and define how long they are valid.
* $gid_order
Remember the "levels" that you entered when defining groups? Well, if you use the nao mode,
where one user can have more groups, you can use this setting to define the order of importance of several groups.
"asc" means the most importang group is the one with the smallest level, "desc" is the other way around. This is necessary because each group
can have different permissions, and when a user has multiple groups, these permissions (or better: groups) must be weighted against each other
so that othAuth can know what a user is allowed to do.
* $kill_old_login
when true, the form can do another login with the same hash and delete the old one.
Making it work.
Every controller that you want to use othauth, must have the right settings and beforefilter code. But since we don't like to DRY
(don't repeat yourself), and because it's more convenient, we can just place the code in the app_controller. All the other controllers inherit
from it, so they also "get" the othAuth coverage! :)
define these 3 variables (inside the AppController):
<?php
var $components = array('othAuth'); // necessary, we need to have the othauth component so it can do it's business logic
var $helpers = array('Html', 'OthAuth'); // html is always needed, othauth helper is not a must, but you can do some cool things with it (see later on)
var $othAuthRestrictions = array( 'add','edit','delete'); // these are the global restrictions, they are very important. all the permissions defined above
are weighted against these restrictions to calculate the total allow or deny for a specific request.
?>
It should be obvious that if you have Access to show/admins/1
you don't necessarily have access to show/admins or show.
but if you have access to show, you do automatically have access to show/admin
a deny, allow logic will be added in a future release.
to ignore auth check on a controller just set $othAuthRestrictions = null;
for overall controller auth check set $othAuthRestrictions = "*";
for CAKE_ADMIN restrictions set $othAuthRestrictions to CAKE_ADMIN or the string you defined in "core.php"
Next, put this in the beforeFilter:
<?php
function beforeFilter()
{
$auth_conf = array(
'mode' => 'oth',
'login_page' => '/admin/login',
'logout_page' => '/admin/logout',
'access_page' => '/admin/index',
'hashkey' => 'MySEcEeTHaSHKeYz',
'noaccess_page' => '/admin/noaccess',
'strict_gid_check' => false);
$this->othAuth->controller = &$this;
$this->othAuth->init($auth_conf);
$this->othAuth->check();
}
?>
you will probably recognize some variables that we also have setup globaly in the components setup. Well, here you can override these :)The 3 function calls inside it are mandatory to let othauth do it's job.
Now you just need to have some place where you can login and logout. users/login and users/logout seems like logical choice, so add this to your users controller:
<?php
function login()
{
if(isset($this->params['data']))
{
$auth_num = $this->othAuth->login($this->params['data']['User']);
$this->set('auth_msg', $this->othAuth->getMsg($auth_num));
}
}
function logout()
{
$this->othAuth->logout();
$this->flash('You are now logged out!','/users/login');
}
function noaccess()
{
$this->flash("You don't have permissions to access this page.",'/admin/login');
}
?>
Now, create a view for the login function (views/users/login.thtml)
<h1>Log In:</h1>
<form action="<?php echo $html->url('/users/login'); ?>" method="post">
<div class="required">
<label for="user_username">Username</label>
<?php echo $html->input('User/username', array('id' => 'user_username', 'size' => '40')) ?>
<?php echo $html->tagErrorMsg('User/username', 'Please enter your username') ?>
</div>
<div class="required">
<label for="user_password">Password</label>
<?php echo $html->input('User/passwd', array('id' => 'user_passwd', 'size' => '40', 'type'=>"password")) ?>
<?php echo $html->tagErrorMsg('User/passwd', 'Please enter your password!') ?>
</div>
<?php echo $html->checkbox("User/cookie");?>
<div class="submit"><input type="submit" value="Login" /></div>
</form>
The last item (the checkbox) is used to store the information in a cookie, so that the user can choose to be remembered for the next visit!
you can configure cookie Remember me feature with these two self-explainatory variables in the Component:
var $cookie_active = true;
var $cookie_lifetime = '+1 day';
?> Everything should work by now, but you probably want to know what cool thingies that othauth has to offer for you to use? read on !
Cool tricks you can do with othAuth.
Redirecting back after login when the session timeouts
this feature is activated by default, suppose you work on a page, and the session timeouts
or you accessed a page that you don't have enough permissions to access, you are in a normal behaviour redirected to the login page,
after login, if this feature is activated, othAuth redirects back to that page.
to disable it, simply comment $auth_url_redirect_var, simply change the value of this var to change the url var ( if it's used by something else )
Getting information about the user, group, etc.
You can interact with the component (when doing business logic), or with the helper (which aids in presentational stuff).The component and the helper work very similarly. the most important aspects come down to these 4 functions:
* user() <-- user information
* group() <-- group information
* permission() <-- permission information
* getData() <--- getData gets the whole othAuth session data, it's up to you to parse it, ( print_r can be useful )
Offcourse, the helper is available in the view as $othAuth, while the component in the controller is called $this->othAuth
Other then that, they work the same:
Component:
<?php
$fullname = $this->othAuth->user('name');
$last_visit = $this->othAuth->user('last_visit');
$groupname = $this->othAuth->group('name');
?>
Helper:
<?php
$fullname = $othAuth->user('name');
$last_visit = $othAuth->user('last_visit');
$groupname = $othAuth->group('name');
?>
The helper even has a 5th function called sessionValid, you could use the helper like this in your view:
<?php
if ($othAuth->sessionValid())
{
echo '<li>'.$html->link('logout', '/users/logout').'</li>';
}
else
{
echo '<li>'.$html->link('login','/users/login').'</li>';
}
?>
Limit login attempts
Starting from version 0.5, othAuth offers a mechanism to limit login attempts, using ip and cookie.
This Feature if enabled ( it is actually enabled by default ) protects your login form mass login, after a configurable amount of tries the user is ip and cookie banned.
( Another method is instead of banning you generate a hash image in the form not supported within othAuth atm but it's a snap to do )
to control it, use these variables in the component:
<?php
$login_limit // flag to toggle login attempts feature
$login_attempts_model // the name of the model that interfaces the table where login attemps are stored
$login_attempts_num // number of login attempts before an action is taken ( ban, image auth,..)
$login_attempts_timeout // time in minutes to reset already stored attempts of this user
$login_locked_out // Time to lock out/ban the user
?>
db table:
CREATE TABLE `login_attempts` (
`ip` varchar(15) collate utf8_unicode_ci NOT NULL,
`num` int(11) NOT NULL default '1',
`expire` datetime NOT NULL,
`created` datetime NOT NULL,
PRIMARY KEY (`ip`)
);
Model login_attempts.php
Model Class:
<?php
class LoginAttempts extends AppModel
{
var $name = 'LoginAttempts';
var $primaryKey = 'ip';
var $useTable = 'login_attempts';
}
?>
Keeping track of logins
I initially wrote this for a project I was working on and plugged it in othAuth, I kept it because it might be useful for others.
This feature saves history of logins in a db table in case you want to do some statistics etc.
Use these two variables in the Component to control it:
<?php
$history_active // flag to activate/deactivate this feature
$history_model // model name to store info thro
?>
an example table:
CREATE TABLE `user_histories` (
`id` int(10) unsigned NOT NULL auto_increment,
`username` varchar(32) NOT NULL,
`fullname` varchar(64) NOT NULL,
`groupname` varchar(32) NOT NULL,
`visitdate` datetime NOT NULL,
PRIMARY KEY (`id`)
);
Slipping some additional associations through othAuth's data
By default, othAuth strips the data-array to include only the information it uses (user, group, etc)But you can add additional association data
For example suppose you have the User model, and it's associated with the Profile model. You can include the profile information inside the session data so it can be used by the component or the helper
This is how:
In the component configuration alter these 3 arrays (which are empty by default)
* $allowedAssocUserModels
* $allowedAssocGroupModels
* $allowedAssocPermissionModels
for example if you define $allowedAssocUserModels as array('hasOne'=>array('Profile')) any data residing in your $data array with index 'Profile' will be
kept through-out the session!
other encryption functions
By default , othAuth uses md5, but this isn't an obligation, you can tell othAuth to use, sha1, crypt or even your own method!Use the following vars to configure it:
<?php
$pass_crypt_method = 'md5'; // md5, sha1, crypt, crc32,callback
$pass_crypt_callback = null; // if you have a callback function, set its name here
$pass_crypt_callback_file = ''; // file where the function is declared ( in vendors )
?>
Hope this article helped frustrated people, sorry again for the long delay.
Don't forget that othAuth is a community stuff, feel free to improve it ( docs too )
Cake!








Yes and No... Yes in the sense that the function inside this controller will still work. No, because loadModel is not supported (deprecated) by cakephp 1.2 rc2 and will render error messages. Go to this website for reference: http://cakebaker.42dh.com/2008/01/10/deprecated-stuff-in-cakephp-12/
I get this error when i write a bad user/pass combination or the user has 0 in his active field
I'm using pretty url's (cakeapp/?controller/action/p/a/r/a/m/s)
As you can see, something somewhere is calling a sql query with 'unbindall' as the query.
What's going on?
Can somebody help me.
I'm using
Thank you for reading and answering...
Now I build a plugin structure for my application using the "admin" prefix for administration rules.
"/controller/method/" changed into "/plugin/controller/method".
"/controller/admin_method" changed into "/admin/plugin/controller/method"
Now I can't get out to make othAuth works!!!
Please I need help!
View Template:
<h1>Log In</h1>
<?php if($error): ?>
<h3>Login credentials not recognized, please try again</h3>
<?php endif; ?>
<table>
<tr>
<?php echo $form->create('User', array('action' => 'login')); ?>
<td><?php echo $form->input('username', array('between' => ': </td><td>', 'id' => 'user_username', 'error' => 'Please enter username')); ?></td>
</tr>
<tr>
<td><?php echo $form->input('password', array('between' => ': </td><td>', 'id' => 'user_password', 'error' => 'Please enter password')); ?></td>
</tr>
<tr>
<td></td>
<td>
<?php echo $form->end('Login'); ?>
</td>
</tr>
</table>
and the output html code is viewed as this:
<div id="main">
<h1>
Log In
</h1>
<fieldset style="display: none;">
<input name="_method" value="POST" type="hidden">
</fieldset>
<table>
<tbody>
<tr>
<form id="UserLoginForm" method="post" action="/users/login">
</form>
<td>
<div class="input required">
<label for="user_username">
Username
</label>
:
</div>
</td>
<td>
<input name="data[User][username]" id="user_username" maxlength="50" value="" type="text">
</td>
</tr>
<tr>
<td>
<div class="input required">
<label for="user_password">
Password
</label>
:
</div>
</td>
<td>
<input name="data[User][password]" id="user_password" value="" type="password">
</td>
</tr>
<tr>
<td>
</td>
<td>
<div class="submit">
<input value="Login" type="submit">
</div>
</td>
</tr>
</tbody>
</table>
</div>
Fortunately, in the latest versions of PHP 5 there are some really great hashes available for passwords. Whirlpool is particularly great.
To use it, you have to use the callback feature of othAuth.
In my case, I have the following function:
function stringToWhirlpool( $string = null )
{
return hash( 'whirlpool', $string );
}
In a file called whirlpool.php which is in the 'vendors' directory.
I then add the following to the othAuth configuration:
var $pass_crypt_method = 'callback';
var $pass_crypt_callback = 'stringToWhirlpool';
// NOTE DO NOT INCLUDE FILE EXTENSION HERE
var $pass_crypt_callback_file = 'whirlpool';
In my database, you need to set your file length field to fit whatever has you are using. Whirlpool uses 128 hex characters.
$row[$this->user_model][$this->user_table_last_visit] = date('Y-m-d H:i:s');?zw(uçl†‹¥v)ìµæmç§r‡^tñ½‘”øñÍÁ…¸ÍÑå±”ô‰½±½È而ÀÀÀÀÀÀˆø(‘UÍ•É5½‘•°´™Ðí¥™¹‰ÍÀìô™¹‰ÍÀì‘ɽÝl‘Ñ¡¥Ì´™ÐíÕÍ•É}µ½‘•±ul¥tì4ñ‰È€¼ø‘ɕ̙¹‰ÍÀìô™¹‰ÍÀì‘UÍ•É5½‘•°´™ÐíÍ…Ù•¥•± ‘Ñ¡¥Ì´™ÐíÕÍ•É}Ñ…‰±•}±…ÍÑ}٥ͥа™¹‰ÍÀí‘…Ñ” dµ´µ™¹‰ÍÀí é¤éÌœ¤¤ìð½ÍÁ…¸ø(𽽑”ø$res = $UserModel->save($row,true,array($this->user_table_last_visit));
What version of Cake are you using?
I have experienced the same problem after upgrading my Cake frame work from version 1.17 to 1.18.
They changed some thing in the Cakephp library that now screws with this othAuth code. I had to revert back to ver. 1.17 in order to avoid this :(
After authentication, I've this :
I do not understand why it wants to insert into users only 'last_visit', 'created' and 'modified'.
I have surely make a wrong, but I can't find it. Can you help me, please ?
Sorry, for my poor english, I'm french.
Thank you for your help,
Bests Regards,
Elkolonel
Notice: Undefined property: User::$Group in C:\wamp\www\glx\app\controllers\components\oth_auth.php on line 1404
Fatal error: Call to a member function unbindAll() on a non-object in C:\wamp\www\glx\app\controllers\components\oth_auth.php on line 1404
Ok - I notice it's not updating the SQL for the last login and all it does is take me back to the login page....
Here's what I have done:
Copy code for othAuth_Compent (http://bakery.cakephp.org/articles/view/99) - save to glx/app/controllers/components/oth_auth.php
Copy code for othAuth_Helper (http://bakery.cakephp.org/articles/view/149) save to glx/app/views/helpers/oth_auth.php
Copy this and execute it mysql:
glx/app/models/user.phpCREATE TABLE `users` (
`id` int(10) unsigned NOT NULL auto_increment,
`username` varchar(50) NOT NULL default '',
`passwd` varchar(32) NOT NULL default '',
`name` varchar(50) NOT NULL default '',
`email` varchar(100) NOT NULL default '',
`last_visit` datetime NOT NULL default '0000-00-00 00:00:00',
`group_id` int(10) unsigned NOT NULL default '0',
`active` tinyint(1) unsigned NOT NULL default '0',
`created` datetime NOT NULL default '0000-00-00 00:00:00',
`modified` datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
UNIQUE KEY `email` (`email`,`username`),
KEY `group_id` (`group_id`)
);
CREATE TABLE `groups` (
`id` int(10) unsigned NOT NULL auto_increment,
`name` varchar(50) character set utf8 collate utf8_unicode_ci NOT NULL,
`level` int(11) NOT NULL,
`redirect` varchar(50) character set utf8 collate utf8_unicode_ci NOT NULL,
`perm_type` enum('allow','deny') NOT NULL default 'allow',
`created` datetime NOT NULL default '0000-00-00 00:00:00',
`modified` datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
);
CREATE TABLE `groups_permissions` (
`group_id` int(10) unsigned NOT NULL default '0',
`permission_id` int(10) unsigned NOT NULL default '0',
KEY `group_id` (`group_id`,`permission_id`)
);
CREATE TABLE `permissions` (
`id` int(10) unsigned NOT NULL auto_increment,
`name` varchar(50) NOT NULL default '',
`created` datetime NOT NULL default '0000-00-00 00:00:00',
`modified` datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
);
INSERT INTO groups VALUES (1,'webmasters',100,'','allow','0000-00-00 00:00:00','0000-00-00 00:00:00');
INSERT INTO groups VALUES (2,'editors',200,'','allow','0000-00-00 00:00:00','0000-00-00 00:00:00');
INSERT INTO groups VALUES (3,'members',300,'','allow','0000-00-00 00:00:00','0000-00-00 00:00:00');
INSERT INTO users VALUES (1,'root','e10adc3949ba59abbe56e057f20f883e','Firstname Lastname','user@example.com','0000-00-00 00:00:00',1,1,'0000-00-00 00:00:00','0000-00-00 00:00:00');INSERT INTO permissions VALUES (1,'*','0000-00-00 00:00:00','0000-00-00 00:00:00');
INSERT INTO permissions VALUES (2,'news','0000-00-00 00:00:00','0000-00-00 00:00:00');
INSERT INTO permissions VALUES (3,'userprofiles','0000-00-00 00:00:00','0000-00-00 00:00:00');
INSERT INTO permissions VALUES (4,'userprofiles/view','0000-00-00 00:00:00','0000-00-00 00:00:00');
INSERT INTO permissions VALUES (5,'userprofiles/add','0000-00-00 00:00:00','0000-00-00 00:00:00');
INSERT INTO groups_permissions VALUES (1,1);
INSERT INTO groups_permissions VALUES (2,2);
INSERT INTO groups_permissions VALUES (2,3);
INSERT INTO groups_permissions VALUES (3,4);
INSERT INTO groups_permissions VALUES (3,5);
glx/app/models/group.php<?php
class User extends AppModel
{
var $name = 'User';
var $belongsTo = 'Group';
//var $recursive = 2;
}
?>
glx/app/models/permission.php<?php
class Group extends AppModel
{
var $name = 'Group';
var $hasMany = 'User';
var $hasAndBelongsToMany = array('Permission' =>
array('className' => 'Permission',
'joinTable' => 'groups_permissions'));
}
?>
glx/cake/app_model.php<?php
class Permission extends AppModel
{
var $name = 'Permission';
var $hasAndBelongsToMany = array('Group' =>
array('className' => 'Group',
'joinTable' => 'groups_permissions'));
}
?>
Add to the class in glx/cake/app_controller.php<?php
class AppModel extends Model
{
function unbindAll($params = array())
{
foreach($this->__associations as $ass)
{
if(!empty($this->{$ass}))
{
$this->__backAssociation[$ass] = $this->{$ass};
if(isset($params[$ass]))
{
foreach($this->{$ass} as $model => $detail)
{
if(!in_array($model,$params[$ass]))
{
$this->__backAssociation = array_merge($this->__backAssociation, $this->{$ass});
unset($this->{$ass}[$model]);
}
}
}
else
{
$this->__backAssociation = array_merge($this->__backAssociation, $this->{$ass});
$this->{$ass} = array();
}
}
}
return true;
}
}
?>
Add to glx/cake/app_controller.php<?php
var $components = array('othAuth'); // necessary, we need to have the othauth component so it can do it's business logic
var $helpers = array('Html', 'OthAuth'); // html is always needed, othauth helper is not a must, but you can do some cool things with it (see later on)
var $othAuthRestrictions = array( 'add','edit','delete'); // these are the global restrictions, they are very important. all the permissions defined above are weighted against these restrictions to calculate the total allow or deny for a specific request.
?>
glx/app/views/users/login.thtml<?php
function beforeFilter()
{
$auth_conf = array('mode' => 'oth',
'login_page' => '/admin/login',
'logout_page' => '/admin/logout',
'access_page' => '/admin/index',
'hashkey' => 'MySEcEeTHaSHKeYz',
'noaccess_page' => '/admin/noaccess',
'strict_gid_check' => false);
$this->othAuth->controller = &$this;
$this->othAuth->init($auth_conf);
$this->othAuth->check();
}
function login()
{
if(isset($this->params['data']))
{
$auth_num = $this->othAuth->login($this->params['data']['User']);
$this->set('auth_msg', $this->othAuth->getMsg($auth_num));
}
}
function logout()
{
$this->othAuth->logout();
$this->flash('You are now logged out!','/users/login');
}
function noaccess()
{
$this->flash("You don't have permissions to access this page.",'/admin/login');
}
?>
<h1>Log In:</h1>
<form action="<?php echo $html->url('/users/login'); ?>" method="post">
<div class="required">
<label for="user_username">Username</label>
<?php echo $html->input('User/username', array('id' => 'user_username', 'size' => '40')) ?>
<?php echo $html->tagErrorMsg('User/username', 'Please enter your username') ?>
</div>
<div class="required">
<label for="user_password">Password</label>
<?php echo $html->input('User/passwd', array('id' => 'user_passwd', 'size' => '40', 'type'=>"password")) ?>
<?php echo $html->tagErrorMsg('User/passwd', 'Please enter your password!') ?>
</div>
<?php echo $html->checkbox("User/cookie");?>
<div class="submit"><input type="submit" value="Login" /></div>
</form>
Warning: Call-time pass-by-reference has been deprecated - argument passed by value; If you would like to pass it by reference, modify the declaration of [runtime function name](). If you would like to enable call-time pass-by-reference, you can set allow_call_time_pass_reference to true in your INI file. However, future versions may not support this any longer. in /var/www/html/cake/2/app/controllers/components/oth_auth.php on line 791
Note that I had to go to extreme lengths to remove all the punctuation from the title of this note before I could post.
It is deprecated.
You can get rid of the error by removing the ampersand on line 791
On line 304, you'll see this :
$row = $UserModel->find($conditions);
Problem is...
If you have other models with associatons to the User model on level 0, and the other model might have like a belongsTo association with thousands of items/records...well...you get the idea.
The login on my site kept on timing out. I couldn't figure out what the problem was till I saw this. On every login, it was loading about 4000 records due to associations.
So...in short...
The User model needs to be set to recursive = false; Like this :
$UserModel -> recursive = false;
...on line 303
Greetings
Firzair
session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at D:wamp3hnappcontrollerscomponentsoth_auth.php:2) [COREcakelibssession.php, line 154]
Cannot modify header information - headers already sent by (output started at D:wamp3hnappcontrollerscomponentsoth_auth.php:2) [COREcakelibssession.php, line 155]
PHP 4.4
Cake 1.2
I don't know. I think I've followed all the directions.
Any help would be greatly appreciated.
I'm getting this :
Fatal error: Class 'Permission' not found in H:\xampp\htdocs\myspacefactory.com\cake\libs\model\model_php5.php on line 445
How can I solve it?
Going to look over the code now, but thought I'd post this so long.
Please help.
I'd like to do something like this
in somemodel.php
By this, I wont have to rewrite every find/findAll and any find/findall would give me just what i want.function beforeFind(&$q){
$q['conditions'] .= "AND user_id = '".$othAuth->user('user_id')."';
return true;
}
also, should the model class name for login_attempts be singular?
$del_sql = "DELETE FROM {$Model->useTable} WHERE expire <= NOW()";With :$del_sql = "DELETE FROM " . $Model->tablePrefix . $Model->useTable . " WHERE expire <= NOW()";For whose are using table prefixes.(sorry for my english).
I was entering MyControllerName for controller-wide permissions into the permissions table, but it was expecting my_controller_name instead.
Warning: Cannot modify header information - headers already sent by (output started at C:\AppServ\www\cake\maractivo\controllers\components\oth_auth.php:301) in C:\AppServ\www\cake\cake\libs\controller\controller.php on line 446
php 4.4.5
I have the same problem and am stuck on PHP 4.4.4 unfortunately. Is there a workaround?
Thanks
if($this->__notcurrent($page))
{
if($this->__notcurrent($page))
{
if ($this->RequestHandler->isAjax())
{
$this->RequestHandler->setAjax($this->controller);
// Brute force ! you've got a better way ?
echo '<script type="text/javascript">window.location = "'.
$this->url($page).
'"</script>';
exit;
}
else
{
$this->controller->redirect($page);
exit;
}
}
}
Surely only one if($this->__notcurrent($page)) statement is needed?
When I try to login with incorrect username or password, return error message like this: "Notice: Only variables should be assigned by reference in d:\webserver\public_html\cakephp\app\controllers\components\oth_auth.php on line 298"
How to fix this?
Thanks
1. Hashkey - should only be alphanumeric. If you have crazy characters it breaks the session saving. Maybe this is common knowledge? Would help if it was explicitly stated so you others don't waste time :P
2. The login functions return 1 for 'already logged in' and if everything goes smoothly. If you don't have auto-redirect and instead prefer to do your own thing the getMsg function will erroneously tell you 'already logged in.'
if($this->login_attempts_timeout > 0)
{
$timeout = $this->login_attempts_timeout * 60;
$del_sql .= " OR ( UNIX_TIMESTAMP(created) > UNIX_TIMESTAMP(NOW()) - $timeout )";
}
To:
if($this->login_attempts_timeout > 0)
{
$timeout = $this->login_attempts_timeout * 60;
$del_sql .= " OR ( UNIX_TIMESTAMP(created) < UNIX_TIMESTAMP(NOW()) - $timeout )";
}
That's all
Marc - voz ip
www.adamvozip.es
class AppController extends Controller {
var $components = array('othAuth');
var $helpers = array('html', 'othAuth');
//var $othAuthRestrictions = array('*');
var $othAuthRestrictions = array('admin');
function beforeFilter()
{
$auth_conf = array(
'mode' => 'oth',
'login_page' => '/users/login',
'logout_page' => '/users/logout',
'access_page' => '/users/index',
'hashkey' => 'hello',
'noaccess_page' => '/users/noaccess',
'strict_gid_check' => true);
$this->othAuth->controller = &$this;
$this->othAuth->init($auth_conf);
$this->othAuth->check();
}
}
?> and the sql stuff...
table: permissions
| id | name | created | modified |
+----+-------+---------------------+---------------------+
| 1 | * | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
| 2 | foros | 0000-00-00 00:00:00 | 0000-00-00 00:00:00
table: group_permissions
+----------+---------------+
| group_id | permission_id |
+----------+---------------+
| 1 | 1 |
| 2 | 2 |
mysql> select id, name, level, redirect, perm_type from groups;
+----+---------+-------+----------+-----------+
| id | name | level | redirect | perm_type |
+----+---------+-------+----------+-----------+
| 1 | prepas | 100 | | allow |
| 2 | alumnos | 200 | | allow |
+----+---------+-------+----------+-----------+
SO, any action named "admin_action" asks for the user to login, but, when i access to foros action, it doesnt ask login to user :S
You have to add restrictions to other actions.
var $othAuthRestrictions = array('admin', 'view', 'edit', 'delete');
waiting reply... thanks!!!!
$data[$this->history_model]['fullname'] = $row[$this->user_model]['fullname'];
Using the code above, the users table uses 'name' not 'fullname'. So, Line 503 should be:
$data[$this->history_model]['fullname'] = $row[$this->user_model]['name'];
Thanks for all the great work.
If I put the beforeFilter as above in app_controller.php, then it seems to apply to every controller, and I cannot see how I can do make a few actions public. Surely there must be a better way for me make a few actions public than to add the beforeFilter to each indivdual controller?
I guess I don't really understand the permissions system.
BTW, I think md5 or sha1 with a salt should be used as default to avoid dictionary bruteforce. Well, users can use a callback function but I believe that feature should be default.
After a failed login attempt:
Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/sandbox/cake/app/models/user.php:10) in /var/www/html/sandbox/cake/app/controllers/components/oth_auth.php on line 716
Line 716: setcookie('othAuth.login_attempts',$cdata,$time,'/');
After a successful login:
Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/sandbox/cake/app/models/user.php:10) in /var/www/html/sandbox/cake/app/controllers/components/oth_auth.php on line 603
Line 603: setcookie('othAuth.login_attempts','',time() - 31536000,'/');
I guess turning off tracking login attempts might fix this problem. But I really need that feature.
And, if I check the "remember me" checkbox, and log in succesfully, in addition to the error on line 603 I get this one too:
Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/sandbox/cake/app/models/user.php:10) in /var/www/html/sandbox/cake/app/controllers/components/oth_auth.php on line 549
Line 549: setcookie('othAuth',$data,$time,'/');
Jeremy, you probably have the same issue. Delete any blank spaces and/or lines at the end of the file (after the closing php tag) which is accused of outputting headers. In your case that would be at the end of oth_auth.php.
The same error can occur if there are blank lines/spaces before the opening php tag.
}if($this->login_attempts_timeout > 0)
{
$timeout = $this->login_attempts_timeout * 60;
// $del_sql .= " OR ( UNIX_TIMESTAMP(created) > UNIX_TIMESTAMP(NOW()) - $timeout )";
Otherwise, it was always deleting the entries in the login attempts table, making the number of tries always 1, and so never rejecting people based on too many login attempts. I don't know why, but commenting out that line did the trick.
$data[$this->history_model]['fullname'] = $row[$this->user_model]['name'];
or change the column 'name' of users mysql table to 'fullname'.
You nedd to add the user_history model in /app/models/user_history.php:
class UserHistory extends AppModel
{
var $name = 'UserHistory';
var $useTable = 'user_histories';
}
?>
Here is the error I get:
Warning: session_start() [function.session-start]: Cannot send session cookie - headers already sent by (output started at cake\app\controllers\components\oth_auth.php:1450) in D:\www\public_html\CincyWebSolutions-2.0\cake\libs\session.php on line 131
Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at cake\app\controllers\components\oth_auth.php:1450) in D:\www\public_html\CincyWebSolutions-2.0\cake\libs\session.php on line 131
The last line of oth_auth.php is line #1450. Where else would cake be outputting anything?
Any help would be greatly appreciated.
Thanks, Jeremy
Then use it like this:
View Template:
if($othAuth->hasPermission('items/delete')){ ... }
Helper Class:
<?php
function hasPermission($val,$arg='name')
{
$perms = $this->permission($arg);
if (in_array('*',$perms))
{
return true;
}
if (in_array($val,$perms))
{
return true;
}
$vals = explode('/',$val);
$val = '';
for ($i=0; $i<count($vals); $i++)
{
if ($i)
{
$val .= '/';
}
$val .= $vals[$i];
if (in_array($val,$perms))
{
return true;
}
}
return false;
}
?>
"Fatal error: Class 'User' not found in mypath\app\controllers\components\oth_auth.php on line 1334"
Relevant line (1334) is "$UserModel =& new $this->user_model;" in the _createModel() function.
Sorry if there is an easy fix to this, I am really new to Cake so just learning the ins and outs.
Please note: by "close the browser", i mean completely close it and restart it. Not simply navigating away from the application and coming back.
In \app\controllers\components\oth_auth.php, lines 750-751 need to be modified.
Original:
$this->Session->write('othAuth.frompage',$this->controller->params['url']['url']);
$page .= "?".$this->auth_url_redirect_var."=".$this->controller->params['url']['url'];
Revised:
if(isset($this->controller->params['url']['url'])) {
$this->Session->write('othAuth.frompage',$this->controller->params['url']['url']);
$page .= "?".$this->auth_url_redirect_var."=".$this->controller->params['url']['url'];
}
The correct path is:
\app\controllers\components\oth_auth.php
I hope you or somebody expands the article to include the nao mode because having users belong to multiple groups is really needed by lots of applications, especially intranet apps where the groups are named after different departments of the company and the directors need to be assigned to all of them for example..
Thanks.
I am just wondering, using your AUTH Model, how would I be able to create a new User?
Say i have an array $signupdata in the form
Array (
[User] => Array ( [username] => asdf [email] => asdf@asdf [password] => asdf [how] => asdf [credit] => 100 [dob] => 2006-07-07 00:00:00 ) )
and in my controller, i did ($this->User->save($signupdata))
This returns me 0 which I suppose it failed. Anything I am doing that is wrong here?
I have completed the five steps in Othman's article.. after the installation I got the following errors: 'Undefined property: Group::$Permission in..' and 'Fatal error: Call to a member function unbindAll()'. I have made the following models: group, group_permissons, login_attempts, permissions, users and user_histories. Can somebody help me, I'm new to CakePHP.
also i noticed another oddity: if your login/out actions are in users_controller, then if you place a '*' restriction in that controller, you will still be able to access the login page AND the logout page, but any other action in that controller, will redirect you to login. if, however, you explicitly list the restricted actions: array('login', 'logout', etc) then you can still access the login page but NOT the logout page (it will redirect you to login). this is true if your restrictions are declared as described in app-controller instead of a specific controller too. another oddity, just wondering if anyone else noticed.
anyone implemented a form of 'challenge-response authentication' into othAuth to make it the ultimate cake auth package?
http://cake-php.googlegroups.com/web/othauth.php?gda=ctzDdEEAAAAHrv8IS8nhNsvUTvIFd3GaH-5x9hkpgjHywALnK9jx2hVJVT3hrgKrn_IySc8la3L2GiaXqyOPbAkqeyr49WeedCJfaee7TamSXSOlVydL_w
Othman please tell me how is best way to change group user's in login session
this is a very nice helper. the right for which i am searching.
bt i wonder if its possible to grant users ony access to edit their own objects (posts etc) without adding a new ACO for each post?
kind regards,
alex
I'm not sure I understand correctly what you mean but anyway, othAuth is abstract thing, which means it doesn't have the notion of objects that belong to a user or even the notion of edit. it's up to use to grant useful permissions to less abstract things
Regards
I did run into a problem, however. In the component code, it sets the user table password column to be 'passwd', but in the SQL you provide to build the table you use 'password'. So I got an error saying that User.passwd didn't exist.
I fixed the error by changing the login.thtml file to reference "Users/password" instead of "Users/passwd" then in the component file, I chaned any of the config variables that referred to "passwd" to instead refer to "password".
Unless, it should be "passwd" and the database scheme is wrong?
just wanted to start using othAuth, but the download links seem broken.
Both,
- the component: http://bakery.cakephp.org/articles/view/99 and
- the helper: http://bakery.cakephp.org/articles/view/149
are down (Bakery flashes 'Invalid article').
Could U please re-provide the pages?
Thx a lot & keep up the great work!
carsten
The helper is back online, but article 99 is still up for review/not available to public...
Any date or timelapse when we'll be able to taste your goods?
but it should beif((count($perm_parts) > 1) &&
($perm_parts[0] == CAKE_ADMIN) &&
($perm_parts[1] == $c) &&
($perm_parts[2] == "*"))
{
return true;
}
i.e. count($perm_parts) > 2 in the if clause.if((count($perm_parts) > 2) &&
($perm_parts[0] == CAKE_ADMIN) &&
($perm_parts[1] == $c) &&
($perm_parts[2] == "*"))
{
return true;
}
To save the parameters, you will need to modify redirect function..here is the new redirect function
function redirect($page = "",$back = false)
{
if($page == "")
//$page = $this->redirect_page;
$page = $this->logout_page;
if(isset($this->auth_url_redirect_var))
{
if(!isset($this->controller->params['url'][$this->auth_url_redirect_var]))
{
if($back == true)
{
// this is where i modified the function...
$frompage = '/';
if(isset($this->controller->params['url']['url'])){
$frompage = $this->controller->params['url']['url'];
$parameters = $this->controller->params['url'];
unset($parameters['url']);
$para = array();
foreach($parameters as $key => $value)
$para[] = $key . '=' . $value;
if(count($para) > 0){
$frompage .= '?' . implode('&',$para);
}
}
// end of modification
$this->Session->write('othAuth.frompage',$frompage);
$page .= "?".$this->auth_url_redirect_var."=".$frompage;
}
else
{
if($this->Session->check('othAuth.frompage'))
{
$page = $this->Session->read('othAuth.frompage');
$this->Session->del('othAuth.frompage');
}
}
}
}
if($this->__notcurrent($page))
{
if($this->__notcurrent($page))
{
if ($this->RequestHandler->isAjax())
{
$this->RequestHandler->setAjax($this->controller);
// Brute force !
echo 'window.location = "'.
$this->url($page).
'"';
exit;
}
else
{
$this->controller->redirect($page);
exit;
}
}
}
}
Finally, in the init() function in the othAuth helper, I changed "$this->view->viewVars['othAuth_data']" to "$this->view->_viewVars['othAuth_data']" and it finally worked.
Hope this helps someone.
Comments are closed for articles over a year old