I've recently migrated an application to LoopBack 2.0.
All my models require user authentication and have these ACLs:
"acls": [
{
"accessType": "*",
"permission": "DENY",
"principalType": "ROLE",
"principalId": "$everyone"
},
{
"accessType": "READ",
"permission": "ALLOW",
"principalType": "ROLE",
"principalId": "$authenticated"
}
]
I have a model called issues. After logging in through the POST method /Users/login:
/issues. I get a list of issues as expected;/issues/{id}/categories), I get the error 401 Authorization required. The same model used to work in Loopback 1.0.Any clues?
I have the same issue. I also think the 401 Unauthorized is a wrong response. I am authenticated, so it should be 403 forbidden. I'm opening a new issue for that.
I think this has already been implemented: https://github.com/strongloop/loopback/issues/301
This issue (#426) itself is not yet resolved. Defining an ACL on a relation property does not seem to work for me.
Replicate by defining a model, adding a relationship to it (for example many user to many group). Then DENY ALL on * for ROLE $everyone, and finally ALLOW READ/EXECUTE on
I am having the exact same issue! I spent a few hours digging through anything I can find, but I still couldnt get it to work!
@dagumak - can you post the ACL's you defined?
@fabien I posted it here (https://github.com/strongloop/loopback/issues/459#issuecomment-52635774), but here it is:
{
"name": "TestUser",
"base": "User",
"strict": true,
"properties": {
"username": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {
"message": {
"type": "hasMany",
"model": "Message",
"foreignKey": "userId"
}
},
"acls": [
],
"methods": []
}
{
"name": "Message",
"base": "PersistedModel",
"properties": {
"type": {
"type": "string",
"required": true
},
"text": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {
"testUser": {
"type": "belongsTo",
"model": "TestUser",
"foreignKey": "userId"
}
},
"acls": [
{
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
],
"methods": []
}
I think the core User ACL's are interfering with the ACL's you defined. I recall the following from one of my projects, which overrides all the ACL's:
TestUser.settings.acls = [
{ principalType: 'ROLE',
principalId: '$everyone',
permission: 'DENY' },
{ principalType: 'ROLE', // this is the important bit
principalId: '$owner',
permission: 'ALLOW' },
{ principalType: 'ROLE',
principalId: '$everyone',
permission: 'ALLOW',
property: 'create' },
{ principalType: 'ROLE',
principalId: '$owner',
permission: 'ALLOW',
property: 'deleteById' },
{ principalType: 'ROLE',
principalId: '$everyone',
permission: 'ALLOW',
property: 'login' },
{ principalType: 'ROLE',
principalId: '$everyone',
permission: 'ALLOW',
property: 'logout' },
{ principalType: 'ROLE',
principalId: '$owner',
permission: 'ALLOW',
property: 'findById' },
{ principalType: 'ROLE',
principalId: '$owner',
permission: 'ALLOW',
property: 'updateAttributes' },
{ principalType: 'ROLE',
principalId: '$everyone',
permission: 'ALLOW',
property: 'confirm' }
]
@dagumak the very least you could do is trace your current TestUser.settings.acls to compare them.
@Fabien I feel silly for asking, but other than console log, how can I do that?
On Tue, Aug 19, 2014 at 11:32 PM, Fabien Franzen [email protected]
wrote:
@dagumak the very least you could do is trace your current TestUser.settings.acls to compare them.
Reply to this email directly or view it on GitHub:
https://github.com/strongloop/loopback/issues/426#issuecomment-52642645
@dagumak console.log is fine
@fabien I am not very familiar with the framework yet, but where are the models loaded and a good place for me to console.log it?
You can put the following into a file at /server/boot/debug.js:
module.exports = function(app) {
var TestUser = app.loopback.getModel('TestUser');
console.log(TestUser.settings.acls);
};
You can run the application with DEBUG enabled:
$ DEBUG=loopback:security:* node .
Thanks,
Raymond Feng
Co-Founder and Architect @ StrongLoop, Inc.
StrongLoop makes it easy to develop APIs in Node, plus get DevOps capabilities like monitoring, debugging and clustering.
On Aug 19, 2014, at 8:29 AM, Fabien Franzen [email protected] wrote:
You can put the following into a file at /server/boot/debug.js:
module.exports = function(app) {
var TestUser = app.loopback.getModel('TestUser');
console.log(TestUser.settings.acls);
};
—
Reply to this email directly or view it on GitHub.
@fabien Thanks a bunch! Here it is:
[ { principalType: 'ROLE',
principalId: '$everyone',
permission: 'DENY' },
{ principalType: 'ROLE',
principalId: '$everyone',
permission: 'ALLOW',
property: 'create' },
{ principalType: 'ROLE',
principalId: '$owner',
permission: 'ALLOW',
property: 'deleteById' },
{ principalType: 'ROLE',
principalId: '$everyone',
permission: 'ALLOW',
property: 'login' },
{ principalType: 'ROLE',
principalId: '$everyone',
permission: 'ALLOW',
property: 'logout' },
{ principalType: 'ROLE',
principalId: '$owner',
permission: 'ALLOW',
property: 'findById' },
{ principalType: 'ROLE',
principalId: '$owner',
permission: 'ALLOW',
property: 'updateAttributes' },
{ principalType: 'ROLE',
principalId: '$everyone',
permission: 'ALLOW',
property: 'confirm' } ]
Is this resolved ? I am still having the same issue
The last thread doesn't help
[ { principalType: 'ROLE',
principalId: '$everyone',
permission: 'DENY' },
{ principalType: 'ROLE',
principalId: '$everyone',
permission: 'ALLOW',
property: 'create' },
{ principalType: 'ROLE',
principalId: '$owner',
permission: 'ALLOW',
property: 'deleteById' },
{ principalType: 'ROLE',
principalId: '$everyone',
permission: 'ALLOW',
property: 'login' },
{ principalType: 'ROLE',
principalId: '$everyone',
permission: 'ALLOW',
property: 'logout' },
{ principalType: 'ROLE',
principalId: '$owner',
permission: 'ALLOW',
property: 'findById' },
{ principalType: 'ROLE',
principalId: '$owner',
permission: 'ALLOW',
property: 'updateAttributes' },
{ principalType: 'ROLE',
principalId: '$everyone',
permission: 'ALLOW',
property: 'confirm' },
{ principalType: 'ROLE',
principalId: '$everyone',
permission: 'ALLOW',
property: 'resetPassword',
accessType: 'EXECUTE' },
{ accessType: '*',
principalType: 'ROLE',
principalId: '$everyone',
permission: 'ALLOW' } ]
Something that helped me with ACL and relations is to run "DEBUG=loopback:security:* slc run" and then check the property it is trying to access.
At first I tried adding ACL to the "orders" property (since it was like /users/2/orders) but it seems like the ACL resolver tried to access this property: __get__orders.
I set that in my json acl file and it is working like a charm.
Example:
"acls": [
{
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW",
"property": "__get__orders"
}
Please create a test project on Github to reproduce the issue as per https://github.com/strongloop/loopback/wiki/Issues#bug-report
@rubentorresbonet the acl that you defined with the property __get__orders is for which model?
Is it for the user model or for the orders model?
@LetsDoIt- Have a look here: http://docs.strongloop.com/display/public/LB/Restricting+access+to+related+models
@rubentorresbonet Holy cow, that worked! I had to use the property __get__customer for a relationship named customer. Thanks!
DEBUG=loopback:security:* slc run really helped me understand what was happening with the ACLs.
This was on a subclassed user model. The full thing looks like this now:
{
"name": "user",
"base": "User",
"idInjection": true,
"properties": {},
"validations": [],
"relations": {
"customer": {
"type": "hasOne",
"model": "Customer"
}
},
"acls": [
{
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW",
"property": "__get__customer"
}
],
"methods": []
}
This can't possibly be the intended design.
Agree with @jdhiro that from a design perspective, this is very uncomfortable. Would it not be better to introduce a single declaration in order to to set R/W/X privileges on a single relation, just as we can do for other built-in methods?
By the way, the link to the documentation for accessing related models provided above is broken, the correct one is here:
https://docs.strongloop.com/display/public/LB/Accessing+related+models
I spent a few hours on this too. Doc is not clear. It should clearly mention that default is denied
@crandmck ^
While trying CoffeeShop example given at https://docs.strongloop.com/display/LB/Getting+started+part+II I'm getting 401 only while editing the review. I've the ACLs defined as given @ https://docs.strongloop.com/display/public/LB/Define+access+controls
So the following ACL entry is failing:
{
"accessType": "WRITE",
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW"
}
If I change $owner to $authenticated, then I don't get 401. So there seems to be some problem in isOwner().
I've tried using DEBUG=loopback:security:* and it gives following output
loopback:security:access-context ---AccessContext--- +1ms
loopback:security:access-context principals: +3ms
loopback:security:access-context principal: {"type":"USER","id":"562a105037cfea381ac14fbb"} +2ms
loopback:security:access-context modelName Review +3ms
loopback:security:access-context modelId 562a105037cfea381ac14fbe +1ms
loopback:security:access-context property upsert +1ms
loopback:security:access-context method upsert +2ms
loopback:security:access-context accessType WRITE +1ms
loopback:security:access-context accessToken: +2ms
loopback:security:access-context id "EoEwOGWIWLNfw4DLgxf9ga2zCoFht974DgCccMFkQLmLrmnQJ64eHJidDIf4e8dh" +1ms
loopback:security:access-context ttl 1209600 +3ms
loopback:security:access-context getUserId() 562a105037cfea381ac14fbb +2ms
loopback:security:access-context isAuthenticated() true +3ms
loopback:security:role Custom resolver found for role $everyone +0ms
loopback:security:role isInRole(): $everyone +2ms
loopback:security:access-context ---AccessContext--- +1ms
loopback:security:access-context principals: +1ms
loopback:security:access-context principal: {"type":"USER","id":"562a105037cfea381ac14fbb"} +1ms
loopback:security:access-context modelName Review +2ms
loopback:security:access-context modelId 562a105037cfea381ac14fbe +1ms
loopback:security:access-context property upsert +1ms
loopback:security:access-context method upsert +3ms
loopback:security:access-context accessType WRITE +1ms
loopback:security:access-context accessToken: +1ms
loopback:security:access-context id "EoEwOGWIWLNfw4DLgxf9ga2zCoFht974DgCccMFkQLmLrmnQJ64eHJidDIf4e8dh" +2ms
loopback:security:access-context ttl 1209600 +2ms
loopback:security:access-context getUserId() 562a105037cfea381ac14fbb +2ms
loopback:security:access-context isAuthenticated() true +1ms
loopback:security:role Custom resolver found for role $everyone +1ms
loopback:security:role isInRole(): $owner +2ms
loopback:security:access-context ---AccessContext--- +1ms
loopback:security:access-context principals: +2ms
loopback:security:access-context principal: {"type":"USER","id":"562a105037cfea381ac14fbb"} +2ms
loopback:security:access-context modelName Review +2ms
loopback:security:access-context modelId 562a105037cfea381ac14fbe +2ms
loopback:security:access-context property upsert +1ms
loopback:security:access-context method upsert +1ms
loopback:security:access-context accessType WRITE +2ms
loopback:security:access-context accessToken: +1ms
loopback:security:access-context id "EoEwOGWIWLNfw4DLgxf9ga2zCoFht974DgCccMFkQLmLrmnQJ64eHJidDIf4e8dh" +2ms
loopback:security:access-context ttl 1209600 +2ms
loopback:security:access-context getUserId() 562a105037cfea381ac14fbb +1ms
loopback:security:access-context isAuthenticated() true +2ms
loopback:security:role Custom resolver found for role $owner +2ms
loopback:security:role isOwner(): Review 562a105037cfea381ac14fbe userId: 562a105037cfea381ac14fbb +2ms
loopback:security:role Model found: {"date":"2015-10-19T10:47:44.791Z","rating":5,"comments":"A very good coffee shop.","id":"562a105037cfea381ac14fbe","coffeeShopId":"562a105037cfea381ac14fb8","publisherId":"562a105037cfea381ac14fbb"} +5ms
loopback:security:role Checking relation reviewer to Reviewer: {"name":"reviewer","type":"belongsTo","modelFrom":"Review","keyFrom":"pulisherId","modelTo":"Reviewer","keyTo":"id","multiple":false} +4ms
loopback:security:acl The following ACLs were searched: +4ms
loopback:security:acl ---ACL--- +1ms
loopback:security:acl model Review +2ms
loopback:security:acl property * +1ms
loopback:security:acl principalType ROLE +1ms
loopback:security:acl principalId $everyone +1ms
loopback:security:acl accessType * +1ms
loopback:security:acl permission DENY +2ms
loopback:security:acl with score: +1ms 7495
loopback:security:acl ---ACL--- +1ms
loopback:security:acl model Review +1ms
loopback:security:acl property * +1ms
loopback:security:acl principalType ROLE +1ms
loopback:security:acl principalId $everyone +2ms
loopback:security:acl accessType READ +1ms
loopback:security:acl permission ALLOW +1ms
loopback:security:acl with score: +1ms -1
loopback:security:acl ---Resolved--- +1ms
loopback:security:access-context ---AccessRequest--- +1ms
loopback:security:access-context model Review +2ms
loopback:security:access-context property upsert +1ms
loopback:security:access-context accessType WRITE +1ms
loopback:security:access-context permission DENY +1ms
loopback:security:access-context isWildcard() false +2ms
loopback:security:access-context isAllowed() false +2ms
@mike-aungsan I added a note to https://docs.strongloop.com/display/LB/Accessing+related+models#Accessingrelatedmodels-note.
Please let me know if there's any issue with it.
@crandmck Many Thanks
Are you guys still running into issues? Can I close this?
The design seems undesirable, but as long as the design is documented (and it looks like it is from @crandmck post), I don't see a problem closing it. I worked around it in my project -- no longer an immediate concern.
@jdhiro Sounds good. Please open a new issue if you guys are still running into issues. Better yet, submit a patch and we can go from there.
Yes - i do
sorry for this question but how do I enable the debug view ?
"You can run the application with DEBUG enabled:
$ DEBUG=loopback:security:* node . "
Thanks,
sorry for this question but how do I enable the debug view ?
What do you mean debug view? Run DEBUG=loopback:security:* node . when starting your loopback app.
Hi,
got it working. Thx. U just run the application DEBUG=loopback:security:* node . on commandline .
somebody can help me ? with the same themes ?
if somebody can help me, I send the problem !!!
https://loopback.io/doc/en/contrib/Reporting-issues.html#dont-use-an-issue-to-ask-a-question
Execuse me, but on gitter nobody responds, and I cant resolve the problem, I dont know what I can do !!!
@emazzu @crandmck , i think this problem has come again in the latest repo. @raymondfeng , please look into it. This exposes the security loophole for the app in production.
Refer this thread https://github.com/strongloop/loopback/issues/3518
@emazzu , @crandmck @raymondfeng , this problem is only with custom access token. I reverted to loopback AccessToken model than it started working as intended.
Most helpful comment
I think the core User ACL's are interfering with the ACL's you defined. I recall the following from one of my projects, which overrides all the ACL's: