Closed foxhound87 closed 7 years ago
I have the same issue
It seems related to the auth.authenticate(['jwt', 'local'])
hook.
When I use it in any hook, I always get Unhandled rejection NotAuthenticated: No auth token
.
For example on the authentication
service hooks I have:
app.service('authentication').hooks({
before: {
create: [
auth.hooks.authenticate(['jwt', 'local']),
customJWTPayload(),
],
},
});
then (with session enabled in configs) no error using app().authenticate()
(without arguments) from the client side
using sockets
.
But if I try to call the REST
endpoint POST /authentication
with username/password params I get Missing credentials
:
feathers-authentication:passport:authenticate Authentication strategy 'local' failed +1ms { message: 'Missing credentials' } 400
feathers-errors NotAuthenticated(401): No auth token +0ms
feathers:rest Error in REST handler: `No auth token` +8ms
feathers-authentication:middleware:failure-redirect Clearing old 'feathers-jwt' cookie +2ms
express:router <anonymous> : /authentication?email=email@test.com&password=12345 +10ms
express:router <anonymous> : /authentication?email=email@test.com&password=12345 +0ms
error: (401) Route: /authentication?email=email@test.com&password=12345 - No auth token
info: NotAuthenticated: No auth token
at NotAuthenticated.ExtendableBuiltin (node_modules/feathers-errors/lib/index.js:21:28)
at NotAuthenticated.FeathersError (node_modules/feathers-errors/lib/index.js:96:116)
at new NotAuthenticated (node_modules/feathers-errors/lib/index.js:149:117)
at node_modules/feathers-authentication/lib/hooks/authenticate.js:80:31
at process._tickCallback (internal/process/next_tick.js:103:7)
and if I remove auth.hooks.authenticate(['jwt', 'local'])
from the authentication
hooks, the POST /authentication
works, the token and the cookie are created.
And what's the real purpose of the auth.hooks.authenticate()
hook?
It is used to enable the auth for certain strategy or it require the auth for specified strategies? It's unclear.
Should it be removed from the before.create
of the authentication
service?
I found it in the migration guide
Then if we suppose its purpose is for block some service I do:
authentication
service (so I can able to generate the token/session)then if I generate the token/session from the rest and I use the token to call these restricted service, the access is grant. But the same configuration, from the client side (logged with cookie using app().authenticate() - without arguments), the service are blocked, I get Unhandled rejection NotAuthenticated: No auth token
. It seems it want a token authentication in this case.
@foxhound87 it should be accessToken
not token
that you pass from the client.
Other issues:
The payload contains the user ID only if I call the the services from the client side using the socket. Even the customizeJWTPayload will not work if I call the authorization from the rest.
The verifyJWT
should be in the app.passport
object. But in the client side is missing.
@ekryski thank you for your answer.
I tried both:
.authenticate({ type: 'accessToken', token })
.authenticate({ strategy: 'accessToken', token })
not working.
But now I'm not using the token anymore, I'm using .authenticate()
without params for sessions.
Still errors: NotAuthenticated: No auth token
.
@foxhound87 the reason you are getting unhandled rejection is because the auth client is trying to authenticate automatically on initialization. @marshallswain added this for SSR but I need to tidy it up a bit so that it doesn't just throw an error. It has nothing to do with the server side.
Your client should be .authenticate({ strategy: 'jwt', accessToken: token })
.
Server side should be:
app.service('authentication').hooks({
before: {
create: [
auth.hooks.authenticate(['jwt', 'local'])
],
},
});
I have no auth token when I log in with rest instance of feathers and I use socket instance later.
@bertho-zero, the feathers client only works with one provider at a time, so you'd have to have two app instances to switch providers. It could still work, but each app would have to authenticate individually.
Ah ok, I was absolutely looking to share the token between the 2 instances. Why not try to take it to the localStorage if it is there?
@bertho-zero it will do that but the problem is that since you are authenticating with effectively 2 different apps the tokens will be different. You'd likely want to give one a different localstorage key name. Otherwise they would overwrite each other every time you successfully authenticate.
@foxhound87 did you get your stuff working? We just pushed a bunch of updates and bug fixes so if you are still having issues you might want to try moving to the official 1.0.x and the latest version of all plugins.
With feathers-rest , setting up the client to look for the token in localStorage will work without having to call feathersClient.authenticate()
. Since socket connections are flagged as authenticated on the server side, you'll have to for sure call feathersClient.authenticate()
with the instance that uses feathers-socketio.
@ekryski I authenticate with a single instance, there is no problem with the token itself, but I would like to share the token between the two instances. For that it would be enough that the client's hook would look in the localStorage no?
@marshallswain If I use the socket everything works, it's just for practical questions that I preferred to see the query, it's less practical with socket.
@bertho-zero are you talking about the logs? I'm getting no logs on server terminal when calling a service from the feathers-client with socket, the logs are shown only from the rest api (I'm using postman). I mean when not using DEBUG.
@ekryski I updated all feathers dependencies:
"feathers": "^2.0.3",
"feathers-authentication": "^1.0.2",
"feathers-authentication-client": "^0.1.6",
"feathers-authentication-jwt": "^0.3.0",
"feathers-authentication-local": "^0.3.2",
"feathers-configuration": "^0.4.1",
"feathers-errors": "^2.5.0",
"feathers-hooks": "^1.7.0",
"feathers-hooks-common": "^2.0.2",
"feathers-mongoose": "^3.6.1",
"feathers-permissions": "^0.1.1",
"feathers-rest": "^1.5.2",
"feathers-socketio": "^1.4.2",
Using the cookie on the feathers configs and authenticate()
without params: first of all, the cookie is never set in the browser, from the server side I cannot access the cookie in the request, and the authenticate()
without params is always failing on the server side.
Anyway, I don't think that is the way to go, I think that the API Server should be completely stateless, accessible with the JWT
token strategy or the local
(username/password) strategy.
The SSR Server
(which will call the same feathers-client
apis both on client and server), instead, should be stateful, should handle the JWT token in the cookie, and proxy all request to the API Server
using the JWT strategy and the feathers-client authenticate({ strategy: 'jwt', accessToken: token })
both on client side and server side. I Think every request to the API Server should be authenticated before calling a service (both on client side and server side).
As feathers is not able to set a cookie properly (even with the latest versions), I disabled it on the feathers config and implemented myself on the SSR Server (some workaround was needed but I'm now able to authenticate with that process).
Now assume we have a restricted service using the auth.authenticate(['jwt', 'local']),
hook.
It seems that after the logout is done on the browser, and I reload the page, on the server side I don't get anymore the cookie with the jwt, the authentication is not done - and it's ok - but the service request is served (data is retrieved, the auth hook is bypassed, no auth error thrown!!!).
How feathers keeps the subsequent requests authenticated if the feathers cookie is not present in the request?
To avoid this behavior, I have to force logout with app.logout()
on the server side on every request if a cookie/token is not present.
Other Issues:
I'm not able to use local stragety from the REST
It's like the jwt and local strategies on the same endpoint are overlapping, for example, if I switch the order of the authenticate hook array to ['local', 'jwt'] says Missing credentials
(even if the username/password params are provided).
Otherwise - using ['jwt', 'local'] - calling POST /authentication with username/password params will throw always: No auth token
.
Maybe the required headers or params are changed with the latest updates? Would be nice to have a complete documentation to clarify all params for the requests, right now I'm getting all the info around the github issues because the current state of the doc is not sufficiently comprehensive (maybe for me as Italian is more difficult, but sometimes is a matter of lack of info).
I setup a customJWTPayload
in the before.create
hook of the authentication
service (as shown in the migration guide). From the feathers-client calls all services gets the additional ID data (which was set by customJWTPayload
with hook.params.user.id
) even if the customJWTPayload
is not present on others services hooks. I think this is not so good behavior to mix data from the hooks of authentication
service into other services. In fact, if I call a service from the REST I don't get the extra data because the authentication
service and customJWTPayload
are never executed on a single REST call (Which I initially thought was the wrong behavior). Even in this case, like the force logout() issue, seems like feathers keeps it's own internal state when using the feathers-client
. (this is tested using the jwt
strategy - not tested with feathers cookies config as I still cant make it working).
I hope this can help you to understand better the needs of the users or improve the feathers experience, as we don't know how feathers works under the hood and if some behaviors are correct and works as expected.
Thank You.
@foxhound87 we fixed some cookie-related bugs, yesterday. The latest versions of all packages should hopefully set cookies properly.
As for the first bullet point, where the order of the strategies matters, that's a PassportJS issue. It's a little annoying because all of the strategies actually do run, but when they all fail, only the error for the first one in the list is returned.
If you have all of the latest packages, please post an example repo. I had one ready for debugging OAuth login and it made it much easier to get a fixed release out.
@marshallswain
https://bitbucket.org/foxhound87/rfx-stack-ssr-test/src/master
https://bitbucket.org/foxhound87/rfx-stack-ssr-test/src/ssr-cookie
The master branch is with the feathers cookie config (not working so well).
The ssr-cookie branch is my attempt with my own implementation of the cookie on the SSR server (which is working pretty well)
Another issue is that app.logout() is never resolved, and this was causing unexpected behaviors on the server side.
@foxhound87 is that the case in the example you posted above? We merged a fix for that which should have been published yesterday.
@marshallswain yes, I'm using proper git comments to help you to fix these issues, I shared this repo with @daffl on slack too some days ago.
https://bitbucket.org/foxhound87/rfx-stack-ssr-test/branch/ssr-cookie
I see that there was a related merge 2 days ago, but maybe is not completely fixed,
I get Warning: .then() only accepts functions but was passed: [object Undefined]
And from the feathers-client
authenticate()
I'm getting Warning: a promise was created in a handler but was not returned from it
. I see these warnings using bluebird
, I suggest to use it to highlight some strangeness, I think it can ensure a more stable implementation of promises.
^ @foxhound87 regarding that warning from Bluebird. Some promises are intentionally created that way but I also have a fix coming for the error around automatic authentication throwing an unhandled promise rejection error.
As for the first bullet point, where the order of the strategies matters, that's a PassportJS issue. It's a little annoying because all of the strategies actually do run, but when they all fail, only the error for the first one in the list is returned.
This is now partially resolved. If you specify the strategy on the client the server will only attempt to use that one. It won't run through them all now and will return the proper error.
Another issue is that app.logout() is never resolved
This has been fixed in https://github.com/feathersjs/feathers-authentication/pull/369.
@ekryski I authenticate with a single instance, there is no problem with the token itself, but I would like to share the token between the two instances. For that it would be enough that the client's hook would look in the localStorage no?
@bertho-zero it should do that yes. If that is still an issue maybe create a separate issue with a simple example that demonstrates that problem and we'll see if we can fix it up! 😄
Honestly, I'm getting a bit lost in this thread as to what the actual issues are anymore. I'm going to close this issue. @foxhound87 please open new ones for each individual issue you are having with a simple reproducible example and feel free to copy-paste the relevant info from this thread for each one. Your RFX stack stuff is awesome but it's a lot to sift through to figure out what could be the issue and it will be much faster to solve any problems if we can quickly reproduce the issue. 😄
Hello, is it normal to use client.authenticate() every time I use a service? I have to add client.authenticate() everytime I use a service.
Should
strategy: 'jwt'
work onv.1.0.0-beta-2
?NOT working:
working (as on older version):
working:
Module versions
NodeJS version:
v7.2.0
Operating System:
MacOS Sierra
Browser Version:
Chrome 54.0.2840.98 (64-bit)
Module Loader:
webpack 2.1.0-beta.27