I'm trying to adapt what I learned from the access control examples into a really simple api that right now has an admin user account that can log in and create a "publication". I am able to log the user in and get an access token, however, when I attempt to post to my publication endpoint I keep getting a 401 Unauthorized
error. I've been stuck on this pretty much all day long. I've been searching and haven't found any info on this issue. Help would be appreciated.
The following is the output when I run
DEBUG=loopback:security:* slc run
:
lopback:security:role isInRole(): admin +10s
loopback:security:access-context ---AccessContext--- +0ms
loopback:security:access-context principals: +0ms
loopback:security:access-context principal: {"type":"USER","id":1} +0ms
loopback:security:access-context modelName publication +0ms
loopback:security:access-context modelId undefined +0ms
loopback:security:access-context property create +0ms
loopback:security:access-context method create +0ms
loopback:security:access-context accessType WRITE +0ms
loopback:security:access-context accessToken: +0ms
loopback:security:access-context id "HtEgTxkSSROIJEfZiB3AObXnWVGGZ0VoFkNDX7jie8HHZh8nHv5vNzGDEgNWiBCb" +0ms
loopback:security:access-context ttl 1209600 +0ms
loopback:security:access-context getUserId() 1 +0ms
loopback:security:access-context isAuthenticated() true +0ms
loopback:security:role isInRole(): $everyone +1ms
loopback:security:access-context ---AccessContext--- +0ms
loopback:security:access-context principals: +0ms
loopback:security:access-context principal: {"type":"USER","id":1} +0ms
loopback:security:access-context modelName publication +0ms
loopback:security:access-context modelId undefined +0ms
loopback:security:access-context property create +0ms
loopback:security:access-context method create +0ms
loopback:security:access-context accessType WRITE +0ms
loopback:security:access-context accessToken: +0ms
loopback:security:access-context id "HtEgTxkSSROIJEfZiB3AObXnWVGGZ0VoFkNDX7jie8HHZh8nHv5vNzGDEgNWiBCb" +1ms
loopback:security:access-context ttl 1209600 +0ms
loopback:security:access-context getUserId() 1 +0ms
loopback:security:access-context isAuthenticated() true +0ms
loopback:security:role Custom resolver found for role $everyone +0ms
loopback:security:role Role found: {"id":1,"name":"admin","created":"2014-12-17T21:02:30.442Z","modified":"2014-12-17T21:02:30.442Z"} +0ms
loopback:security:role Role mapping found: null +2ms
loopback:security:role isInRole() returns: false +0ms
loopback:security:acl The following ACLs were searched: +0ms
loopback:security:acl ---ACL--- +0ms
loopback:security:acl model publication +0ms
loopback:security:acl property * +0ms
loopback:security:acl principalType ROLE +1ms
loopback:security:acl principalId $everyone +0ms
loopback:security:acl accessType * +0ms
loopback:security:acl permission DENY +0ms
loopback:security:acl with score: +0ms 7495
loopback:security:acl ---Resolved--- +0ms
loopback:security:access-context ---AccessRequest--- +0ms
loopback:security:access-context model publication +0ms
loopback:security:access-context property create +1ms
loopback:security:access-context accessType WRITE +0ms
loopback:security:access-context permission DENY +0ms
loopback:security:access-context isWildcard() false +0ms
loopback:security:access-context isAllowed() false +0ms
common/models/publication.json
{
"name": "publication",
"base": "PersistedModel",
"idInjection": true,
"properties": {
"name": {
"type": "string",
"required": true
},
"price": {
"type": "number",
"required": true
}
},
"validations": [],
"relations": {},
"acls": [
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
},
{
"accessType": "WRITE",
"principalType": "ROLE",
"principalId": "admin",
"permission": "ALLOW",
"property": "create"
}
],
"methods": []
}
server/database.json
{
"ids": {
"User": 1,
"AccessToken": 2,
"ACL": 1,
"RoleMapping": 1,
"Role": 1,
"publication": 1,
"account": 3
},
"models": {
"User": {},
"AccessToken": {
"HtEgTxkSSROIJEfZiB3AObXnWVGGZ0VoFkNDX7jie8HHZh8nHv5vNzGDEgNWiBCb": "{\"id\":\"HtEgTxkSSROIJEfZiB3AObXnWVGGZ0VoFkNDX7jie8HHZh8nHv5vNzGDEgNWiBCb\",\"ttl\":1209600,\"created\":\"2014-12-17T21:02:48.103Z\",\"userId\":1}"
},
"ACL": {},
"RoleMapping": {
"1": "{\"id\":1,\"principalType\":\"USER\",\"roleId\":1}"
},
"Role": {
"1": "{\"id\":1,\"name\":\"admin\",\"created\":\"2014-12-17T21:02:30.442Z\",\"modified\":\"2014-12-17T21:02:30.442Z\"}"
},
"publication": {},
"account": {
"1": "{\"fullname\":\"Jane Doe\",\"username\":\"janed\",\"password\":\"$2a$10$PWkG/Y.Jb9w25xtxZwUt/.WOQRZTVgIdKTalGVoCyBE3PoDqD9tK6\",\"email\":\"[email protected]\",\"id\":1}",
"2": "{\"fullname\":\"John Doe\",\"username\":\"johnd\",\"password\":\"$2a$10$dD6r9NmV18R.epAg8.FuvuluQoJfIPMnUw9nGVFivu94PeKp0aKja\",\"email\":\"[email protected]\",\"id\":2}"
}
}
}
Edit:
Some progress, I noticed that my principal id of the role mapping wasn't being set when creating my test data. I have fixed that, however, the role mapping still isn't being found.
Edit 2:
Actually that was indeed the problem, I was testing the wrong end point after I fixed the principalId
. Testing the create endpoint now works.
Turns out when setting up my test data I wasn't setting the principal id properly. I was using
var accounts = [{
username: 'janed',
email: '[email protected]',
fullname: 'Jane Doe',
password: 'secret'
}, {
username: 'johnd',
email: '[email protected]',
fullname: 'John Doe',
password: 'secret'
}];
accounts.forEach(function (account) {
Account.create(account, function(err, result) {
//...
role.principals.create({
principalType: RoleMapping.USER,
principalId: account.id // <-- undefined! should use result.id
});
//...
Once I switch the principal id to use result.id
the ACL began to work.