Commit c5842ec9 authored by Jure's avatar Jure
Browse files

Merge branch 'update-review' into 'master'

Update README.md

See merge request !19
parents 02b67ff6 dc145704
Pipeline #6046 passed with stage
in 37 seconds
# Authsome
Flexible team-based authorization module. This software is in an alpha stage.
Flexible attribute-based authorization module. This software is in a beta stage.
# Overview
Authsome is team-based, which means that authorization is determined based on team membership. A team consists of a group of members and belongs to one of the at team types configured at load time.
A team is always based around an object (the object of the authorization request). A team can also be conditionally active, i.e. only active if the current state of the object matches the requirement for team activation.
Best to explain this in an example. See Science Blogger mode example below.
Authsome is a minimal module with some syntax sugar surrounding a flexible attribute-based access control (ABAC) core. The external API consists of:
# Modes
Modes are exchangeable mechanisms of authorization (e.g. built in example modes: blog, journal, and noon).
# API example
```
const authsome = new Authsome({mode: yourMode}, context)
const permission = authsome.can(user, operation, object)
```
If Authsome configuration is:
The `authsome.can` bit is also named an authorization query/question in discussions and you'll see this term pop up in various places. They way your mode handles an authorization query is completely flexible, e.g. the simplest mode could look like:
```
let config = {
mode: require('./src/modes/blog'),
teams: {
teamContributors: {
name: 'Contributors',
permissions: 'create'
},
teamCoauthors: {
name: 'Coauthors',
permissions: 'update'
}
}
const yourMode = async function (user, operation, object, context) {
return true
}
```
Then Authsome can be created like so:
The above will just return true for any kind of authorization query, so it's not really useful (take a look at [example modes below](#example-modes)).
A useful but still minimal example might be something like this, where you instantiate a mode with a bit more `context`, in other words, more information about the environment where authorization questions are asked (e.g. how to find a user in the database):
```
let authsome = new Authsome(
config.mode,
{ teams: config.teams }
)
const authsome = new Authsome({mode: yourMode}, {
models: {
User: {
find: id => User.find(id)
}
}
})
```
And then used like so:
This would proxy `models.User.find` to your `User.find`, which is accessible from where you instantiate Authsome, e.g. in [your server](https://gitlab.coko.foundation/pubsweet/pubsweet/blob/master/packages/server/src/helpers/authsome.js#L7) or [your client](https://gitlab.coko.foundation/pubsweet/pubsweet/blob/master/packages/client/src/helpers/withAuthsome.js#L13), and in practice this gives your mode access to your models or similarly important context. An authsome mode that knows about the User model can then do things like this:
```
authsome.can(user, operation, object)
module.exports = {
before: async function (userId, operation, object, context) {
const user = await context.models.User.find(userId)
if (user.admin) {
return true
}
},
someOperation: async function (userId, operation, object, context) {
const user = await context.models.User.find(userId)
if(user.allowedSomeOperation) {
return true
}
}
```
or:
The above gives you a good way to structure your authorization modes, where each property of your mode corresponds to handling of authorization queries for a certain operation. The one exception is the `before` property of a mode, which is evaluated before everything else, and is used to give e.g. admin users the permissions to do everything. The other property of the above example mode is `someOperation`, which corresponds to the `operation` parameter in a `authsome.can(user, operation, object)` query.
```
authsome.can(currentUser, 'update', fragment)
```
However, storing if a user can or can not do `someOperation` on the User model is a bit like the RBAC (role-based authorization system), which often isn't flexible enough - this brings us to a topic that's out of scope for the Authsome module, but is absolutely in-scope for authorization modes that are implemented with Authsome. For example, authorization modes for PubSweet products are based around the concept of object-based Teams, which means that authorization is determined based on team membership. A team consists of a group of members and can be one of the configured team types. A team can be based around an object (the object of the authorization request), or can be a global team (not based around a specific object). An example of a team is, e.g. a team of type `reviewers`, which is based around a `manuscript` object, and when the question of `authsome.can(reviewerUser, 'review', manuscript)` is considered, the mode checks if the `status` property of the `manuscript` is 'in-review', and returns true if it is. For more examples of how teams are used to address authorization requirements, check out the advanced examples below.
The currently configured modes then take over and decide on the authorization, returning true or false.
# Example Modes
# Science Blogger example
Modes are exchangeable mechanisms of authorization (e.g. built in example modes: [blog](https://gitlab.coko.foundation/pubsweet/authsome/blob/master/src/modes/blog/index.js), [journal](https://gitlab.coko.foundation/pubsweet/authsome/blob/master/src/modes/journal/index.js), [specific](https://gitlab.coko.foundation/pubsweet/authsome/blob/master/src/modes/specific/index.js), and [noon](https://gitlab.coko.foundation/pubsweet/authsome/blob/master/src/modes/noon/index.js)).
In [Science Blogger](https://gitlab.coko.foundation/pubsweet/science-blogger), we have two types of teams. One is a 'contributor' type, which allows you to create blogposts for the blog. The other is a 'coauthor' team type, which allows you to update a specific blogpost (write it with someone). There is no conditional activity of teams, and only these two team types.
There are also real world/advanced examples (WIP) for [xpub (PubSweet-based journal publishing platform)](https://gitlab.coko.foundation/xpub/xpub/blob/e52a20537c9ab7447a1d316bb2decd26b14d4bb7/config/authsome.js) and [Editoria (PubSweet-based book production platform)](https://gitlab.coko.foundation/editoria/editoria/blob/editoria-authsome/packages/editoria-authsome/src/index.js).
When your managing teams, you create a new team with a certain type, and a certain object (in the case of Contributors, you would chose the blog object as the object of the team). You can then add members to this team, and those members can then ask (and receive) authorization to create blogposts for the blog.
# PubSweet starter a.k.a. Science Blogger example a.k.a. blog mode
Authsome can be used on both the backend (for authorizing API requests, e.g. [for creating collections in PubSweet](https://gitlab.coko.foundation/pubsweet/core/blob/d6c330b724d6f3ca9a7460a36ec61ebfa8287da5/api/routes/api_collection.js#L23-37)), and frontend (for showing/hiding UI that relates to an authorization request, e.g. a [Create Blogpost button.](https://gitlab.coko.foundation/pubsweet/core/blob/d6c330b724d6f3ca9a7460a36ec61ebfa8287da5/app/components/PostsManager/PostsManager.jsx#L36-38))
In [PubSweet starter](https://gitlab.coko.foundation/pubsweet/pubsweet-starter), we have two types of teams. One is a 'contributor' type, which allows you to create blogposts for the blog. The other is a 'coauthor' team type, which allows you to update a specific blogpost (write it with someone). These are the only two team types.
# Future plans
When you're managing teams, you create a new team with a certain type, and a certain object (in the case of Contributors, you would choose the blog object as the object of the team). You can then add members to this team, and those members can then ask for and receive authorization to create blogposts for the blog.
- [x] Take individual modes and make them into modules, that you can plug and play.
- [ ] Introduce concept of protected attributes/properties. All attributes/properties that could have an effect on the authorization result should be protected from being change with insufficient authorization (and by doing so changing the authorization result.). This is essential and until this is handled this should be considered alpha/prototype stage software.
Authsome can be used on both the server (for authorizing API requests, e.g. [for creating collections in PubSweet](https://gitlab.coko.foundation/pubsweet/pubsweet/blob/master/packages/server/src/routes/util.js#L115)), and client (for showing/hiding UI that relates to an authorization request, e.g. a [Create Blogpost button.](https://gitlab.coko.foundation/pubsweet/pubsweet/blob/master/packages/components/PostsManager/Post.jsx#L111))
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment