loopback bug acl not working? - loopbackjs

i m try to implement acl for model(named as company)
"relations": {
"user": {
"type": "belongsTo",
"model": "user",
"foreignKey": "company_id"
}
},
"acls": [
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
},
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW"
}
],
deny all user and access only to authenticated user owner of that object . here i m also try to add permission for super user who have all permission in short admin and owner of objec(data) can do crud is there any soultion for this please help

You can deny all unauthenticated users then deny everyone and allow only the owner like below :
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$unauthenticated",
"permission": "DENY"
},
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
},
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW"
}
you need only CRUD for the $owner, you can assign the properties needed for your user as below :
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW",
"property": [
"find",
"create",
"updateAll",
"delete"
]
}
For the super user you should create this Role and assign it to one of your users.
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "superuser",
"permission": "ALLOW"
}
How to create a ROLE ? you can follow the documentation here.
And make sure that you have this file /server/boot/autentication.jsand authetication is enabled : server.enableAuth()
'use strict';
module.exports = function enableAuthentication(server) {
// enable authentication
server.enableAuth();
};
For more ACL tricks please read the official documentation here.

Related

Ownership of an in direct model

I have a user which own a house (several of users can own the house), the house can have several of furnitures.
CustomUser.json relation:
"houses": {
"type": "hasAndBelongsToMany",
"model": "House",
"foreignKey": "houseId"
}
House.json relations:
"furnitures": {
"type": "hasAndBelongsToMany",
"model": "Furniture",
"foreignKey": ""
},
"customUsers": {
"type": "hasAndBelongsToMany",
"model": "CustomUser",
"foreignKey": ""
}
My ACL is simple and looks like this for both House and Furniture:
"acls": [
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
},
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "admin",
"permission": "ALLOW"
},
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW"
}
]
Now, accessing houses for the users works fine, but the users won't get their furnitures listed since they belong to a house (the house is the owner). How do I fix this the easiest way possible? Best would be to somehow define that User owns furnitures through the house? The furnitures must belong to the house, though (since multiple users can have a house).
So I got past this through another module called "loopback-component-access-groups" which lets you define groups. In this particular case I made the House-model a group which the users and furnitures have access to. A user can have different roles so I just set that the user (which have the role "member") can access the furnitures which are in the same group (house). This solution works for me, but I am not entirely sure if further objects inherits that they belong to a house if they are related to a furniture.
Writing my own role resolver made this quite flexible, in the role resolver I had to make logic to find the original parent and also make sure there were no dead relationships (since LB doesn't have support for cascade yet).
I recommend starting with this to get going:
https://loopback.io/doc/en/lb3/Defining-and-using-roles.html

Denying permissions issue in loopback

I've created a model Webuser based on the built in User model.
This is this model's ACL entry in "webuser.json":
"acls": [
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
}
]
To my surprise, I can login via POST /api/webusers/login with no problems. I expected all access to be denied.
What am I doing wrong?
Well I believe the default user acls are still working and they are not overrided. The way loopback decides which ACL entry is effective for the request, is by selecting most specific one that appears later. So loopback has defined this entry:
{
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW",
"property": "login"
}
Since it's as specific as it gets, to beat that you have to add this in your model:
{
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY",
"property": "login"
}
There's also another way to remove the default user acls via code but it's not documented.

Constantly getting 401 errors in loopback while using User Model

