Closed subodhpareek18 closed 7 years ago
@zusamann, please post the version numbers of each of the imported modules.
Latest ones on NPM I think, since I just did a npm i -S ......
"feathers": "^2.0.3",
"feathers-authentication": "^0.7.11",
"feathers-authentication-jwt": "^0.3.1"
@marshallswain
If you are using feathers-authentication-<strategy>
you need to explicitly install feathers-authentication@^1.0.0
.
But as you can see above @daffl I did two attempts, with and without feathers-authentication-<strategy>
got the same error in both cases.
Ok here I am using "feathers-authentication": "^1.0.2"
and getting a slightly different error.
import feathers from 'feathers';
import rest from 'feathers-rest';
import bodyParser from 'body-parser';
import auth from 'feathers-authentication';
import jwt from 'feathers-authentication-jwt';
import sequelize from 'feathers-sequelize';
const db = require('./models');
const init = () => {
const app = feathers();
app.configure(rest());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.configure(auth({ secret: 'my-secret' }));
app.configure(jwt());
Object.keys(db.sequelize.models)
.map(key =>
app.use(`/rest/${key}`, sequelize({
Model: db[key],
paginate: {
default: 5,
max: 25
}
}))
);
app.listen(3030);
};
export const run = () => init();
D:\code\playground\core-playground\feathers\node_modules\feathers-authentication-jwt\lib\verifier.js:32
throw new Error('options.service does not exist.\n\tMake sure you are passing a valid service path or service instance and it is initialized before feathers-authentication-jwt.');
^
Error: options.service does not exist.
Make sure you are passing a valid service path or service instance and it is initialized before feathers-authentication-jwt.
@zusamann, check out the default options for the jwt plugin here: https://github.com/feathersjs/feathers-authentication-jwt#default-options. You probably need to fix the service
attribute (Or create a user service if you haven't, yet.)
Yes you are right @marshallswain this error is not thrown anymore. I had to add the following:
import memory from 'feathers-memory';
// ...
// ...
app.use('/users', memory());
Now I was looking to finally use the authentication on all of my endpoints which I'm generating procedurally like so:
Object.keys(db.sequelize.models).map(key =>app.use(`/rest/${key}`, sequelize({ Model: db[key] })));
So I added the following:
app.service('authentication').hooks({
before: {
all: [
auth.hooks.authenticate('jwt')
]
}
});
But it is generating the following error:
D:\code\playground\core-playground\feathers\server.js:64
app.service('authentication').hooks({
^
TypeError: app.service(...).hooks is not a function
at init (D:/code/playground/core-playground/feathers/server.js:32:33)
@zusamann you probably just need to install the hooks plugin: https://github.com/feathersjs/feathers-hooks#quick-start
But not import it anywhere?
Use the quick start I just linked.
Right again @marshallswain, had to add the following to the code:
import hooks from 'feathers-hooks';
// ...
// ...
app.configure(hooks());
And modify the service creation so the hooks are added over the keys.map.
Object.keys(db.sequelize.models)
.map(key =>
app.use(`/rest/${key}`, sequelize({
Model: db[key],
paginate: {
default: 5,
max: 25
}
}))
.hooks({
before: {
all: [
auth.hooks.authenticate(['jwt'])
]
}
})
);
Thank you so much for your help.
I was wondering if the docs could be updated to reflect some of the nuances covered above. Of placing a users service and configuring hooks, etc.
The Auk docs will contain all of the information for feathers-authentication@1.0.x. Just out of curiosity, why did you decide to install feathers-authentication-jwt? How did you discover it? I ask because the current release of feathers-authentication on npm already includes that functionality. We decided to implement auth plugins in the upcoming release (which you've just upgraded to using)
I have actually just recently discovered feathers, like 1-2 days ago and have just been reading all the repos, documentation, changelog, issues I could find. Learned about auk release there itself.
I just started doing some PoCs today, hence hitting all these confusions and errors.
I see. We have big docs updates underway as the final part of the Auk release, so the confusion will disappear, shortly.
Glad to hear that, do you think the already out releases of Auk like the new authentication plugin are stable enough to use in production? Cause I'm really looking forward to using all of what I can find.
feathers-permissions
will see some changes. Everything else is stable.
Great! Looking forward to it.
In the meantime, using feathers-authentication@1.0.x, you'll probably want to familiarize yourself with the old authentication hooks. Some might work, but others you might have to modify. https://github.com/feathersjs/feathers-legacy-authentication-hooks
Back again, having trouble setting up the client side usage.
/**
server.js
"feathers": "^2.0.3",
"feathers-authentication": "^1.0.2",
"feathers-authentication-jwt": "^0.3.1",
**/
import feathers from 'feathers';
import rest from 'feathers-rest';
import bodyParser from 'body-parser';
import auth from 'feathers-authentication';
import jwt from 'feathers-authentication-jwt';
import hooks from 'feathers-hooks';
import errorHandler from 'feathers-errors/handler';
import memory from 'feathers-memory';
import sequelize from 'feathers-sequelize';
import cors from 'cors';
import socketio from 'feathers-socketio';
const db = require('./models');
const init = () => {
const app = feathers();
app.use(cors());
app.configure(socketio({
wsEngine: 'uws'
}));
app.configure(rest());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.configure(hooks());
app.configure(auth({ secret: 'secret' }));
app.configure(jwt());
app.use('/users', memory());
Object.keys(db.sequelize.models)
.map(key => {
app.use(`/db/${key}`, sequelize({
Model: db[key],
paginate: {
default: 10,
max: 25
}
}));
app.service(`/db/${key}`).hooks({
before: {
all: [
auth.hooks.authenticate(['jwt'])
]
}
});
});
app.use(errorHandler());
app.listen(3030);
};
export const run = () => init();
/**
client.js
"feathers-client": "^1.9.0",
**/
import feathers from 'feathers-client';
// import io from 'socket.io-client';
import axios from 'axios';
const host = 'http://localhost:3030';
const client = feathers()
// .configure(feathers.socketio(io(host)))
.configure(feathers.rest(host).axios(axios)) // tried both clients, explained below
.configure(feathers.hooks())
.configure(feathers.authentication({
storage: window.localStorage
}));
export default client;
/**
App.js (client side)
**/
class App extends Component {
constructor() {
super()
this.state = { films: [] }
client.authenticate({
type: 'token',
endpoint: '/authentication' // without this the default post is to /auth/token, a bit confusing
})
.then(res => {
console.log(res) // get a token with rest client, nothing comes with io client
window.localStorage
.setItem('feathers-jwt', res.accessToken); // tried without this first, that didnt work either
client.service('/db/film').get(1).then(console.log) // errors out, 401 unautho...
})
.catch(rej => console.log(rej))
//...
So having trouble setting the fetched token in rest client, and with io client not getting any token at all. Both resulting in 401s. My thinking is it might be due to using incompatible server and client side auth libs.
On further exploration, this works on with the rest client, but doesn't with the io client. Don't even get an error. Which tells me there needs to be done something entirely different with the io client.
/**
App.js (client side)
**/
class App extends Component {
constructor() {
super()
this.state = { films: [] }
client.authenticate({
type: 'token',
endpoint: '/authentication'
})
.then(res => {
client.set('token', res.accessToken)
client.service('/db/film').get(1).then(console.log)
})
.catch(rej => console.log(rej))
//...
@zusamann Looks like you're still using the old version of the auth client. You can upgrade by importing the new client plugin:
import auth from 'feathers-authentication-client'
...
.configure(auth({
storage: window.localStorage
}));
I'm actually not using the individual clients. Rather "feathers-client": "^1.9.0"
, you suppose it's better to use broken up clients?
Nah. You can keep everything else the same. Just change the auth plugin part.
Ok will try that and revert
/**
"feathers-authentication-client": "^0.1.7",
"feathers-client": "^1.9.0",
**/
// client.js
import feathers from 'feathers-client';
import auth from 'feathers-authentication-client';
// import io from 'socket.io-client';
import axios from 'axios';
const host = 'http://localhost:3030';
const client = feathers()
// .configure(feathers.socketio(io(host)))
.configure(feathers.rest(host).axios(axios))
.configure(feathers.hooks())
.configure(auth({
storage: window.localStorage
}));
export default client;
// App.js
class App extends Component {
constructor() {
super()
client.authenticate({
type: 'token',
endpoint: '/authentication'
})
.then(console.log)
.catch(console.error)
}
render() {
// ...
Getting this error in my browser console twice.
base64_url_decode.js:14Uncaught (in promise) TypeError: Cannot read property 'replace' of undefined
at module.exports (base64_url_decode.js:14)
at module.exports (index.js:12)
at passport.js:266
@marshallswain
The API has changed. You now need to specify the strategy
, which refers to the name of the PassportJS strategy being used on the server. In the case of feathers-authentication-jwt
, the name is just jwt
. You can see, from looking at the expected params in the README.md: https://github.com/feathersjs/feathers-authentication-jwt#expected-request-data, that you also need to provide an accessToken
property, which is the actual JWT.
client.authenticate({
type: 'jwt',
accessToken: window.localStorage.getItem('feathers-jwt')
})
A shortcut to the above would be to simply call client.authenticate()
, with no params. The above and below are functionally equivalent.
client.authenticate()
If there is a token in storage, it will attempt to login. If not, it will return an error that no token was found.
Actually I tried with all the various combinations of params. And just now I tried the below again.
client.authenticate()
.then(console.log)
.catch(console.error)
Tried setting the token manually too
client.authenticate()
.then(res => window.localStorage.setItem('feathers-jwt', res.accessToken))
.catch(console.error)
Getting the same error as above on both.
It's actually erroring out even before the .authenticate()
is being made. I commented out all code in my App.js
except for import client from './client';
and getting an error there itself.
So there must be some thing wrong with this:
/**
"feathers-authentication-client": "^0.1.7",
"feathers-client": "^1.9.0",
**/
// client.js
import feathers from 'feathers-client';
import auth from 'feathers-authentication-client';
// import io from 'socket.io-client';
import axios from 'axios';
const host = 'http://localhost:3030';
const client = feathers()
// .configure(feathers.socketio(io(host)))
.configure(feathers.rest(host).axios(axios))
.configure(feathers.hooks())
.configure(auth({
storage: window.localStorage
}));
export default client;
Hmmm... Try switching to the individual modules.
feathers/client
feathers-hooks
doesn't need to be changed.feathers-rest/client
feathers-authentication-client
/**
"feathers": "^2.0.3",
"feathers-authentication-client": "^0.1.7",
"feathers-hooks": "^1.7.1",
"feathers-rest": "^1.6.0",
**/
import feathers from 'feathers/client';
import hooks from 'feathers-hooks';
import rest from 'feathers-rest/client';
import auth from 'feathers-authentication-client';
import axios from 'axios';
const host = 'http://localhost:3030';
const client = feathers()
.configure(rest(host).axios(axios))
.configure(hooks())
.configure(auth({
storage: window.localStorage
}));
export default client;
Same error sadly.
base64_url_decode.js:14Uncaught (in promise) TypeError: Cannot read property 'replace' of undefined
at module.exports (base64_url_decode.js:14)
at module.exports (index.js:12)
at passport.js:266
There's something else going on here. What's the path to passport.js in your project or node_modules? There is no reference to the replace
function anywhere in the passport.js that's included in feathers-authentication-client
. Which version do you have installed?
Oh you posted that above. Just need the path to that file, then.
I thought it was this file: https://github.com/feathersjs/feathers-authentication-client/blob/master/src/passport.js
But it's not in that file, directly. Can you trace it down?
Looks like it's the dep jwt-decode
// ./~/jwt-decode/lib/base64_url_decode.js
Can you post your code in a repo that I can pull?
Yes sure, give me few minutes
@marshallswain here is the code: https://github.com/zusamann/feathers-poc
There are two folders client-side
and server-side
you need to go to both and do an npm i
& npm start
. As for the database I'm using postgres with the sample db I found here http://www.postgresqltutorial.com/load-postgresql-sample-database/
In order to connect with your own db you'll have to change line 15 in server-side/models/index.js
let sequelize = new Sequelize('postgres://postgres:password@localhost:5432/dvdrental', databaseOptions);
You can alternatively load some completely different db and models as you see fit.
Were you able to have a go? In any case what would be your suggestion @marshallswain @daffl , should I downgrade to a pre 1.0 feathers-authentication on my server and try there?
Trying this out right now.
@zusamann I made a PR to your repo. https://github.com/zusamann/feathers-poc/pull/1
Both local and jwt auth should work, now. You'll need to integrate the client, but it should be trivial, now.
I didn't import the Postgres database, and just focused on getting auth working.
@marshallswain sorry but I'm getting the same error on the client side. Can you have a look at the client side code? It's in the client-side
folder.
base64_url_decode.js:14Uncaught (in promise) TypeError: Cannot read property 'replace' of undefined
at module.exports (base64_url_decode.js:14)
at module.exports (index.js:12)
at passport.js:266
Also didn't really understand the change you made to thee server side code. I mean apart from including the local auth strategy, it seems like you replaced memory with nedb but not much else for jwt auth. The auth was working fine on the server side earlier as well which is why I had closed the issue earlier. But at that point I was simply using POSTMAN, this time I was looking to use the client.
Also this change in server.js actually stopped my server from running as the file bootstrap.js expects a function run to work, so not sure how you were running the server. That's a minor point though.
-- export const run = () => init();
++ module.exports = () => init();
@zusamann
Can you have a look at the client side code? It's in the client-side folder.
I'll take a look later today.
Also didn't really understand the change you made to thee server side code.
The most important part was registering the hook on the /authentication
service. None of the auth plugins will work without that.
@zusamann I think you might have a problem with your environment. I don't get the error you pasted, above. I just submitted another PR where I got auth working. Try removing your node_modules folders on the client and reinstall. It probably shouldn't matter, but I installed modules using Yarn.
Here's the PR: https://github.com/zusamann/feathers-poc/pull/2
The most important part was registering the hook on the /authentication service. None of the auth plugins will work without that.
@marshallswain actually I was using /authentication
to generate the tokens and using them to call the /db/films
end point which was authenticated. This was an intended behavior actually for my customer facing landing page where the freely generated token is then used to authenticate lots of calls to the backend.
As for the server change, I was just using node server
to run the code after I switched back to CommonsJS.
Try removing your node_modules folders on the client and reinstall. It probably shouldn't matter, but I installed modules using Yarn.
Ok trying, though to be honest I did a clean install in a separate folder just to be sure when I pushed this code on github.
As for the server change, I was just using node server to run the code after I switched back to CommonsJS
Okay
I was using /authentication to generate the tokens and using them to call the /db/films end point. This was an intended behavior actually for my customer facing landing page where the freely generated token is then used to authenticate lots of calls to the backend.
I see. Let me try this.
I just tried this and got no errors. I think we're back to this being an environment issue.
I think you might have a problem with your environment. I don't get the error you pasted, above. I just submitted another PR where I got auth working. Try removing your node_modules folders on the client and reinstall. It probably shouldn't matter, but I installed modules using Yarn.
Just tried again with a rm -rf node_modules
and a yarn install
inside the client-side
folder and tried again. Same error actually, coming from the jwt-decode
lib. Did you use the actual code in the client-side
folder?
Also just to be clear the server side implementation was working as intended. A call to the open /authentication
endpoint gave me a token which successfully let me call the other authenticated endpoints /db/...
.
It's just the client-side
code is giving troubles.
Do you think it could be a windows issue? Should I try to setup the entire thing in vagrant or something?
I see you have pushed another PR, let me try with that once.
Here's my code running on windows 10.
Have also tried this:
Getting this error in both cases: