Authorization#
Policies#
Mainflux uses policies to control permissions on entities: users, things, and groups. Under the hood, Mainflux uses ORY Keto that is an open-source implementation of "Zanzibar: Google's Consistent, Global Authorization System".
Policies define permissions for the entities. For example, which user has access to a specific thing. Such policies have three main components: subject, object, and relation.
To put it briefly:
Subject: As the name suggests, it is the subject that will have the policy such as users. Mainflux uses entity UUID on behalf of the real entities.
Object: Objects are Mainflux entities (e.g. thing or group) represented by their UUID.
Relation: This is the action that the subject wants to do on the object.
For more conceptual details, you can refer official ORY Keto documentation
All three components create a single policy.
For example, let's assume we have a following policy: "user_id_123" has "read" relation on "thing_id_123"
. This policy means that subject (a user with ID: user_id_123
) has a relation (read
) on the object (a thing with ID: thing_id_123
). Based upon this example, If the user wants to view a Thing
, Mainflux first identifies the user with Authentication Keys and checks the policy as:
User with ID: `user_id_123` has `read` relation on the thing with ID: `thing_id_123`.
If the user has no such policy, the operation will be denied; otherwise, the operation will be allowed. In this case, since the user user_id_123
has the policy, the read
operation on the thing thing_id_123
will be allowed for the user with ID user_id_123
. On the other hand, requests coming from other users (who have a different ID than user_id_123
) will be denied.
In order to check whether a user has the policy or not, Mainflux makes a gRPC call to Keto API, then Keto handles the checking existence of the policy.
All policies are stored in the Keto Database. The database responsible for storing all policies is deployed along with the Mainflux, as a standalone PostgreSQL database container.
Predefined Policies#
Mainflux comes with predefined policies.
Users service related policies#
- By default, Mainflux allows anybody to create a user. If you disable this default policy, only admin is able to create a user.
This default policy can be disabled through an environment variable called
MF_USERS_ALLOW_SELF_REGISTER
in deployment time.MF_USERS_ALLOW_SELF_REGISTER
is a boolean. Therefore, it expects"true"
or"false"
. If you assign"false"
to this environment variable, only admin can create a user. Mainflux creates a special policy to enable this feature as follows:user#create@*
. This policy dictates that subject*
hascreate
relation on the objectusers
. Here, Mainflux uses a special*
subject to represent all users. If this policy is defined, everybody can create new users. - All users are a
member of the users
. To be more precise, once the new user is created, the policy service creates the following policy:users#member@<user_id>
indicating that the subject<user_id
> hasmember
relation on the objectusers
. - The admin has a special policy indicating that the user is admin. This policy is the following:
<admin_id>
hasmember
relation on the objectauthorities
.
Things service related policies#
- There are 3 policies regarding
Things
:read
,write
anddelete
. - When a user creates a thing, the user will have
read
,write
anddelete
policies on theThing
. - In order to view a thing, you need
read
policy on that thing. - In order to update and share the thing, you need a
write
policy on that thing. - In order to remove a thing, you need a
delete
policy on that thing.
Group entity related policies#
- Once the user creates a new group, the user will have a
member
policy on the group. - If you assign a new User member to your group, the new user will have a
member
policy on this particular group. - If you assign a new Thing member to your group, whatever has
member
policy on that group will haveread
,write
anddelete
policies on the Things defined in the Group. - Mainflux allows users to assign access rights of the Things group with the Users group. Thus, each member of the User group can access Things defined in the Thing group. In order to do so, the Policy service adds members of the User group as a
member
of the Thing Group. Therefore, the Users group members haveread
,write
anddelete
policy on the Things defined in the Thing Group.
Summary of the Defined Policies#
member
: Identifies registered user's role such asadmin
. Also, it indicates memberships on the Group entity.read
,write
anddelete
: Controls access control for the Things.create
: Mainflux uses specialcreate
policy to allow everybody to create new users. If you want to enable this feature through the HTTP, you need to make following request:
curl -isSX POST http://localhost/policies -d '{"subjects":["*"],"policies": ["create"], "object": "user"}' -H "Authorization: Bearer <admin_token>" -H 'Content-Type: application/json'
Add Policies#
You can add policies as well through an HTTP endpoint. Only admin can use this endpoint. Therefore, you need an authentication token for the admin.
Caveat: Only policies defined under Summary of the Defined Policies are allowed. Other policies are not allowed. For example, you can add member
policy but not custom-member
policy because custom-member
policy is not defined on the system.
curl -isSX POST http://localhost/policies -d '{"subjects": ["<subject_id1>",..."<subject_idN>"], "object": "<object>", "policies": ["<action_1>, ..."<action_N>"]}' -H "Authorization: Bearer <admin_token>" -H 'Content-Type: application/json'
Delete Policies#
The admin can delete policies. Only policies defined on Predefined Policies section are allowed.
Must-have: admin_token, object, subjects_ids and policies
curl -isSX PUT http://localhost/policies -d '{"subjects": ["<subject_id1>",..."<subject_idN>"], "object": "<object>", "policies": ["<action_1>, ..."<action_N>"]}' -H "Authorization: Bearer <admin_token>" -H 'Content-Type: application/json'
admin_token must belong to the admin.
Response:
HTTP/1.1 204 No Content
Content-Type: application/json
Date: Wed, 03 Nov 2021 13:00:05 GMT
If you delete policies, the policy will be removed from the policy storage. Further authorization checks related to that policy will fail.
For example, let's assume user1
has read
policy on the thing thing-123
. If you delete this policy as:
curl -isSX PUT http://localhost/policies -d '{"subjects": ["<user1_id>"], "object": "thing-123", "policies": ["read"]}' -H "Authorization: Bearer <admin_token>" -H 'Content-Type: application/json'
user1
will not be able to view the thing-123
anymore because the policy which allows user1
to view thing-123
is deleted by the admin.
Example usage of adding a policy#
Suppose we are using the Mainflux version that doesn't have a policies feature yet. Once you migrate a new version of the Mainflux including the Policy feature, your users will face a lack of authorization. For example, there is a user created before the Policy feature. This user is authenticated by <user_token
>. Although the following operation is valid, the user will have an authorization error.
mainflux-cli things create '{"name":"user-thing"}' <user_token>
error: failed to create entity: 403 Forbidden
The reason is that the user has not enough policy to create a new Thing after migration. In order to create a new thing, the user has to have a member
relation on the users
key. So that, Mainflux understands that the requester user is authorized to create new Things.
The easiest solution for this problem is adding policies for the users through the HTTP endpoint. As described above, the user needs a member
relation on the users
.
curl -isSX POST http://localhost/policies -d '{"subjects":["<user_id>"],"policies": ["member"], "object": "users"}' -H "Authorization: Bearer <admin_token> " -H 'Content-Type: application/json'
So what this request does is add new policies for the subject defined in the subjects
field of the request body. Henceforth, the subject (here <user_id>
) will have a member
relation on the object users
. This policy allows the user to create new Things.
Please, keep in mind that this endpoint requires you to use <admin_token>
, not any token. So, the token must belong to the admin.
Example usage of sharing a Thing#
Let's assume, we have two users (called user1
and user2
) registered on the system who have user_id_1
and user_id_2
as their ID respectively.
Let's create a thing with the following command:
mainflux-cli things create '{"name":"user1-thing"}' <user1_token>
created: a1109d52-6281-410e-93ae-38ba7daa9381
This command creates a thing called "user1-thing"
with ID = a1109d52-6281-410e-93ae-38ba7daa9381
. Mainflux identifies the user1
by using the <user1_token>
. After identifying the requester as user1
, the Policy service adds read
, write
and delete
policies to user1
on "user1-thing"
.
If user2
wants to view the "user1-thing"
, the request will be denied.
mainflux-cli things get a1109d52-6281-410e-93ae-38ba7daa9381 <user2_token>
error: failed to fetch entity : 403 Forbidden
After identifying the requester as user2
, the Policy service checks that Is user2 allowed to view the "user1-thing"?
Since user2
has no such policy (read
policy on "user1-thing"
), the Policy service denies this request.
Now, user1
wants to share the "user1-thing"
with user2
. user1
can achieve this via HTTP endpoint for sharing things as follows:
curl -isSX POST http://localhost/things/a1109d52-6281-410e-93ae-38ba7daa9381/share -d '{"user_ids":["<user2_id>]", "policies": ["read", "delete"]}' -H "Authorization: Bearer <user1_token>" -H 'Content-Type: application/json'
HTTP/1.1 200 OK
Server: nginx/1.20.0
Date: Thu, 09 Sep 2021 11:36:10 GMT
Content-Type: application/json
Content-Length: 3
Connection: keep-alive
Access-Control-Expose-Headers: Location
{}
Note: Since sharing a thing requires a
write
policy on the thing,user2
cannot assign a new policy for"user1-thing"
by itself.
Now, user2
has read
and delete
policies on "user1-thing"
which allows user2
to view and delete "user1-thing"
. However, user2
cannot update the "user1-thing"
because user2
has no write
policy on "user1-thing"
.
Let's try again viewing the "user1-thing"
as user2
:
mainflux-cli things get a1109d52-6281-410e-93ae-38ba7daa9381 <user2_token>
{
"id": "a1109d52-6281-410e-93ae-38ba7daa9381",
"key": "6c9c2146-de49-460d-8f0d-adce4ad37500",
"name": "user1-thing"
}
As we expected, the operation is successfully done. The policy server checked that Is user2 allowed to view "user1-thing"?
Since user2
has a read
policy on "user1-thing"
, the Policy server allows this request.
Example usage of Groups#
In this scenario, there will be two users called user1@example.com
and user2@example.com
. user1@example.com
will create one Thing called thing-test
. Then, the Group entity will be utilized to store all of the created entities (user1@example.com
, user2@example.com
, and thing-test
). At the end of this scenario, we will verify that although user2@example.com
has no ownership of thing-test
, user2@example.com
can access the thing-test
because they are in the same group.
Let's start with creating users:
- Create user1@example.com
curl -s -S -i -X POST -H "Content-Type: application/json" http://localhost/users -d '{"email":"user1@example.com", "password":"12345678"}'
- Create
user2@example.com
curl -s -S -i -X POST -H "Content-Type: application/json" http://localhost/users -d '{"email":"user2@example.com", "password":"12345678"}'
Now, let's create a Thing called thing-test
owned by user1@example.com
. Prior to creating it, first, obtain a token for user1@example.com
as follows:
curl -s -S -i -X POST -H "Content-Type: application/json" http://localhost/tokens -d '{"email":"user1@example.com", "password":"12345678"}'
It is convenient to store the generated token because the token will be required in further steps repeatedly.
export USER1TOKEN=<USER1TOKEN>
And create a Thing called thing-test
curl -s -S -i -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $USER1TOKEN" http://localhost/things -d '[{"name": "thing-test"}]'
Note: We will need the ID of newly created Thing in further steps. Again, it is better to store it.
If user2@example.com
tries to view thing-test
, the operation will be denied by policy service because user2@example.com
has no policies related to reading thing-test
.
curl -s -S -i -X GET -H "Authorization: Bearer $USER2TOKEN" http://localhost/things/<thing_id>
HTTP/1.1 403 Forbidden
Server: nginx/1.20.0
Date: Fri, 05 Nov 2021 06:03:42 GMT
Content-Type: application/json
Content-Length: 60
Connection: keep-alive
{"error":"failed to perform authorization over the entity"}
It is time to create a new Group and put all entities into that Group. Mainflux provides HTTP API for Groups like other entities. We will utilize this HTTP API for Group operations. For more details about Groups, please see Groups documentation.
curl -s -S -i -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $USER1TOKEN" http://localhost/groups -d '{"name": "my_group"}'
HTTP/1.1 201 Created
Server: nginx/1.20.0
Date: Fri, 05 Nov 2021 06:10:32 GMT
Content-Type: application/json
Content-Length: 0
Connection: keep-alive
Location: /groups/01FKQBGQEP71DG9C99J37YBJD7
Access-Control-Expose-Headers: Location
The POST /groups
API creates a new group. In our case, it creates a group called my_group
. Since user1@example.com
's token is used, the policy service creates a policy to indicate that user1@example.com
is member of my_group.
In the Location response header, you can see the ID of the my_group
. For the response above, the location is Location: /groups/01FKQBGQEP71DG9C99J37YBJD7
. Therefore, the group ID of my_group
is 01FKQBGQEP71DG9C99J37YBJD7
. We will need this ID while assigning new members to my_group
.
The group my_group
includes just a member that is user1@example.com
, yet. In order to add new members, we will use POST /groups/<group_id>/members
. While assigning entities, you will need the ID of the entities respectively. Let's start with assigning thing-test
to my_group
.
curl -s -S -i -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $USER1TOKEN" http://localhost/groups/<group_id>/members -d '{"members":["<thing_id>"], "type":"things"}'
The crucial point here is that since we are assigning a Thing to the Group, the "type"
field of the request body must be things
.
Now, assign user2@example.com
to my_group
.
curl -s -S -i -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $USER1TOKEN" http://localhost/groups/$g/members -d '{"members": "c0fb3fdb-ecfa-407a-bd11-93884d70baf7"], "type":"users"}'
Again, please be careful about the "type"
field of the request body. Since we are assigning the user, the type is users
.
Under the hood, the Policy service creates
member
policies for each entity respectively. Also, each user member will have access to Things defined in the Group. That's why the type field is crucial.
Okay, let's check whether user2@example.com
is capable to view the my-thing
. Previously, the Policy service denied that request from user2@example.com
. Try again:
curl -s -S -i -X GET -H "Authorization: Bearer $USER2TOKEN" http://localhost/things/<thing_id>
HTTP/1.1 200 OK
Server: nginx/1.20.0
Date: Fri, 05 Nov 2021 06:36:03 GMT
Content-Type: application/json
Content-Length: 111
Connection: keep-alive
Access-Control-Expose-Headers: Location
{"id":"7d551538-834d-4398-bd4d-38940dd4bfa9","name":"thing-test","key":"4305f78d-399b-4cc4-ad42-3fd5bac09715"}
Successful as we expected. Since user2@example.com
and my-thing
reside in the same group, user2@example.com
can access the my-thing
through Group policies.
If you unassign user2@example.com, the user cannot access my-thing
. In order to test it, you can unassign the user2@example.com
as follows:
curl -s -S -i -X DELETE -H "Content-Type: application/json" -H "Authorization: Bearer $USER1TOKEN" http://localhost/groups/$g/members -d '{"members": "c0fb3fdb-ecfa-407a-bd11-93884d70baf7"], "type":"users"}'
Since user2@example.com
is not a member of the my_group anymore, the Policy service denies incoming request related to viewing the my-thing
from user2@example.com
.
curl -s -S -i -X GET -H "Authorization: Bearer $USER2TOKEN" http://localhost/things/$th
HTTP/1.1 403 Forbidden
Server: nginx/1.20.0
Date: Fri, 05 Nov 2021 06:39:47 GMT
Content-Type: application/json
Content-Length: 60
Connection: keep-alive
{"error":"failed to perform authorization over the entity"}
Example usage of sharing entities via Group#
Mainflux allows you to group entities (e.g., Users
and Things
) through Group
object in auth
service. You can find more details about usage of the Group
at Groups documentation.
In this example, we will demonstrate how you can share access of the Users group to the Things group. So, each member of the Users group will have access to each Thing assigned to the Things group. We are going to start from a clean Mainflux setup and follow these steps:
- Create a new user and multiple Things,
- Create a Thing and User group, and assign members to groups,
- Share access of the groups
First of all, obtain a token for the default admin. You can use any user but for the simplicity of the document, the default admin will be used.
By default, Mainflux uses credentials described in .env for the default admin.
$ curl -s -S -i -X POST -H "Content-Type: application/json" http://localhost/tokens -d '{"email":"admin@example.com",
"password":"12345678"}'
HTTP/1.1 201 Created
Server: nginx/1.20.0
Date: Wed, 13 Oct 2021 08:26:45 GMT
Content-Type: application/json
Content-Length: 285
Connection: keep-alive
Strict-Transport-Security: max-age=63072000; includeSubdomains
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: *
Access-Control-Allow-Headers: *
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MzQxNDk2MDUsImlhdCI6MTYzNDExMzYwNSwiaXNzIjoibWFpbmZsdXguYXV0aCIsInN1YiI6ImFkbWluQGV4YW1wbGUuY29tIiwiaXNzdWVyX2lkIjoiOTA3MjkzMDMtZDMwZC00YmQ5LTkwMTYtNDljMThjZmY4YjUxIiwidHlwZSI6MH0.G1kjXiGX76BqpytmLdXtjLF9s9K5CVm4ScNMIaKlkwE"}
You can store the generated token because we will need it in further steps.
$ export token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MzQxNDk2MDUsImlhdCI6MTYzNDExMzYwNSwiaXNzIjoibWFpbmZsdXguYXV0aCIsInN1YiI6ImFkbWluQGV4YW1wbGUuY29tIiwiaXNzdWVyX2lkIjoiOTA3MjkzMDMtZDMwZC00YmQ5LTkwMTYtNDljMThjZmY4YjUxIiwidHlwZSI6MH0.G1kjXiGX76BqpytmLdXtjLF9s9K5CVm4ScNMIaKlkwE
Now, we can create a new user as follows:
curl -s -S -i -X POST -H "Content-Type: application/json" http://localhost/users -d '{"email":"user@example.com", "password":"12345678"}'
HTTP/1.1 201 Created
Server: nginx/1.20.0
Date: Wed, 13 Oct 2021 08:45:57 GMT
Content-Type: application/json
Content-Length: 0
Connection: keep-alive
Location: /users/f31f8a0a-11b1-4aa6-a4a3-9629378c0326
Strict-Transport-Security: max-age=63072000; includeSubdomains
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: *
Access-Control-Allow-Headers: *
You can obtain the user ID via Location
. The ID of the user@example.com
is f31f8a0a-11b1-4aa6-a4a3-9629378c0326
.
After creating the new user, we have two users on the system as admin@example.com
and user@example.com
.
Then, the admin creates multiple Things called admin-thing-1
and admin-thing-2
.
curl -s -S -i -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" http://localhost/things -d '[{"name": "a
dmin-thing-1"}, {"name": "admin-thing-2"}]'
HTTP/1.1 201 Created
Server: nginx/1.20.0
Date: Wed, 13 Oct 2021 08:53:38 GMT
Content-Type: application/json
Content-Length: 241
Connection: keep-alive
Access-Control-Expose-Headers: Location
{"things":[{"id":"c3d75452-ae00-4aea-84f9-29ab79fd0d26","name":"admin-thing-1","key":"4fb36389-f7a5-424d-8c4f-da5c9e91f3c5"},{"id":"ee589c61-0b98-4176-9da0-d91913087be6","name":"admin-thing-2","key":"410f5889-c756-470d-bd65-2e99b4ecc679"}]}
export th1=c3d75452-ae00-4aea-84f9-29ab79fd0d26
export th2=ee589c61-0b98-4176-9da0-d91913087be6
Mainflux identifies admin@example.com
via the token provided through the Authorization
request header. On top of that, Mainflux claims ownership of things (admin-thing-1
and admin-thing-2
) on the admin@example.com
. So that, the creator of Things (in this case admin@example.com
) is going to have read
, write
and delete
policies on the Thing.
If user@example.com
logs in the system, user@example.com
cannot access the things created by the admin@example.com
due to lack of policies.
The next step is creating the user and things Groups respectively. You can create groups as follows:
curl -s -S -i -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" http://localhost/groups -d '{"name": "user_group"}'
HTTP/1.1 201 Created
Server: nginx/1.20.0
Date: Wed, 13 Oct 2021 09:24:39 GMT
Content-Type: application/json
Content-Length: 0
Connection: keep-alive
Location: /groups/01FHWFFMME9N2N26DG0DMNRWRW
Access-Control-Expose-Headers: Location
curl -s -S -i -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" http://localhost/groups -d '{"name": "thing_group"}'
HTTP/1.1 201 Created
Server: nginx/1.20.0
Date: Wed, 13 Oct 2021 09:24:58 GMT
Content-Type: application/json
Content-Length: 0
Connection: keep-alive
Location: /groups/01FHWFG78DSYA458D8ST4YQ9Y9
Access-Control-Expose-Headers: Location
Again, you can obtain group IDs via Location
in response. It is convenient to store them in variables.
export ug=01FHWFFMME9N2N26DG0DMNRWRW
export tg=01FHWFG78DSYA458D8ST4YQ9Y9
After creating groups, we are ready to assign new members to groups. Let's start with the user group.
curl -s -S -i -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" http://localhost/groups/$ug/members -d '{"members":["f31f8a0a-11b1-4aa6-a4a3-9629378c0326"], "type":"users"}'
HTTP/1.1 200 OK
Server: nginx/1.20.0
Date: Wed, 13 Oct 2021 09:37:05 GMT
Content-Type: application/json
Content-Length: 0
Connection: keep-alive
Access-Control-Expose-Headers: Location
If you remember, f31f8a0a-11b1-4aa6-a4a3-9629378c0326
is the ID of the user@example.com
. Since the $ug
represents the ID of the user group called user_group
, we indicated the type of the group as "users"
in the request body.
Now, we can assign Things to the thing group.
curl -s -S -i -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" http://localhost/groups/$tg/members -d '{"members":["c3d75452-ae00-4aea-84f9-29ab79fd0d26", "ee589c61-0b98-4176-9da0-d91913087be6"], "type":"things"}'
HTTP/1.1 200 OK
Server: nginx/1.20.0
Date: Wed, 13 Oct 2021 09:42:12 GMT
Content-Type: application/json
Content-Length: 0
Connection: keep-alive
Access-Control-Expose-Headers: Location
The same logic applies here as well. The IDs of the things that admin@example.com
created are c3d75452-ae00-4aea-84f9-29ab79fd0d26
and ee589c61-0b98-4176-9da0-d91913087be6
. Since the $tg
represents the ID of the thing group called thing_group
, we indicated the type of the group as "things"
in the request body.
Before moving to the third step, let's analyze the current situation. We have two groups, two users, and two things. The first group is the user group and consists of two users, admin@example.com
(since the admin created the group) and user@example.com
. The second group is the thing group. It includes two things created by admin@example.com
. user@example.com
still has no access to things created by admin@example.com
. You can verify it as:
curl -s -S -i -X GET -H "Authorization: Bearer $TOKEN" http://localhost/things/$th1
HTTP/1.1 403 Forbidden
Server: nginx/1.20.0
Date: Wed, 13 Oct 2021 09:51:45 GMT
Content-Type: application/json
Content-Length: 60
Connection: keep-alive
{"error":"failed to perform authorization over the entity"}
curl -s -S -i -X GET -H "Authorization: Bearer $TOKEN" http://localhost/things/$th2
HTTP/1.1 403 Forbidden
Server: nginx/1.20.0
Date: Wed, 13 Oct 2021 09:51:49 GMT
Content-Type: application/json
Content-Length: 60
Connection: keep-alive
{"error":"failed to perform authorization over the entity"}
The $TOKEN
is the token for user@example.com
. As you can see, requests to access things are denied.
Now, let's assign group access rights.
curl -s -S -i -X POST http://localhost/groups/$ug/share -d '{"thing_group_id": "01FHWFG78DSYA458D8ST4YQ9Y9"}' -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN"
HTTP/1.1 200 OK
Server: nginx/1.20.0
Date: Wed, 13 Oct 2021 09:59:13 GMT
Content-Type: application/json
Content-Length: 3
Connection: keep-alive
Access-Control-Expose-Headers: Location
Now, all the members of the user_group
have access to things within the thing_group
. Therefore, user@example.com
has read
, write
and delete
policies on the things within the thing_group.
Try to access things as user@example.com
.
curl -s -S -i -X GET -H "Authorization: Bearer $TOKEN" http://localhost/things/$th1
HTTP/1.1 200 OK
Server: nginx/1.20.0
Date: Wed, 13 Oct 2021 10:02:19 GMT
Content-Type: application/json
Content-Length: 114
Connection: keep-alive
Access-Control-Expose-Headers: Location
{"id":"c3d75452-ae00-4aea-84f9-29ab79fd0d26","name":"admin-thing-1","key":"4fb36389-f7a5-424d-8c4f-da5c9e91f3c5"}
curl -s -S -i -X GET -H "Authorization: Bearer $TOKEN" http://localhost/things/$th2
HTTP/1.1 200 OK
Server: nginx/1.20.0
Date: Wed, 13 Oct 2021 10:02:21 GMT
Content-Type: application/json
Content-Length: 114
Connection: keep-alive
Access-Control-Expose-Headers: Location
{"id":"ee589c61-0b98-4176-9da0-d91913087be6","name":"admin-thing-2","key":"410f5889-c756-470d-bd65-2e99b4ecc679"}
Successful!
Let's assume, admin@example.com
does not want to share things with user@example.com
anymore. In order to achieve that, admin@example.com
unassigns user@example.com
from the user_group
.
curl -s -S -i -X DELETE -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" http://localhost/groups/$ug/members -d '{"members":["f31f8a0a-11b1-4aa6-a4a3-9629378c0326"], "type":"users"}'
HTTP/1.1 204 No Content
Server: nginx/1.20.0
Date: Wed, 13 Oct 2021 10:08:56 GMT
Content-Type: application/json
Connection: keep-alive
Access-Control-Expose-Headers: Location
Now, when user@example.com
tries to access the things, the request will be denied.
curl -s -S -i -X GET -H "Authorization: Bearer $TOKEN" http://localhost/things/$th1
HTTP/1.1 403 Forbidden
Server: nginx/1.20.0
Date: Wed, 13 Oct 2021 10:10:26 GMT
Content-Type: application/json
Content-Length: 60
Connection: keep-alive
{"error":"failed to perform authorization over the entity"}
curl -s -S -i -X GET -H "Authorization: Bearer $TOKEN" http://localhost/things/$th2
HTTP/1.1 403 Forbidden
Server: nginx/1.20.0
Date: Wed, 13 Oct 2021 10:10:28 GMT
Content-Type: application/json
Content-Length: 60
Connection: keep-alive
{"error":"failed to perform authorization over the entity"}