Sessions, authentication, user and permission systems
- The authPass object
- Extending the authPass object using
hook_auth_authpass
- Accessing currently active sessions
- Managing authentication on the server side
- Clearing all of a user's access tokens using `hook_auth_clearauth'
- Roles and permissions
- User accounts
- Authentication when making REST requests from outside of Iris
Access to Iris is managed through a system of userids and access tokens which, if successfully paired together, form an authPass which contains information about a user or machine accessing the system. If userid and access tokens are not provided an anonymous authpass is created. Anonymous sessions are given an authPass with a unique userid of the format anon_<id>
, e.g. anon_a3ec5e9ab42e4d1f1f09d23
. This can be used to track and interact with a specific anonymous user.
An authPass typically looks something like this:
{
roles:["authenticated", "admin"],
userid: '1'
}
An authPass is assigned (via token/userid checks from cookies or information provided via REST parameters) automatically as soon as a request enters the system. If you have the Express request object (typically called req
) you should be able to find this using req.authPass
.
To find out the authPass of the session that started an Iris hook (see the hook system documentation for more information) look at the thisHook.authPass object inside the hook's callback function.
For example:
iris.modules.mymodule.registerHook("my_custom_hook", 0, function(thisHook, data){
console.log(thisHook.authPass);
thisHook.pass(data);
}
Sometimes you may need to get the authPass for a user that isn't that of the user making the current request. Using the currently active sessions list iris.modules.auth.globals.userList
you can use a special getAuthPass method to extract a user id. This returns a promise as its internal call to hook_auth_authPass
is asynchronous.
iris.modules.auth.globals.userList["1"].getAuthPass().then(function (authPass) {
// Do something with authPass
}, function(fail){
// Do something when authPass could not be retrieved.
});
To extend the authPass object (add extra roles etc) you can use the hook_auth_authpass
hook. The hook receives the HTTP request object in its thisHook.context object so you can read things like cookies or the requested url.
An example:
iris.modules.mymodule.registerHook('hook_auth_authpass', 0, function(thisHook, authPass){
if(authpass.roles.indexOf("admin") !== -1){
authpass.roles.push("superuser");
}
thisHook.pass(authPass);
})
Currently active sessions are stored in iris.modules.auth.userList
The iris.modules.auth.userList
object also contains a lastActivity property for each session. You can use this to find out when the user's last request was.
iris.modules.auth.userList["1"].lastActivity // Returns a timestamp
There are a series of hooks that can be used to create, edit and delete access tokens for a userid.
You can call hook_auth_maketoken with an object containing a userid to make a token for a user and create a session on the system for them. Note that the user calling this hook needs to have access to the "can make access token" permission (see section on permissions). A user with the admin role automatically gets all the permissions and will usually be the only caller of this function.
Here's an example from the api callback to make new tokens via the REST API:
iris.route.post('/auth/maketoken', function (req, res) {
iris.hook("hook_auth_maketoken", req.authPass, {
userid: req.body.userid
}).then(function (success) {
res.respond(200, success);
}, function (fail) {
res.send(fail);
});
});
You can delete a specific token for a user by calling `hook_auth_deletetoken'. If a user has no more access tokens when one is deleted their session is closed.
An example:
iris.route.post('/auth/deletetoken', function (req, res) {
// req.authpass contains {userid: ..., token: ... }
iris.hook("hook_auth_deletetoken", req.body, req.authPass).then(function (success) {
res.send(success);
}, function (fail) {
res.send(fail);
});
});
If the hook-calling user has the can delete user access
permission they can use this hook to clear all of a user's sessions. Useful on logging out.
Example
iris.app.post('/auth/clearauth', function (req, res) {
iris.hook("hook_auth_clearauth", req.body.userid, req.authPass).then(function (success) {
res.send(success);
}, function (fail) {
res.send(fail);
});
});
The base installation comes with three roles, anonymous (given automatically to not logged in users), authenticated (users that have logged in but have no extra roles (again given automatically)) and "admin". Admin allows a user to administrate the whole system so should be given sparingly.
More roles can be added with one line of code in a custom module.
iris.modules.auth.globals.registerRole("contributor");
This instantly makes it visible and usable in the permissions user interface. How a role is assigned to a user is up to you and your module.
Some permissions have already been created such as permissions to create, delete, view and edit entities of various types. Modules can register additional permissions.
iris.modules.auth.globals.registerPermission("can make access token", "auth", "this allows a user to make access tokens for other users to access the system")
To grant or revoke a permission for a role, visit the permissions tab in the administration toolbar and select/unselect the relevat box for the role/permission. Then hit save at the bottom on of the form.
To check a permission within a module use the iris.modules.auth.globals.checkPermissions function. This takes an array of permissions and an authPass to check against. It returns true or false.
if (iris.modules.auth.globals.checkPermissions(["my permission"], thisHook.authPass)) {
// This is run if the authPass has the "my permission" permission.
}
Iris comes with a user system which allows people to log in to your website/application and see/do different things depending on their role. Behind the scenes this simply calls the maketoken functions when a user supplies credentials that match a user entities username and password.
To log in to the administration system, visit /admin or /login and type in your access details.
To log out, either visit /logout or hit the logout button on the administration toolbar.
The user entity is a fieldable entity like any other, except for the password field (which is hashed and stored securely in the database), and a roles field where users can be given roles to allow various permissions.
All API requests are authenticated using a credentials object included in the GET or POST as a JSON encoded object containing userid
and token
. To generate an access token:
POST /api/login
with parameters:
{"username": YOURUSERNAME, "password": YOURPASSWORD}
If successful, a new auth object will be returned which will be used to validate future requests. You can also POST to auth/maketoken via the API to make tokens for any userid without requiring their username and password (if the user calling this has the relevant permissions).
// Credentials object
{ "userid": "1", "token": "a6b5cd4e8e3db2c18a7b2ee2" }
A new authtoken is generated on every valid call to /api/login
and legacy tokens remain valid until hard server reset.
When using the API from external services, the 'credentials' object (see above) need to be passed at the root level in all requests. An example of editing an entity in jQuery would be:
iris.server = "http://localhost:3000";
var editedEntity = {
eid: 5,
title: 'Entity title',
field_description: 'Example description'
};
var credentials = {
userid: 1,
token: 'ho87yoho87o8w7eyrfdfvfj9'
};
// The entity edit API endpoint expects to receive the entity object, but we also include the credentials to this object before sending.
editedEntity.credentials = credentials;
jQuery.ajax({
type: "POST",
url: iris.server + '/entity/edit/group/5',
data: groupEntity,
success: function (data, status) {
console.log(data, status);
},
error: function(jqXHR, status, errorThrown) {
console.log(jqXHR, status);
},
dataType: 'json'
});
If you wish to authenticate a web socket connection to use a particular Iris userid you will need to use the API to make an access token and then send a pair event with a credentials object containing this data.
For example:
iris.credentials = {
"userid": YOURUSERID
"token": YOURUSERTOKEN,
};
var socket = io(iris.server);
socket.on("connect", function () {
if (iris.credentials.userid) {
socket.emit('pair', {
credentials: iris.credentials
});
} else {
console.log("Anonymous connected with Iris")
}
});
- userid
- userid
- userid
- token
- username
- password
*Returns userid and token.
- None. Logs out the user for the authpass of the request. User clearauth if you wish to log out other users.
- Setting up an Iris site
- Folder structure
- Module system
- Restarting the server after code changes
- Hook system
- Entity system
- Theme and template system
- Form system
- Text filters
- Message system
- Routing system
- Sessions, authentication, user and permission systems
- Configuration system
- Menu system
- Translation system
- Triggers
- Websocket system
- Logs
- Adding tags (meta, css, javascript) to templates dynamically
- Block and region system