├── README.md
├── application
├── config
│ └── bitauth.php
├── controllers
│ └── example.php
├── language
│ └── english
│ │ └── bitauth_lang.php
├── libraries
│ ├── Bitauth.php
│ ├── MY_Form_validation.php
│ └── phpass.php
└── views
│ └── example
│ ├── activation_failed.php
│ ├── activation_successful.php
│ ├── add_group.php
│ ├── add_user.php
│ ├── edit_group.php
│ ├── edit_user.php
│ ├── groups.php
│ ├── login.php
│ ├── no_access.php
│ └── users.php
├── bitauth.sql
└── user_guide
├── general
├── config.html
├── notes.html
├── utility.html
└── validation.html
├── groups
├── adding.html
├── assigning.html
├── editing.html
└── fetching.html
├── images
├── arrow.gif
├── nav_bg_darker.jpg
├── nav_separator_darker.jpg
├── nav_toggle_darker.jpg
└── transparent.gif
├── index.html
├── nav
├── hacks.txt
├── moo.fx.js
├── nav.js
├── prototype.lite.js
└── user_guide_menu.js
├── roles
├── checking.html
├── creating.html
└── setting.html
├── toc.html
├── userguide.css
└── users
├── adding.html
├── assigning.html
├── customizing.html
├── editing.html
├── fetching.html
└── logging_in.html
/README.md:
--------------------------------------------------------------------------------
1 | #BitAuth
2 |
3 | * [Website](http://www.dmontgomery.net/bitauth) - http://www.dmontgomery.net/bitauth
4 | * [Github](https://github.com/danmontgomery/codeigniter-bitauth) - https://github.com/danmontgomery/codeigniter-bitauth
5 | * [Issues](https://github.com/danmontgomery/codeigniter-bitauth/issues) - https://github.com/danmontgomery/codeigniter-bitauth/issues
6 |
7 | ##Requirements
8 | * PHP 5.1.6+, 5.3+ recommended
9 | * CodeIgniter 2.0+
10 | * MySQL
11 | * ~~php-gmp~~
12 |
13 | ##Features
14 | * Phpass Integration: BitAuth uses [phpass](http://www.openwall.com/phpass/) to handle password hashing
15 | * Password complexity rules: Along with minimum and maximum length, specify the required number of:
16 | * Uppercase Characters
17 | * Numbers
18 | * Special Characters
19 | * Spaces
20 | * ... Or, add your own
21 | * Password aging: Require your users to change their passwords at a set interval
22 | * Completely custom userdata: Easily customize BitAuth to include any custom you want. Full name, Nickname, Phone number, Favorite color... You name it!
23 | * Groups and Roles: Create groups, and assign users to your groups. Your roles are set on a group, not a user, so changing roles, whether the scale is large or small, is fast and painless.
24 | * Text-based roles: Simply list your roles in the configuration file, then check against them in your code. BitAuth handles everything in between.
25 |
26 | ##Download
27 | [https://github.com/danmontgomery/codeigniter-bitauth/tarball/v0.2.1](https://github.com/danmontgomery/codeigniter-bitauth/tarball/v0.2.1)
28 |
29 | ##Installation
30 | Copy the included files to their appropriate locations in the application/ folder. Import bitauth.sql into your database. **If you would like to change the names of the tables BitAuth uses, you can change them in this .sql file, and must also change them in config/bitauth.php**.
31 |
32 | ##Updating
33 | If updating from v0.1.x, there is a convert() function in the Example controller. This will modify the structure of your groups table, as well as convert any roles you have stored to the new format. This function uses base_convert(), which means results may vary depending on the machine you're running this on. After upgrading, be sure to check the roles in your groups for accuracy.
34 |
35 | ##Notes
36 | As of v0.2.0, php-gmp is no longer used. The structure of the bitauth_groups table has changed, as well.
37 |
38 | The default login is **admin**/**admin**.
39 |
40 | I **highly** recommend you not use the default cookie session... [Try my driver replacement](http://getsparks.org/packages/session-driver/show) for CI's session library (end of shameless self promotion).
41 |
42 | Currently, only MySQL is supported. This may change in the future. Or not. We'll see.
--------------------------------------------------------------------------------
/application/config/bitauth.php:
--------------------------------------------------------------------------------
1 | 1,
68 | 'number' => 1,
69 | 'special' => 0,
70 | 'spaces' => 0,
71 | );
72 |
73 | /**
74 | * Which characters are included in each complexity check. Must be in
75 | * regex-friendly format. Using the Posix Collating Sequences should make these
76 | * language-independent, but are here in case you want to change them.
77 | */
78 | $config['pwd_complexity_chars'] = array(
79 | 'uppercase' => '[[:upper:]]',
80 | 'number' => '[[:digit:]]',
81 | 'special' => '[[:punct:]]',
82 | 'spaces' => '\s'
83 | );
84 |
85 | /**
86 | * Number of seconds a "forgot password" code is valid for
87 | * Default: 3600
88 | */
89 | $config['forgot_valid_for'] = 3600;
90 |
91 | /**
92 | * Whether or not to log login attemps. If set to FALSE, users can no longer
93 | * be locked out by invalid login attempts.
94 | * Default: TRUE
95 | */
96 | $config['log_logins'] = TRUE;
97 |
98 | /**
99 | * Number of invalid logins before account is locked.
100 | * Set this to 0 to disable this functionality.
101 | * Default: 3
102 | */
103 | $config['invalid_logins'] = 3;
104 |
105 | /**
106 | * Number of minutes between invalid login attemps where a user will be locked
107 | * out
108 | * Default: 5
109 | */
110 | $config['mins_login_attempts'] = 5;
111 |
112 | /**
113 | * Number of minutes before a locked account is unlocked.
114 | * Default: 10
115 | */
116 | $config['mins_locked_out'] = 10;
117 |
118 | /**
119 | * Tables used by BitAuth
120 | */
121 | $config['table'] = array(
122 | 'users' => 'bitauth_users', // Required user information (username, password, etc)
123 | 'data' => 'bitauth_userdata', // Optional user information (profile)
124 | 'groups' => 'bitauth_groups', // Groups
125 | 'assoc' => 'bitauth_assoc', // Users -> Groups associations
126 | 'logins' => 'bitauth_logins' // Record of all logins
127 | );
128 |
129 | /**
130 | * Base-2 logarithm of the iteration count used for password stretching by
131 | * Phpass
132 | * See: http://en.wikipedia.org/wiki/Key_strengthening
133 | * Default: 8
134 | */
135 | $config['phpass_iterations'] = 8;
136 |
137 | /**
138 | * Require the hashes to be portable to older systems?
139 | * From: http://www.openwall.com/articles/PHP-Users-Passwords
140 | * Unless you force the use of "portable" hashes, phpass' preferred hashing
141 | * method is CRYPT_BLOWFISH, with a fallback to CRYPT_EXT_DES, and then a final
142 | * fallback to the "portable" hashes.
143 | * Default: FALSE
144 | */
145 | $config['phpass_portable'] = FALSE;
146 |
147 | /**
148 | * What format BitAuth stores the date as. By default, BitAuth uses DATETIME
149 | * fields. If you want to store date as a unix timestamp, you just need to
150 | * change the columns in the database, and change this line:
151 | * $config['date_format'] = 'U';
152 | * See: http://php.net/manual/en/function.date.php
153 | */
154 | $config['date_format'] = 'Y-m-d H:i:s';
155 |
156 | /**
157 | * Your roles. These are how you call permissions checks in your code.
158 | * eg: if($this->bitauth->has_role('example_role'))
159 | * DO NOT reorder these once they have been assigned.
160 | */
161 | $config['roles'] = array(
162 |
163 | /**
164 | * THE FIRST ROLE IS ALWAYS THE ADMINISTRATOR ROLE
165 | * ANY USERS IN GROUPS GIVEN THIS ROLE WILL HAVE FULL ACCESS
166 | */
167 | 'admin' => 'User is an Administrator',
168 | /**
169 | * Add as many roles here as you like.
170 | * Follow the format:
171 | * 'role_slug' => 'Role Description',
172 | */
173 |
174 | );
--------------------------------------------------------------------------------
/application/controllers/example.php:
--------------------------------------------------------------------------------
1 | load->library('bitauth');
15 |
16 | $this->load->helper('form');
17 | $this->load->helper('url');
18 |
19 | $this->load->library('form_validation');
20 | $this->form_validation->set_error_delimiters('
BitAuth has the following configuration options available:
60 |
61 |
62 |
63 |
Config
64 |
Default Value
65 |
Options
66 |
Description
67 |
68 |
69 |
require_user_activation
70 |
TRUE
71 |
TRUE, FALSE
72 |
If set to TRUE, users must be activated before they are able to login.
73 |
74 |
75 |
default_group_id
76 |
2
77 |
Any Existing Group ID
78 |
The group_id of the default group users will be added to when they register. NOTE: This group's roles will not be inherited by the user until they are activated.
79 |
80 |
81 |
remember_token_name
82 |
rememberme
83 |
84 |
Name of the cookie where the "Remember Me" token is stored. This value is prefixed with cookie_prefix value in config.php, if one is set.
85 |
86 |
87 |
remember_token_expires
88 |
604800 (7 days)
89 |
90 |
Number of seconds that the "Remember Me" token lasts before expiring. Once this time has passed, the user will need to login again the next time they visit.
91 |
92 |
93 |
remember_token_updates
94 |
TRUE
95 |
TRUE, FALSE
96 |
If set to TRUE, the timer on the "Remember Me" token will reset every time this user revisits the site.
97 |
98 |
99 |
pwd_max_age
100 |
90
101 |
102 |
Number of days a password is valid for. Once this time has passed, a user cannot login, and must have their password reset by an administrator or through the "Forgot Password" page. To disable, set to FALSE.
103 |
104 |
105 |
pwd_age_notification
106 |
7
107 |
108 |
Number of days before password expiration that a user is notified. Once inside this number of days, the user will be directed to a form to change their password every time they login automatically. To disable, set to FALSE.
109 |
110 |
111 |
pwd_min_length
112 |
8
113 |
114 |
Minimum required length of passwords. To disable, set to FALSE.
115 |
116 |
117 |
pwd_max_length
118 |
20
119 |
120 |
Maximum allowable length of passwords. To disable, set to FALSE.
121 |
122 |
123 |
pwd_complexity
124 |
Uppercase: 1 Numbers: 1 Special Chars: 0
125 |
126 |
Minimum number of each type of character required for a password to valid. To disable requirements for any type of character, set that value to 0.
127 |
128 |
129 |
pwd_complexity_chars
130 |
Uppercase: [[:upper:]] Numbers: [[:digit:]] Special Chars: [[:punct:]] Spaces: \s
131 |
132 |
The regular expression for each type of character. The default values should be language independent, so you should not need to change them.
133 |
134 |
135 |
log_logins
136 |
TRUE
137 |
TRUE,FALSE
138 |
Whether or not to log login attemps. Setting this to FALSE effectively disables locking out users from invalid login attemps.
139 |
140 |
141 |
invalid_logins
142 |
3
143 |
144 |
How many invalid logins a user gets before they are locked out.
145 |
146 |
147 |
mins_login_attempts
148 |
5
149 |
150 |
Number of minutes between invalid login attemps where a user will be locked out.
151 |
152 |
153 |
mins_locked_out
154 |
10
155 |
156 |
Number of minutes before a locked account is unlocked.
Require the hashes to be portable to older systems. If FALSE, phpass' preferred hashing method is CRYPT_BLOWFISH, with a fallback to CRYPT_EXT_DES, and then a final fallback to the "portable" hashes. See: http://www.openwall.com/articles/PHP-Users-Passwords.
184 |
185 |
186 |
date_format
187 |
Y-m-d H:i:s
188 |
189 |
What format BitAuth stores timestamps in. Defaults to the MySQL DATETIME format. To use unix timestamps, change this value to 'U' (in addition to changing your DB structure).
190 |
191 |
192 |
roles
193 |
194 |
195 |
196 |
This is where all of your roles are stored. There is only one role required by BitAuth, admin. This should always be the first listed.
BitAuth stores roles in the session (encrypted), which means if you are using CodeIgniter's default session settings, roles are stored in a cookie. I can't advise against this strongly enough. You should, at a bare minimum be encrypting the session cookie by enabling sess_encrypt_cookie in config.php. Even better, you should be using database sessions so the information is stored server-side.
60 |
Why PHP 5.3+?
61 |
As of 5.3.0, crypt_blowfish is integrated into the PHP interpreter, which means PHPass will never fall back to CRYPT_EXT_DES or md5.
62 |
63 |
Limitations
64 |
Currently, you are limited to 64 roles. This is due to MySQL's limitation of 64 bits when working with bit operations. No more limitations on the number of roles!
65 |
What is NOT included?
66 |
67 |
Built-In Email Functionality (email for activation, forgot password, etc)
This will hash the plain text password passed to $new_password, and update the user along with the value for password_last_set.
64 |
65 |
$this->bitauth->get_role($slug)
66 |
This will return the bit offset for a role based on the slug that is passed. This is a utility function used internally in BitAuth.
67 |
68 |
$this->bitauth->get_roles()
69 |
This returns an array of all roles defined in the configuration. The array is exactly as it's defined, in the format:
70 |
array( 'slug' => 'description' );
71 |
72 |
$this->bitauth->set_login_field($field)
73 |
Declares a field that must be matched on login. There is no processing done before or after this check, an exact match is required. So, for example, if you want a
74 | case-insensitive match, you should run strtolower() on the data before it's stored in the database, and also on the form data before it's checked.
Stores an error message in BitAuth. Currently, BitAuth only stores one message at a time. By default, this message will be saved to the session,
82 | you can disable this by passing FALSE as the second parameter.
83 |
84 |
$this->bitauth->get_error($incl_delim = TRUE)
85 |
Retrieves the message stored by $this->bitauth->set_error(). The message is wrapped with $_error_delim_prefix and $_error_delim_suffix, unless passed FALSE as a parameter.
This function returns a string explaining the complexity requirements you have defined in your configuration.
104 | Called by the bitauth_valid_password form_validation rule.
105 |
106 |
Returns FALSE if the group name is not unique. Pass a group_id as an optional parameter to exclude that group from the check.
77 |
bitauth_unique_group bitauth_unique_group[2]
78 |
79 |
80 |
bitauth_valid_password
81 |
No
82 |
Returns FALSE if the password does not meet the complexity requirements you have specified in the configuration. This rule
83 | also checks the pwd_min_length and pwd_max_length you have specified, so separate use of those rules is unnecessary.
Just like when assigning groups to the user, adding users to the group is done by passing an array of user_ids to the group
60 | object in the members attribute.
61 |
When Adding a Group
62 |
There are no default members when creating a group, so if you don't specify any the group will be empty. Specifying members, however, is quite simple.
CodeIgniter 2.0+ (BitAuth was built on Reactor, when that was a thing)
60 |
MySQL
61 |
php-gmp
62 |
63 |
64 |
Features
65 |
66 |
Phpass: BitAuth uses phpass to handle password hashing
67 |
Password complexity rules: Along with minimum and maximum length, specify the required number of:
68 |
69 |
Uppercase Characters
70 |
Numbers
71 |
Special Characters
72 |
Spaces
73 |
... Or, add your own
74 |
75 |
76 |
Password aging: Require your users to change their passwords at a set interval
77 |
Completely custom userdata: Easily customize BitAuth to include any custom you want. Full name, Nickname, Phone number, Favorite color... You name it!
78 |
Groups and Roles: Create groups, and assign users to your groups. Your roles are set on a group, not a user, so changing roles, whether the scale is large or small, is fast and painless.
79 |
Text-based roles: Simply list your roles in the configuration file, then check against them in your code. BitAuth handles everything in between.
Users can be members of one or many groups. Roles are assigned to a group. When a user is a member of a group, he or she inherits all roles of that group. If a user is a member of multiple groups, he or she inherits all of the combined roles of those groups.
60 |
Checking Roles
61 |
62 |
$this->bitauth->has_role($slug, $mask = NULL)
63 |
Checks whether a user or group has a role. If $mask is NULL, the currently logged in user is assumed.
64 |
65 |
Checking the current user
66 |
if($this->bitauth->has_role('can_edit'))
67 | {
68 | echo "Current user has 'can_edit' role.";
69 | }
Roles are created in the configuration file. What roles you choose are completely up to you, BitAuth only requires one: admin.
60 | The roles section of the configuration file looks like this:
61 |
/**
62 | * Your roles. These are how you call permissions checks in your code.
63 | * eg: if($this->bitauth->has_role('example_role'))
64 | */
65 | $config['roles'] = array(
66 |
67 | /**
68 | * THE FIRST ROLE IS ALWAYS THE ADMINISTRATOR ROLE
69 | * ANY USERS IN GROUPS GIVEN THIS ROLE WILL HAVE FULL ACCESS
70 | */
71 | 'admin' => 'User is an Administrator',
72 | /**
73 | * Add as many roles here as you like.
74 | * Follow the format:
75 | * 'role_slug' => 'Role Description',
76 | */
77 |
78 | );
79 |
80 |
Creating roles is as simple as adding new elements to this array:
81 |
'sample_role' => 'This is a sample role',
82 |
83 |
The slug is how you check that role in your code. The description is how you describe that role in human-readable language.
84 |
85 |
You can add any number of roles you like in this format, as long as the first (admin) remains at the top of the list. You can change the slug and description of this role, the first on the list will always be treated as the administrator role. No matter what you change the slug to be, you can always check for this role with $this->bitauth->is_admin().
When adding a user, there are two required fields: username and password. The password must be given
60 | in clear text. BitAuth will handle the password hashing.
61 |
If you have customized user data, you only need to pass these fields to add_user() with all
62 | of the other data, BitAuth will put them in the appropriate table.
If you don't specify a groups attribute, the configuration value of default_group_id is used.
72 | For information about adding users to groups, see Assigning Groups or Adding Members.
73 |
$require_activation defaults to the configuration value of require_user_activation.
74 | How you handle user activation is completely up to you. If this value is TRUE, an activation code is generated and stored in the
75 | activation_code field.
In order to add your own password complexity rules, you need to make 3 changes.
85 |
In config/bitauth.php, you need to add a line to both $config['pwd_complexity'] and $config['pwd_complexity_chars']. pwd_complexity contains the required number of characters, and pwd_complexity_chars contains the regular expression to check for those characters.
86 |
/**
87 | * Optional password complexity options. Set a number for each to
88 | * require that many characters, or set to 0 to disable
89 | * Default: 1, 1, 0, 0
90 | */
91 | $config['pwd_complexity'] = array(
92 | 'uppercase' => 1,
93 | 'number' => 1,
94 | 'special' => 0,
95 | 'spaces' => 0,
96 | 'dash' => 1
97 | );
98 |
99 | /**
100 | * Which characters are included in each complexity check. Must be in
101 | * regex-friendly format. Using the Posix Collating Sequences should make these
102 | * language-independent, but are here in case you want to change them.
103 | */
104 | $config['pwd_complexity_chars'] = array(
105 | 'uppercase' => '[[:upper:]]',
106 | 'number' => '[[:digit:]]',
107 | 'special' => '[[:punct:]]',
108 | 'spaces' => '\s',
109 | 'dash' => '-'
110 | );
111 |
112 |
Then, you just need to add a line to language/english/bitauth_lang.php, which contains the language line called when the rule fails validation.
Assigning a user to one or more groups is as simple as passing an array of group_ids to that user when adding or updating.
60 |
When Adding a User
61 |
When adding a user, you can pass an array of group_ids for that user to be added to. If you don't, the user will be added to
62 | whatever you have specified in the configuration file as default_group_id.
BitAuth has a number of required fields, and they are all in the users table (default: bitauth_users).
60 | Anything in the data (default: bitauth_userdata) table is optional, and you can customize this table
61 | to include anything you like. This table will only be updated when data is passed to add_user() or update_user()
62 | that is not found in the users table.
63 |
To include custom user data in BitAuth, all you need to do is update the structure of bitauth_userdata with your new fields,
64 | then pass data for those new fields to add_user() and update_user(). That's it! BitAuth determines which table
65 | the data given to it belongs to, and it will insert or update the appropriate table. Also, just by being in the userdata table, your
66 | custom data will be included with the user object that is returned when fetching users.
67 |
For example, if you add the column mydata to the userdata table, you can access that attribute easily with:
Editing a user is as simple as passing a user_id and the user data to update_user(). $data may be an object or an array.
60 | Only the information you give is updated, and what information you do give overwrites what is currently stored. Just like with add_user(),
61 | BitAuth is able to determine whether the information you are updating is in the users table or the data table.
Users who are disabled will not be able to login, are removed from all groups, and aren't returned by get_users() or get_groups()
88 | (see Fetching Users for information on overriding this).
89 |
Users who are deleted, in addition to being disabled, also have their corresponding row deleted in the data table (bitauth_userdata).
90 | Essential information (user_id and username) should be kept for posterity.
Timestamp of when the user's password was last set
80 |
81 |
82 |
password_never_expires
83 |
Boolean value, set to TRUE and the user's password will never expire.
84 |
85 |
86 |
remember_me
87 |
"Remember Me" token, if the user has a currently active "remember me" login
88 |
89 |
90 |
activation_code
91 |
Random hash for activation code, if this option is enabled in the configuration
92 |
93 |
94 |
active
95 |
Whether user is active or not
96 |
97 |
98 |
enabled
99 |
Whether user is enabled or not. If FALSE, user will not show up by default in any queries for fetching users
100 |
101 |
last_login
102 |
Timestamp of when the user last logged in
103 |
104 |
105 |
last_login_ip
106 |
IP the user last logged in from
107 |
108 |
109 |
groups
110 |
Array of group_ids the user is a member of
111 |
112 |
113 |
roles
114 |
Numeric representation of the user's inherited roles. You cannot set this value directly on the user.
115 |
116 |
117 |
118 |
Along with all of this information, any custom user data you may have is also returned. You can access and edit this information exactly as you would any other user information.
Returns all users. Each user object contains the information listed above. By default, any users with enabled = 0 will be excluded.
122 | Pass TRUE as the second parameter to override this. For information on disabled/deleted users see Disabling/Deleting Users.
Tries to authenticate the user, and sets the "Remember Me" token if appropriate. Returns FALSE and sets an error message retrieved with get_error() if authentication fails. The following code is from the example that comes with BitAuth:
Once logged in, all userdata for the user is assigned directly to the BitAuth object in the same manner as get_users(),
91 | with the exception of the password:
92 |
echo $this->bitauth->username;
93 |
For information on all of the available fields, see Fetching Users.
94 |
95 |
Requiring Additional Login Fields
96 |
Username is always required. You can, however, add any number of additional fields which will be checked at login. This is a 2-step process. First, you must tell BitAuth to expect the field(s):
97 |
$this->bitauth->add_login_field('email');
98 |
Once this is done, you simply have to pass the data to login() as an associative array. So, we would update our earlier example:
In order to get an error message for these fields if they fail validation, you must add a line to the language file, bitauth_invalid_{field} (ie, bitauth_invalid_email).
121 |
$lang['bitauth_invalid_email'] = 'Email does not match this username';
122 |
This function also accepts an array for multiple fields:
To login with something besides username; to use email as a username, for example, simply change the bitauth_username line in the language file to whatever label you like,
126 | and setup the form_validation for your login form appropriately.
127 |
128 |
$this->bitauth->login_from_token()
129 |
If a valid "Remember Me" token is found, but not an active login, BitAuth will try to login from that token. If the login is invalid, the token is destroyed. This can be seen in BitAuth's __construct():
Returns TRUE if the user is within pwd_max_age days of the maximum password age config setting. If no $user
147 | is given, the currently logged in user is assumed.
148 |
149 |
$this->bitauth->password_is_expired($user = NULL)
150 |
Returns TRUE if the user's password is expired. If no $user is given, the currently logged in user is assumed.