I am new to loopback and I am not able to extend User Base model properly. Though in explorer it shows that it is extended but all API's give a 401 error. ex. In normal get call for /users I get..
{
"error": {
"name": "Error",
"status": 401,
"message": "Authorization Required",
"statusCode": 401,
"code": "AUTHORIZATION_REQUIRED",
"stack": "Error: Authorization Required"
}
}
I went thru all the links and questions but none of they are working for me. I have properly put public:true in model-config for User Model extended model and written acls etc. but none of them works. I have also raised an issue on git for strongloop: https://github.com/strongloop/loopback/issues/1809 . Any leads would be awesome. Thanks.
User.json is as below:
{
"name": "user",
"plural": "users",
"base": "User",
"idInjection": true,
"options": {
"validateUpsert": true
},
"mongodb": {
"collection": "User"
},
"properties": {
"name": {
"type": "string",
"required": true
},
"email": {
"type": "string",
"required": true
},
"password": {
"type": "string",
"required": true
},
"phone": {
"type": "string"
}
},
"validations": [],
"relations": {
"question": {
"type": "hasMany",
"model": "question",
"foreignKey": ""
}
},
"acls": [
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
},
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "admin",
"permission": "ALLOW"
},
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW"
},
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
],
"methods": {}
}
Some notes meriting consideration though:
1)You are defining email, password,.. properties, although they are already defined exactly the same way in the parent User model; please see: https://github.com/strongloop/loopback/blob/master/common/models/user.json;
2)For ACLs you are missing accesstypes, they are not right, but they do not break anything...For more info about ACL please see: https://docs.strongloop.com/display/public/LB/Define+access+controls
3)Also when you login please make sure to use user that you have created(a POST request) and it is in database already.
Thanks!
Seems like you've not logged into the application.
Anyway by default most of the functions are not accessible by the settings in user parent class. (This totally is a turn-off)
run the code in the login section
{
"username":"abc",
"password":"xyz"
}
This action will return the token id.
Enter this id in the top most right corner of the page and click the set token button.
Now you're able to use some of the user function.
Create a model inheriting user
:~/nodejs/lab/user-api$ slc loopback:model
? Enter the model name: customer
? Select the data-source to attach customer to: db (memory)
? Select model's base class: User
? Expose customer via the REST API? Yes
? Custom plural form (used to build REST URL): customers
Let's add some customer properties now.
Enter an empty property name when done.
? Property name: phone
invoke loopback:property
? Property type: string
? Required? No
Let's add another customer property.
Enter an empty property name when done.
? Property name:
Granting ACL Access:
slc loopback:acl
? Select the model to apply the ACL entry to: customer
? Select the ACL scope: All methods and properties
? Select the access type: All (match all types)
? Select the role: All users
? Select the permission to apply: Explicitly grant access
Granting ACL Access once again:
slc loopback:acl
? Select the model to apply the ACL entry to: customer
? Select the ACL scope: All methods and properties
? Select the access type: All (match all types)
? Select the role: All users
? Select the permission to apply: Explicitly grant access
When we're granting access two times it takes precedence over DENY in the base class. You'll get a result next time.
A sample class with the ACLs. You can try it in a loopback project, it'll work :)
{
"name": "customer",
"plural": "customers",
"base": "User",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"phone": {
"type": "string"
}
},
"validations": [],
"relations": {},
"acls": [
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
},
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
],
"methods": []
}
Please accept answer if it works. It will. Cheers!

Cannot access S3 bucket from Lambda function

I created a simple Lambda function that receives a file as a Base64 string and uploads it to my S3 bucket. I used the default S3 role suggested by the Lambda console:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}
But I'm still getting an access error:
{
"errorMessage": "The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.",
"errorType": "PermanentRedirect",
"stackTrace": [
Doesn't the "arn:aws:s3:::*" cover all my needs? What else do I need to add to use this function?
The must be addressed using the specified endpoint error normally indicates a mismatch between the bucket region and the endpoint that you are calling with your code.
For example: The AWS client connection is established with Sydney but the bucket is in Tokyo.
Try something like this:
var s3 = new AWS.S3({region: 'ap-southeast-2'});
It might also happens to your sourceKey settings, try to add the exact file path in your S3 like:
{
"Records": [
{
"eventVersion": "2.0",
"eventTime": "1970-01-01T00:00:00.000Z",
"requestParameters": {
"sourceIPAddress": "127.0.0.1"
},
"s3": {
"configurationId": "testConfigRule",
"object": {
"eTag": "0123456789abcdef0123456789abcdef",
"sequencer": "0A1B2C3D4E5F678901",
"key": "images/HappyFace.jpg",
"size": 1024
},
"bucket": {
"arn": "arn:aws:s3:::mybucket",
"name": "mybucket",
"ownerIdentity": {
"principalId": "EXAMPLE"
}
},
"s3SchemaVersion": "1.0"
},
"responseElements": {
"x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH",
"x-amz-request-id": "EXAMPLE123456789"
},
"awsRegion": "us-east-1",
"eventName": "ObjectCreated:Put",
"userIdentity": {
"principalId": "EXAMPLE"
},
"eventSource": "aws:s3"
}
]
}

Strongloop/loopback: how to disable authentication for User model over REST?

I have typed in at the commandline: slc loopback:acl
and disabled all security for the User model.
Going into strongloop explorer, doing a simple GET Users request gives me a 401 authorization required error.
Any ideas how to open up the User object? Is this a known bug?
Thank you
You can extend your user model and set permissions for your custom model like this:
{
"name": "CustomUser",
"base": "User",
"idInjection": true,
"properties": {},
"validations": [],
"relations": {},
"acls": [
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$unauthenticated",
"permission": "ALLOW"
},
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW"
},
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW"
}
],
"methods": []
}
However I would NEVER recommend you doing this.
If you really want to disable the endpoints on the User model, you can do this.
Go to your model.config.json and add "public": false to the User field like so:
...
"User": {
"public": false,
"dataSource": "db"
},
...