How do you get the current user/token payload in hooks?
In express/passport you would serializeUser the stuff you want to keep around like user id and roles and then use req.user anywhere to get the payload in question.
Is there such a thing in feathers? The only thing I'm seeing would be to call app.passport.verifyJWT in a hook after auth.hooks.authenticate and populate this myself. But I feel like I'm missing something.
Thanks!
Once it ran through the authenticate hook, the entity will be populated in hook.params.user by default (or with the entity name set in the options).
Found the issue thanks
another question in link with this..
how could I do an api that work with and without auth?
like if I call auth.hooks.authenticate('jwt') and there no auth token it will return an error.
but I would instead want to still validate the token but then make a hook that check if hook.params.user is there or not, and depending on this it would either work or return an error if you try doing admin stuff like setting a role.
Basically I want to have the same users api for the front and the admin. If you are logged in as admin you have permission to edit the roles of the user your creating, but if you're not logged in we just assume you're a visitor creating an account for himself and return an error you if you try to give yourself an admin role.
You can use mixed auth endpoints as described in docs here : https://docs.feathersjs.com/guides/auth/recipe.mixed-auth.html#set-up-a-mixed-auth-endpoint
Oh I see.. thanks!
This doesn't seem to be working that well actually.
When authenticate() is inside an iff hook it no longer populate params.user.
It's there, but it's an empty object.
I even created an api from scratch with feathers-clito be sure and the issue is still there.
inside app.hooks.js
This will return the user
before: {
all: [
authenticate('jwt'),
hook => {
console.log(hook.params.user);
}
]
},
this will return an empty user object {}
before: {
all: [
commonHooks.iff(
hook => hook.params.headers.authorization,
authenticate('jwt')
),
hook => {
console.log(hook.params.user);
}
]
},
Can you post the decoded JWT (paste into https://jwt.io/) here? My guess is that your userId is not being set (related: https://github.com/feathersjs/feathers-authentication/issues/392)
{
"userId": "59760731bd4ea755301ed80f",
"iat": 1503004672,
"exp": 1503091072,
"aud": "https://yourdomain.com",
"iss": "feathers",
"sub": "anonymous"
}
I does work outside the iff(), so it seem like the auth is working.
I don't think it's hook.params.header. As the linked article says, you probably want to check for hook.params.token.
Nope still doing the same, I don't even have the that value in my hook.params actually.
But headers.authorization is there.
I haven't setup the auth initially, it's a boilerplate we found.. so I don't know exactly what could be different to make it not be inside params.token, but I compared with the stuff that feathers-cli generate and it's the same. Also like I said the auth work outside the iff.
I'm a bit lost on what it could be.
content of hook.params
{ query: {},
provider: 'rest',
headers:
{ host: 'localhost:3030',
connection: 'keep-alive',
authorization: 'eyJhbGciOiJIUzI1NiIsInR5cCI6ImFjY2VzcyJ9.eyJ1c2VySWQiOiI1OTc2MDczMWJkNGVhNzU1MzAxZWQ4MGYiLCJpYXQiOjE1MDMwMjIzNTMsImV4cCI6MTUwMzEwODc1MywiYXVkIjoiaHR0cHM6Ly95b3VyZG9tYWluLmNvbSIsImlzcyI6ImZlYXRoZXJzIiwic3ViIjoiYW5vbnltb3VzIn0.dYKBjJrgDiYyI7AK6z5ZzdDKbVuH6467ha49vnsJz60',
'postman-token': '1e8bd6d3-c154-3ece-ec36-c95cadf3f82e',
'cache-control': 'no-cache',
'x-postman-interceptor-id': 'd0e4d5d9-f4d4-02f8-adb1-3fd1862262e2',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36',
'content-type': 'application/json',
accept: '*/*',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-US,en;q=0.8,fr;q=0.6',
cookie: 'liveagent_oref=; liveagent_vc=2; liveagent_ptid=50a2336d-0156-492c-bb2f-1a365d20608e; country=CA; io=DoT3LrIfBZe3Sr0dAAAA; feathers-jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6ImFjY2VzcyJ9.eyJ1c2VySWQiOiI1OTc2MDczMWJkNGVhNzU1MzAxZWQ4MGYiLCJpYXQiOjE1MDMwMjIzNTMsImV4cCI6MTUwMzEwODc1MywiYXVkIjoiaHR0cHM6Ly95b3VyZG9tYWluLmNvbSIsImlzcyI6ImZlYXRoZXJzIiwic3ViIjoiYW5vbnltb3VzIn0.dYKBjJrgDiYyI7AK6z5ZzdDKbVuH6467ha49vnsJz60' },
cookies:
{ liveagent_oref: '',
liveagent_vc: '2',
liveagent_ptid: '50a2336d-0156-492c-bb2f-1a365d20608e',
country: 'CA',
io: 'DoT3LrIfBZe3Sr0dAAAA',
'feathers-jwt': 'eyJhbGciOiJIUzI1NiIsInR5cCI6ImFjY2VzcyJ9.eyJ1c2VySWQiOiI1OTc2MDczMWJkNGVhNzU1MzAxZWQ4MGYiLCJpYXQiOjE1MDMwMjIzNTMsImV4cCI6MTUwMzEwODc1MywiYXVkIjoiaHR0cHM6Ly95b3VyZG9tYWluLmNvbSIsImlzcyI6ImZlYXRoZXJzIiwic3ViIjoiYW5vbnltb3VzIn0.dYKBjJrgDiYyI7AK6z5ZzdDKbVuH6467ha49vnsJz60' }
}
and here are the auth settings
auth: {
secret: '*****',
cookie: {
enabled: true,
httpOnly: false,
maxAge: ONE_DAY,
secure: process.env.NODE_ENV === 'production'
},
facebook: {
path: '/auth/facebook',
clientID: '*****',
clientSecret: '*****',
permissions: {
authType: 'rerequest'
},
scope: ['public_profile', 'email'],
profileFields: ['id', 'displayName', 'photos', 'email', 'first_name', 'last_name', 'age_range'],
accessTokenField: 'accessToken'
}
},
and here the boilerplate in case that could help. I haven't changed much regarding the auth, beside making it use mongoose instead and trying to move the auth inside an app hook and make it optional : https://github.com/bertho-zero/react-redux-universal-hot-example
Think I found it.. seem like hook won't throw error even if you literally put gibberish in there.
The app will ignore the hook and continue like nothing happened.
is that a known issue/limitation?
You mean something like
commonHooks.iff(
hook => hook.fhkdshf.fjdslkfjdslk
authenticate('jwt')
),
Won't do anything?
no it was something like this inside a file
export function isAdmin(hook) {
console.log('test');
FAOISHODIHAS
console.log('test2');
return hook.params.user && hook.params.user.roles && _.includes(hook.params.user.roles, config.get('feathers.adminRoles'));
}
and then in the other file I had
import { isAdmin } from 'hooks';
iff(isNot(isAdmin),
restrictToOwner({ ownerField: '_id' })
)
It would log the first test, but not test2 and then the app would just continue and break the population of the user in the auth, since the internal get would not resolve I guess.
But I think now that It's because of the way that the hooks file is setup inside that boilerplate we used.
https://github.com/bertho-zero/react-redux-universal-hot-example
if you look at api/hooks/index.js my hook was in there.
and then look at /api/services/users/hooks.js
The way the other file is loaded
import { validateHook } from 'hooks';
like it was a module instead of something like ../../hooks
I don't know enough about es6 yet to figure out what black magic make this work, but it seem to be the root of the issue.
That index.js won't reload the app if you save it, won't throw eslint error even tho the way the export is made is wrong, won't work if you ctrl+click on the import call in VS Code and it also won't ouput an error if you put gibberish in it.
Do you know what make this work?
But even if I bring that function back in the same file as the hook it still won't throw any error. I don't get this.
function isAdmin(hook) {
return asdfadsfasdfasdf
}
iff(isNot(isAdmin),
restrictToOwner({ ownerField: '_id' })
)
no error, it just ignore the hook and continue..
Make it pretty hard to debug hooks.
If I try to reproduce this in the feathers-chat everything works as expected. You may have to bring the issue up to the author of the boilerplate since it seems it has something to do with that (potentially old module versions or the way that error handling is set up).
Alright, thanks for the help!
Maybe this is on me, but I really had to dig to find the info here about hook.params.user. It might improve the doc if that were more prominent somewhere. Just a thought...
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue with a link to this issue for related bugs.
Most helpful comment
This doesn't seem to be working that well actually.
When
authenticate()is inside aniffhook it no longer populateparams.user.It's there, but it's an empty object.
I even created an api from scratch with
feathers-clito be sure and the issue is still there.inside
app.hooks.jsThis will return the user
this will return an empty user object {}